[macruby-changes] [3117] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon Dec 14 17:42:49 PST 2009


Revision: 3117
          http://trac.macosforge.org/projects/ruby/changeset/3117
Author:   lsansonetti at apple.com
Date:     2009-12-14 17:42:46 -0800 (Mon, 14 Dec 2009)
Log Message:
-----------
emit dwarf metadata at compilation time and use it to establish backtracing later at runtime

Modified Paths:
--------------
    MacRuby/trunk/bridgesupport.cpp
    MacRuby/trunk/compiler.cpp
    MacRuby/trunk/compiler.h
    MacRuby/trunk/llvm.h
    MacRuby/trunk/vm.cpp

Modified: MacRuby/trunk/bridgesupport.cpp
===================================================================
--- MacRuby/trunk/bridgesupport.cpp	2009-12-15 01:33:42 UTC (rev 3116)
+++ MacRuby/trunk/bridgesupport.cpp	2009-12-15 01:42:46 UTC (rev 3117)
@@ -13,6 +13,7 @@
 #include <llvm/Instructions.h>
 #include <llvm/ModuleProvider.h>
 #include <llvm/Intrinsics.h>
+#include <llvm/Analysis/DebugInfo.h>
 #include <llvm/ExecutionEngine/JIT.h>
 #include <llvm/PassManager.h>
 #include <llvm/Target/TargetData.h>

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2009-12-15 01:33:42 UTC (rev 3116)
+++ MacRuby/trunk/compiler.cpp	2009-12-15 01:42:46 UTC (rev 3117)
@@ -8,6 +8,10 @@
 
 #define ROXOR_COMPILER_DEBUG 	0
 
+#if !defined(DW_LANG_Ruby)
+# define DW_LANG_Ruby 0x15 // TODO: Python is 0x14, request a real number
+#endif
+
 #include "llvm.h"
 #include "ruby/ruby.h"
 #include "ruby/encoding.h"
@@ -17,6 +21,7 @@
 #include "vm.h"
 #include "compiler.h"
 #include "objc.h"
+#include "version.h"
 
 extern "C" const char *ruby_node_name(int node);
 
@@ -26,6 +31,9 @@
 
 RoxorCompiler::RoxorCompiler(void)
 {
+    assert(RoxorCompiler::module != NULL);
+    debug_info = new DIFactory(*RoxorCompiler::module);
+
     fname = "";
     inside_eval = false;
 
@@ -58,7 +66,6 @@
     return_from_block = -1;
     return_from_block_ids = 0;
     ensure_pn = NULL;
-    current_scope = NULL;
 
     dispatcherFunc = NULL;
     fastPlusFunc = NULL;
@@ -737,10 +744,11 @@
 	    (module->getOrInsertFunction("rb_vm_dispatch", ft));
     }
 
-    assert(current_scope != NULL);
-    current_scope->dispatch_lines.push_back(current_line);
-
-    return compile_protected_call(dispatcherFunc, params);
+    Instruction *insn = compile_protected_call(dispatcherFunc, params);
+    if (fname != NULL) {
+	debug_info->InsertStopPoint(debug_compile_unit, current_line, 0, bb);
+    }
+    return insn;
 }
 
 Value *
@@ -3096,10 +3104,6 @@
 		Function *f = Function::Create(ft, GlobalValue::ExternalLinkage,
 			function_name, module);
 
-		RoxorScope *old_current_scope = current_scope;
-		current_scope = new RoxorScope(fname);
-		scopes[f] = current_scope;
-
 		BasicBlock *old_rescue_invoke_bb = rescue_invoke_bb;
 		BasicBlock *old_rescue_rethrow_bb = rescue_rethrow_bb;
 		BasicBlock *old_entry_bb = entry_bb;
@@ -3110,6 +3114,13 @@
 		rescue_rethrow_bb = NULL;
 		bb = BasicBlock::Create(context, "MainBlock", f);
 
+		DISubprogram old_debug_subprogram = debug_subprogram;
+		debug_subprogram = debug_info->CreateSubprogram(
+			debug_compile_unit, f->getName(), f->getName(),
+			f->getName(), debug_compile_unit, nd_line(node),
+			DIType(), f->hasInternalLinkage(), true);
+		debug_info->InsertSubprogramStart(debug_subprogram, bb);
+
 		std::map<ID, Value *> old_lvars = lvars;
 		lvars.clear();
 		Value *old_self = current_self;
@@ -3360,7 +3371,7 @@
 		current_self = old_self;
 		current_var_uses = old_current_var_uses;
 		running_block = old_running_block;
-		current_scope = old_current_scope;
+		debug_subprogram = old_debug_subprogram;
 
 		return cast<Value>(f);
 	    }
@@ -5300,6 +5311,19 @@
     return NULL;
 }
 
+void
+RoxorCompiler::set_fname(const char *_fname)
+{
+    if (fname != _fname) {
+	fname = _fname;
+
+	if (fname != NULL) {
+	    debug_compile_unit = debug_info->CreateCompileUnit(DW_LANG_Ruby,
+		    fname, "", RUBY_DESCRIPTION, false, false, "");
+	}
+    }
+}
+
 Function *
 RoxorCompiler::compile_main_function(NODE *node)
 {

Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2009-12-15 01:33:42 UTC (rev 3116)
+++ MacRuby/trunk/compiler.h	2009-12-15 01:42:46 UTC (rev 3117)
@@ -27,14 +27,6 @@
 #define DEFINED_SUPER	6
 #define DEFINED_METHOD	7
 
-class RoxorScope {
-    public:
-	std::string path;
-	std::vector<unsigned int> dispatch_lines;
-
-	RoxorScope(const char *fname) : path(fname) {}
-};
-
 class RoxorCompiler {
     public:
 	static llvm::Module *module;
@@ -43,9 +35,7 @@
 	RoxorCompiler(void);
 	virtual ~RoxorCompiler(void) { }
 
-	void set_fname(const char *_fname) {
-	    fname = _fname;
-	}
+	void set_fname(const char *_fname);
 
 	Value *compile_node(NODE *node);
 
@@ -71,26 +61,11 @@
 	bool is_dynamic_class(void) { return dynamic_class; }
 	void set_dynamic_class(bool flag) { dynamic_class = flag; }
 
-	RoxorScope *scope_for_function(Function *f) {
-	    std::map<Function *, RoxorScope *>::iterator i = scopes.find(f);
-	    return i == scopes.end() ? NULL : i->second;
-	}
-
-	bool delete_scope(Function *f) {
-	    std::map<Function *, RoxorScope *>::iterator i = scopes.find(f);
-	    if (i != scopes.end()) {
-		scopes.erase(i);
-		delete i->second;
-		return true;
-	    } 
-	    return false;
-	}
-
-	void clear_scopes(void) {
-	    scopes.clear();
-	}
-
     protected:
+	DIFactory *debug_info;
+	DICompileUnit debug_compile_unit;
+	DISubprogram debug_subprogram;
+
 	const char *fname;
 	bool inside_eval;
 
@@ -99,7 +74,6 @@
 	std::map<ID, Value *> ivar_slots_cache;
 	std::map<std::string, GlobalVariable *> static_strings;
 	std::map<CFHashCode, GlobalVariable *> static_ustrings;
-	std::map<Function *, RoxorScope *> scopes;
 
 #if ROXOR_COMPILER_DEBUG
 	int level;
@@ -142,7 +116,6 @@
 	int return_from_block;
 	int return_from_block_ids;
 	PHINode *ensure_pn;
-	RoxorScope *current_scope;
 	bool class_declaration;
 
 	Function *dispatcherFunc;

Modified: MacRuby/trunk/llvm.h
===================================================================
--- MacRuby/trunk/llvm.h	2009-12-15 01:33:42 UTC (rev 3116)
+++ MacRuby/trunk/llvm.h	2009-12-15 01:42:46 UTC (rev 3117)
@@ -11,6 +11,7 @@
 #include <llvm/Instructions.h>
 #include <llvm/ModuleProvider.h>
 #include <llvm/Intrinsics.h>
+#include <llvm/Analysis/DebugInfo.h>
 #include <llvm/ExecutionEngine/JIT.h>
 #include <llvm/PassManager.h>
 #include <llvm/Target/TargetData.h>

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-12-15 01:33:42 UTC (rev 3116)
+++ MacRuby/trunk/vm.cpp	2009-12-15 01:42:46 UTC (rev 3117)
@@ -16,10 +16,13 @@
 #include <llvm/Instructions.h>
 #include <llvm/ModuleProvider.h>
 #include <llvm/PassManager.h>
+#include <llvm/Analysis/DebugInfo.h>
 #include <llvm/Analysis/Verifier.h>
 #include <llvm/Target/TargetData.h>
+#include <llvm/CodeGen/MachineFunction.h>
 #include <llvm/ExecutionEngine/JIT.h>
 #include <llvm/ExecutionEngine/JITMemoryManager.h>
+#include <llvm/ExecutionEngine/JITEventListener.h>
 #include <llvm/ExecutionEngine/GenericValue.h>
 #include <llvm/Target/TargetData.h>
 #include <llvm/Target/TargetMachine.h>
@@ -61,35 +64,55 @@
 
 VALUE rb_cTopLevel = 0;
 
-struct RoxorFunction {
-    Function *f;
-    RoxorScope *scope;
-    unsigned char *start;
-    unsigned char *end;
-    void *imp;
-    std::vector<unsigned char *> ehs;
+class RoxorFunction {
+    public: 
+	// Information retrieved from JITManager.
+	Function *f;
+	unsigned char *start;
+	unsigned char *end;
+	std::vector<unsigned char *> ehs;
 
-    RoxorFunction(Function *_f, RoxorScope *_scope, unsigned char *_start,
-	    unsigned char *_end) {
-	f = _f;
-	scope = _scope;
-	start = _start;
-	end = _end;
-	imp = NULL; 	// lazy
-    }
+	// Information retrieved from JITListener.
+	std::string file;
+	class Line {
+	    public:
+		uintptr_t address;
+		unsigned line;
+		Line(uintptr_t _address, unsigned _line) {
+		    address = _address;
+		    line = _line;
+		}
+	};
+	std::vector<Line> lines;
+
+	// Information retrieved later (lazily).
+	void *imp;
+
+	RoxorFunction(Function *_f, unsigned char *_start,
+		unsigned char *_end) {
+	    f = _f;
+	    start = _start;
+	    end = _end;
+	    imp = NULL;
+	}
 };
 
-class RoxorJITManager : public JITMemoryManager {
+class RoxorJITManager : public JITMemoryManager, public JITEventListener {
     private:
         JITMemoryManager *mm;
 	std::vector<struct RoxorFunction *> functions;
 
+	RoxorFunction *current_function(void) {
+	    assert(!functions.empty());
+	    return functions.back();
+	}
+
     public:
 	RoxorJITManager() : JITMemoryManager() { 
 	    mm = CreateDefaultMemManager(); 
 	}
 
-	struct RoxorFunction *find_function(uint8_t *addr) {
+	RoxorFunction *find_function(uint8_t *addr) {
 	     if (functions.empty()) {
 		return NULL;
 	     }
@@ -125,6 +148,8 @@
 	    return NULL;
 	}
 
+	// JITMemoryManager callbacks.
+
 	void setMemoryWritable(void) { 
 	    mm->setMemoryWritable(); 
 	}
@@ -172,8 +197,7 @@
 		uint8_t *FunctionEnd) {
 	    mm->endFunctionBody(F, FunctionStart, FunctionEnd);
 	    Function *f = const_cast<Function *>(F);
-	    RoxorScope *s = RoxorCompiler::shared->scope_for_function(f);
-	    functions.push_back(new RoxorFunction(f, s, FunctionStart,
+	    functions.push_back(new RoxorFunction(f, FunctionStart,
 			FunctionEnd));
 	}
 
@@ -198,14 +222,37 @@
 
 	void endExceptionTable(const Function *F, uint8_t *TableStart, 
 		uint8_t *TableEnd, uint8_t* FrameRegister) {
-	    assert(!functions.empty());
-	    functions.back()->ehs.push_back(FrameRegister);
+	    current_function()->ehs.push_back(FrameRegister);
 	    mm->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
 	}
 
 	void setPoisonMemory(bool poison) {
 	    mm->setPoisonMemory(poison);
 	}
+
+	// JITEventListener callbacks.
+
+	void NotifyFunctionEmitted(const Function &F,
+		void *Code, size_t Size,
+		const EmittedFunctionDetails &Details)
+	{
+	    RoxorFunction *function = current_function();
+
+	    std::string file;
+	    for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator iter = Details.LineStarts.begin(); iter != Details.LineStarts.end(); ++iter) {
+		DebugLocTuple dlt = Details.MF->getDebugLocTuple(iter->Loc);
+		if (file.size() == 0) {
+		    DICompileUnit unit(dlt.CompileUnit);
+		    unit.getFilename(file);
+		    assert(file.size() != 0);
+		}
+
+		RoxorFunction::Line line(iter->Address, dlt.Line);
+		function->lines.push_back(line);
+	    }
+
+	    function->file = file;
+	}
 };
 
 extern "C" void *__cxa_allocate_exception(size_t);
@@ -248,6 +295,7 @@
 	abort();
     }
     ee->DisableLazyCompilation();
+    ee->RegisterJITEventListener(jmm);
 
     fpm = new FunctionPassManager(emp);
     fpm->add(new TargetData(*ee->getTargetData()));
@@ -482,7 +530,6 @@
     }
 
     // Remove the compiler scope.
-    RoxorCompiler::shared->delete_scope(func);
     delete f;
 
     // Delete machine code.
@@ -526,49 +573,21 @@
 	}
 
 	rb_vm_method_node_t *node = iter->second;
-
-	RoxorScope *scope = f == NULL ? NULL : f->scope;
 	if (ln != NULL) {
-	    if (scope != NULL) {
-#if __LP64__
-		// So, we need to determine here which call to the dispatcher
-		// we are exactly, so that we can retrieve the appropriate
-		// line number from the annotation.
-		// Unfortunately, the only way to achieve that seems to scan
-		// the current function's machine code.
-		// This code has only been tested on x86_64 but could be
-		// easily ported to i386.
-		const uint32_t sym = *(uint32_t *)((unsigned char *)addr - 8);
-		const int sentinel = sym & 0xff;
-
-		unsigned char *p = f->start;
-		unsigned int i = 0;
-		while ((p = (unsigned char *)memchr(p, sentinel,
-				(unsigned char *)addr - p)) != NULL) {
-		    if (*(uint32_t *)p == sym) {
-			i++;
+	    *ln = 0;
+	    if (f != NULL) {
+		for (std::vector<RoxorFunction::Line>::iterator iter =
+			f->lines.begin(); iter != f->lines.end(); ++iter) {
+		    if ((*iter).address == (uintptr_t)addr) {
+			*ln = (*iter).line;
+			break;
 		    }
-		    p++;
 		}
-
-		if (i > 0 && i - 1 < scope->dispatch_lines.size()) {
-		    *ln = scope->dispatch_lines[i - 1];
-		}
-		else {
-		    *ln = 0;
-		}
-#else
-		// TODO 32-bit hack...
-		*ln = 0;
-#endif
 	    }
-	    else {
-		*ln = 0;
-	    }
 	}
 	if (path != NULL) {
-	    if (scope != NULL) {
-		strncpy(path, scope->path.c_str(), path_len);
+	    if (f != NULL && f->file.size() > 0) {
+		strncpy(path, f->file.c_str(), path_len);
 	    }
 	    else {
 		strncpy(path, "core", path_len);
@@ -3765,6 +3784,8 @@
     return rb_vm_run(fname, node, binding, inside_eval);
 }
 
+extern VALUE rb_progname;
+
 extern "C"
 void
 rb_vm_aot_compile(NODE *node)
@@ -3773,6 +3794,7 @@
     assert(ruby_aot_init_func);
 
     // Compile the program as IR.
+    RoxorCompiler::shared->set_fname(RSTRING_PTR(rb_progname));
     Function *f = RoxorCompiler::shared->compile_main_function(node);
     f->setName(RSTRING_PTR(ruby_aot_init_func));
     GET_CORE()->optimize(f);
@@ -4622,6 +4644,7 @@
 Init_PreVM(void)
 {
     llvm::DwarfExceptionHandling = true; // required!
+    llvm::JITEmitDebugInfo = true;
 
     RoxorCompiler::module = new llvm::Module("Roxor", getGlobalContext());
     RoxorCompiler::module->setTargetTriple(TARGET_TRIPLE);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091214/dec36a48/attachment-0001.html>


More information about the macruby-changes mailing list