[llvm-commits] CVS: llvm-gcc/gcc/llvm-expand.c llvm-internals.h llvm-out.c llvm-out.h toplev.c
Chris Lattner
lattner at cs.uiuc.edu
Thu Nov 18 12:44:38 PST 2004
Changes in directory llvm-gcc/gcc:
llvm-expand.c updated: 1.54 -> 1.55
llvm-internals.h updated: 1.1 -> 1.2
llvm-out.c updated: 1.5 -> 1.6
llvm-out.h updated: 1.4 -> 1.5
toplev.c updated: 1.5 -> 1.6
---
Log message:
Initial checkin of line number support for llvmgcc and llvmg++. This will
be improved a bit in a second, but this basically works.
You get line numbers by passing -g to llvmgcc. Now llvm-db is actually
useful! :)
All of the hard parts of this patch was written by Michael McCracken, I just
got C++ to work with it. Thanks Michael!
---
Diffs of the changes: (+548 -3)
Index: llvm-gcc/gcc/llvm-expand.c
diff -u llvm-gcc/gcc/llvm-expand.c:1.54 llvm-gcc/gcc/llvm-expand.c:1.55
--- llvm-gcc/gcc/llvm-expand.c:1.54 Tue Oct 19 23:54:31 2004
+++ llvm-gcc/gcc/llvm-expand.c Thu Nov 18 14:44:23 2004
@@ -64,6 +64,15 @@
extern int isPassedByInvisibleReference(tree Type);
+
+/* Debugging info emitter functions. */
+static void llvm_emit_dbg_stoppoint(llvm_function *Fn, unsigned lineNo,
+ unsigned colNo);
+static void llvm_emit_dbg_declare(llvm_function *Fn, tree t);
+static void llvm_emit_region_end(llvm_function *Fn);
+static void llvm_emit_dbg_function_info(struct llvm_function *Fn);
+static void llvm_emit_dbg_function_start(llvm_function *Fn);
+
/*===----------------------------------------------------------------------===**
... Helper functions for Instruction Emission ...
*===----------------------------------------------------------------------===*/
@@ -716,6 +725,12 @@
*/
llvm_value *IndirectGotoValue; /* The dynamic block id to go to. */
llvm_basicblock *IndirectGotoBlock;
+
+ /* Debug info */
+ llvm_instruction *dbg_call_funcstart_inst;
+ llvm_value *dbg_global_memloc;
+ llvm_instruction *dbg_entry_alloca;
+
} llvm_expand_info;
/* add_scope_stack - Allocate and add a scope to the top of the scope list, with
@@ -2628,6 +2643,17 @@
/* Set up context appropriately for handling this statement. */
int saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
prep_stmt (t);
+
+ if(debug_info_level > DINFO_LEVEL_NONE){
+ if(TREE_CODE(t) == COMPOUND_STMT){
+ /* skip compound statements - we handle their components.
+ Avoids emitting multiple stop points for a single line. */
+ }else if (TREE_CODE(t) == DECL_STMT){
+ llvm_emit_dbg_declare(Fn, t); /* FIXME: does nothing */
+ }else{
+ llvm_emit_dbg_stoppoint(Fn, STMT_LINENO(t), 0);
+ }
+ }
switch (TREE_CODE (t)) {
case FILE_STMT:
@@ -5118,6 +5144,11 @@
}
+/* Counts the number of string constants.
+ * moved to file scope to allow for more than one type.
+ */
+static int StrCounter = 0;
+
/* llvm_expand_lvalue_expr: generate code for computing the address of EXP. An
* llvm_value* for the computed L-value is returned. This is only legal to call
@@ -5403,7 +5434,7 @@
}
case STRING_CST: { /* Literal string lvalue: "x" expression */
- static int StrCounter = 0;
+
/* Create a new global variable for the constant string */
char Name[20];
llvm_global *G;
@@ -5971,6 +6002,16 @@
break;
case EXPR_WITH_FILE_LOCATION:
+ /* output location note for EXPR_WFL
+ why does expr.c use a stack? I see the commit from 1998
+ in the changelog, but not the explanation in the lists.
+
+ EXPR_WFL doesn't seem to be used in C much.
+
+ */
+ if (EXPR_WFL_EMIT_LINE_NOTE (exp)){
+ llvm_emit_dbg_stoppoint(Fn, EXPR_WFL_LINENO(exp), EXPR_WFL_COLNO(exp));
+ }
Result = llvm_expand_expr(Fn, EXPR_WFL_NODE(exp), DestLoc);
break;
@@ -6824,6 +6865,11 @@
/*assert(!current_function_needs_context && "Case not handled!");*/
TREE_ASM_WRITTEN(subr) = 1;
+ if (debug_info_level > DINFO_LEVEL_NONE) {
+ /* emit global with info and prepare call to function start intrinsic. */
+ llvm_emit_dbg_function_info(Fn);
+ }
+
return Fn;
}
@@ -6857,6 +6903,13 @@
&DECL_SOURCE_LOCATION (decl), decl);
}
+ /* emit global with info and call to function start intrinsic
+ * do this after the body is expanded so when we insert at
+ * the beginning, we don't get bumped later by alloca's.
+ */
+ if (debug_info_level > DINFO_LEVEL_NONE)
+ llvm_emit_dbg_function_start(Fn);
+
/* Output the label for the actual return from the function. */
llvm_emit_label(Fn, Fn->ExpandInfo->ReturnBlock);
@@ -6917,6 +6970,11 @@
assert(Fn->ExpandInfo->GotoFixupList == 0 && "Goto fixups remain?");
assert(Fn->ExpandInfo->InnermostScope == 0 && "A scope didn't get popped?");
+ if(debug_info_level > DINFO_LEVEL_NONE){
+ /* emit region end intrinsic to end the function */
+ llvm_emit_region_end(Fn);
+ }
+
/* Reset the identifier rename table now that we are out of function scope */
ResetIdentifierTableForEndOfFunction();
@@ -7193,3 +7251,463 @@
return V->Name;
}
+
+/* --== Debugging support ==-- */
+
+/* Fn Prototypes, where to move them to? */
+static llvm_global *EmitGlobalString(const char *InStr);
+
+/* debug constants */
+
+static unsigned LLVM_DEBUG_VERSION = 0;
+static unsigned LLVM_DEBUG_LANG_CODE = 1;
+
+static llvm_type *stopPtFnTy;
+static llvm_type *funcStartFnTy;
+static llvm_type *regionEndFnTy;
+static llvm_type *regionStartFnTy;
+static llvm_type *dbgDeclareFnTy;
+
+static llvm_function *dbg_declare_fn;
+static llvm_function *dbg_region_end_fn;
+static llvm_function *dbg_region_start_fn;
+static llvm_function *dbg_func_start_fn;
+static llvm_function *dbg_stoppoint_fn;
+
+static llvm_type *dbCompileUnitTy;
+static llvm_type *dbGlobalTy;
+
+static llvm_type *emptyStructTy;
+static llvm_type *ptrToEmptyStructTy;
+
+static llvm_global *dbCompileUnitGlobal;
+static llvm_global *dbTranslationUnitsGlobal;
+static llvm_global *dbGlobalsGlobal;
+
+/* used for file name and function names */
+static llvm_global *EmitGlobalString(const char *InStr){
+ static char name[20];
+ unsigned i = 0;
+ unsigned CP = 0;
+ unsigned len = strlen(InStr);
+ char *Buffer = (char *)alloca(3*len + 6);
+ llvm_global *G;
+ llvm_type *sByteArrayTy;
+
+ sprintf(name, ".str_%d", ++StrCounter);
+ Buffer[CP++] = 'c'; Buffer[CP++] = '"';
+ for (i = 0; i != len; ++i)
+ if (isprint((int)InStr[i]) && InStr[i] != '"' && InStr[i] != '\\')
+ Buffer[CP++] = InStr[i];
+ else {
+ sprintf(Buffer+CP, "\\%02X", ((unsigned)InStr[i] & 0xFF));
+ CP += 3;
+ }
+
+ Buffer[CP++] = '\\';
+ Buffer[CP++] = '0';
+ Buffer[CP++] = '0';
+ Buffer[CP++] = '\"'; Buffer[CP++] = 0;
+
+
+ sByteArrayTy = llvm_type_get_array(SByteTy, len+1);
+
+ G = llvm_global_new(sByteArrayTy, name);
+ G->isConstant = 1;
+ G->Linkage = L_Internal;
+
+ G->Init = V2C(llvm_constant_new(sByteArrayTy, Buffer));
+
+ llvm_ilist_push_back(llvm_global, TheProgram.Globals, G);
+
+ return G;
+}
+
+/* llvm_emit_debug_context_info
+ emits file level debug info as LLVM globals
+ */
+
+void llvm_emit_debug_context_info(const char *fileName,
+ const char *path,
+ const char *producer){
+ llvm_constant *CA = 0;
+ llvm_global *pathStr = EmitGlobalString(fileName);
+ llvm_global *fileNameStr = EmitGlobalString(path);
+ llvm_global *producerStr = EmitGlobalString(producer);
+ llvm_value **Elements = (llvm_value**) xcalloc(7, sizeof(llvm_value*));
+ llvm_instruction *gep = 0;
+
+ /* Infer language of file, stolen from dwarf2out.c */
+ const char *language_string = lang_hooks.name;
+ if (strcmp (language_string, "GNU C++") == 0)
+ LLVM_DEBUG_LANG_CODE = 0x0004; /*DW_LANG_C_plus_plus;*/
+ else if (strcmp (language_string, "GNU Ada") == 0)
+ LLVM_DEBUG_LANG_CODE = 0x000d; /* DW_LANG_Ada95; */
+ else if (strcmp (language_string, "GNU F77") == 0)
+ LLVM_DEBUG_LANG_CODE = 0x0007; /* DW_LANG_Fortran77; */
+ else if (strcmp (language_string, "GNU Pascal") == 0)
+ LLVM_DEBUG_LANG_CODE = 0x0009; /* DW_LANG_Pascal83; */
+ else if (strcmp (language_string, "GNU Java") == 0)
+ LLVM_DEBUG_LANG_CODE = 0x000b; /* DW_LANG_Java; */
+ else
+ LLVM_DEBUG_LANG_CODE = 0x0001; /* DW_LANG_C89; */
+
+
+ /* The constant in Elements[0] is DW_TAG_COMPILE_UNIT */
+ Elements[0] = llvm_constant_new_integral(UIntTy, 17);
+ Elements[1] = llvm_constant_new_integral(UShortTy, LLVM_DEBUG_VERSION);
+ Elements[2] = llvm_constant_new_integral(UShortTy, LLVM_DEBUG_LANG_CODE);
+
+ gep = create_gep3(G2V(fileNameStr),
+ llvm_constant_intptr_0,
+ llvm_constant_intptr_0);
+ Elements[3] = G2V(llvm_constant_expr_new(gep));
+
+ gep = create_gep3(G2V(pathStr),
+ llvm_constant_intptr_0,
+ llvm_constant_intptr_0);
+ Elements[4] = G2V(llvm_constant_expr_new(gep));
+
+ gep = create_gep3(G2V(producerStr),
+ llvm_constant_intptr_0,
+ llvm_constant_intptr_0);
+ Elements[5] = G2V(llvm_constant_expr_new(gep));
+
+ Elements[6] = G2V(dbTranslationUnitsGlobal);
+ CA = G2C(llvm_constant_aggregate_new(dbCompileUnitTy, Elements));
+
+ dbCompileUnitGlobal = llvm_global_new(dbCompileUnitTy, "d.compile_unit");
+ dbCompileUnitGlobal->isConstant = 1;
+ dbCompileUnitGlobal->Linkage = L_Internal;
+ dbCompileUnitGlobal->Init = CA;
+
+ llvm_ilist_push_back(llvm_global, TheProgram.Globals, dbCompileUnitGlobal);
+
+}
+
+/* llvm_emit_dbg_function_info emits a global of type lldb.global
+ * that describes a function in the program.
+ * it sets a static variable in this file to allow other emitted
+ * debug intrinsics to refer to that function.
+ */
+/* static llvm_instruction *dbg_call_funcstart_inst; */
+/* static llvm_value *dbg_global_memloc = 0; */
+/* static llvm_instruction *dbg_entry_alloca = 0; */
+
+static llvm_global *dbg_func_info_global;
+
+static void llvm_emit_dbg_function_info(llvm_function *Fn) {
+ char *func_name = G2V(Fn)->Name;
+ char *gFuncName = 0;
+
+ llvm_constant *CA = 0;
+ llvm_global *funcNameStr = 0;
+ llvm_value **Elements = 0;
+ llvm_instruction *gep = 0;
+
+ funcNameStr = EmitGlobalString(func_name);
+ Elements = (llvm_value**) xcalloc(7, sizeof(llvm_value*));
+ Elements[0] = llvm_constant_new_integral(UIntTy, 46); /* DW_TAG_subprogram */
+ Elements[1] = G2V(dbCompileUnitGlobal);
+
+ gep = create_gep3(G2V(funcNameStr),
+ llvm_constant_intptr_0,
+ llvm_constant_intptr_0);
+ Elements[2] = G2V(llvm_constant_expr_new(gep));
+
+ Elements[3] = G2V(dbGlobalsGlobal);
+ Elements[4] = llvm_constant_VoidPtr_null;
+ Elements[5] = llvm_constant_bool_true;
+ Elements[6] = llvm_constant_bool_false;
+ CA = G2C(llvm_constant_aggregate_new(dbGlobalTy, Elements));
+
+ asprintf(&gFuncName,"d.%s", func_name);
+ dbg_func_info_global = llvm_global_new(dbGlobalTy, gFuncName);
+ free(gFuncName);
+
+ dbg_func_info_global->Linkage = L_External;
+ dbg_func_info_global->Init = CA;
+
+ llvm_ilist_push_back(llvm_global, TheProgram.Globals, dbg_func_info_global);
+
+ Fn->ExpandInfo->dbg_entry_alloca = create_alloca_inst("dbg",
+ ptrToEmptyStructTy,
+ llvm_constant_uint_1);
+ Fn->ExpandInfo->dbg_global_memloc = D2V(Fn->ExpandInfo->dbg_entry_alloca);
+
+}
+
+
+/*
+ llvm_emit_dbg_function_start
+ emits the instruction that was built in emit_dbg_function_info
+ */
+static void llvm_emit_dbg_function_start(llvm_function *Fn) {
+ /* get start of first basic block. */
+ llvm_basicblock *entryBlock = llvm_ilist_front(llvm_basicblock,
+ Fn->BasicBlocks);
+
+ llvm_instruction *storeFuncCall = 0;
+
+ /* prep function.start call */
+
+ Fn->ExpandInfo->dbg_call_funcstart_inst =
+ llvm_instruction_new(ptrToEmptyStructTy, "dbg", O_Call, 2);
+
+ Fn->ExpandInfo->dbg_call_funcstart_inst->Operands[0] =
+ G2V(dbg_func_start_fn);
+ Fn->ExpandInfo->dbg_call_funcstart_inst->Operands[1] =
+ G2V(dbg_func_info_global);
+
+
+ /* the 'alloca trick':
+ store into a memory location to force debug intrinsics to become SSA
+ during mem2reg.
+
+ Note that the following pushes are onto the front, so this becomes:
+ alloca
+ call dbg.func.start
+ store
+ */
+ storeFuncCall = create_store_inst(Fn->ExpandInfo->dbg_call_funcstart_inst,
+ Fn->ExpandInfo->dbg_entry_alloca, 0);
+
+ llvm_ilist_push_front(llvm_instruction, entryBlock->Instructions,
+ storeFuncCall);
+ llvm_ilist_push_front(llvm_instruction, entryBlock->Instructions,
+ Fn->ExpandInfo->dbg_call_funcstart_inst);
+ llvm_ilist_push_front(llvm_instruction, entryBlock->Instructions,
+ Fn->ExpandInfo->dbg_entry_alloca);
+}
+
+
+/* InitDebuggerTypeDecls inits type decls for debugger types,
+ * declarations for debugger intrinsics
+ * ^--- (some are currently unused in the generated bytecode)
+ * and global object anchors.
+ */
+void InitDebuggerTypeDecls(void){
+
+ llvm_type *ptrToSByteTy;
+ unsigned ptrTySz, uIntTySz, uShortTySz, boolTySz;
+ unsigned dbCompileUnitSz;
+ unsigned dbGlobalTySz;
+ llvm_type *ptrToDBCompileUnitTy;
+ llvm_type *ptrToDBGlobalTy;
+ unsigned dbLocalTySz;
+ llvm_type *dbLocalTy;
+ llvm_type *ptrToDBLocalTy;
+ llvm_value *emptyStructConst;
+
+ emptyStructTy = llvm_type_create_struct(0, 0);
+ emptyStructTy = llvm_type_get_cannonical_struct(emptyStructTy);
+ ptrToEmptyStructTy = llvm_type_get_pointer(emptyStructTy);
+ ptrToSByteTy = llvm_type_get_pointer(SByteTy);
+
+ ptrTySz = llvm_type_get_size(ptrToEmptyStructTy);
+ uIntTySz = llvm_type_get_size(UIntTy);
+ uShortTySz = llvm_type_get_size(UShortTy);
+ boolTySz = llvm_type_get_size(BoolTy);
+
+ /* setup debugger types */
+ dbCompileUnitSz = uIntTySz + 2 * uShortTySz + 4 * ptrTySz;
+ dbCompileUnitTy = llvm_type_create_struct(7, dbCompileUnitSz);
+ dbCompileUnitTy->x.Struct.MemberOffsets[0] = 0;
+ dbCompileUnitTy->Elements[0] = UIntTy;
+ dbCompileUnitTy->x.Struct.MemberOffsets[1] = uIntTySz;
+ dbCompileUnitTy->Elements[1] = UShortTy;
+ dbCompileUnitTy->x.Struct.MemberOffsets[2] = uShortTySz;
+ dbCompileUnitTy->Elements[2] = UShortTy;
+ dbCompileUnitTy->x.Struct.MemberOffsets[3] = uShortTySz;
+ dbCompileUnitTy->Elements[3] = ptrToSByteTy;
+ dbCompileUnitTy->x.Struct.MemberOffsets[4] = ptrTySz;
+ dbCompileUnitTy->Elements[4] = ptrToSByteTy;
+ dbCompileUnitTy->x.Struct.MemberOffsets[5] = ptrTySz;
+ dbCompileUnitTy->Elements[5] = ptrToSByteTy;
+ dbCompileUnitTy->x.Struct.MemberOffsets[6] = ptrTySz;
+ dbCompileUnitTy->Elements[6] = ptrToEmptyStructTy;
+ dbCompileUnitTy->x.Struct.TypeName = (char *)"lldb.compile_unit";
+
+ dbCompileUnitTy = llvm_type_get_cannonical_struct(dbCompileUnitTy);
+ ptrToDBCompileUnitTy = llvm_type_get_pointer(dbCompileUnitTy);
+
+ dbGlobalTySz = uIntTySz + 4 * ptrTySz + 2 * boolTySz;
+ dbGlobalTy = llvm_type_create_struct(7, dbGlobalTySz);
+ dbGlobalTy->x.Struct.MemberOffsets[0] = 0;
+ dbGlobalTy->Elements[0] = UIntTy;
+ dbGlobalTy->x.Struct.MemberOffsets[1] = uIntTySz;
+ dbGlobalTy->Elements[1] = ptrToDBCompileUnitTy;
+ dbGlobalTy->x.Struct.MemberOffsets[2] = ptrTySz;
+ dbGlobalTy->Elements[2] = ptrToSByteTy;
+ dbGlobalTy->x.Struct.MemberOffsets[3] = ptrTySz;
+ dbGlobalTy->Elements[3] = ptrToEmptyStructTy;
+ dbGlobalTy->x.Struct.MemberOffsets[4] = ptrTySz;
+ dbGlobalTy->Elements[4] = ptrToSByteTy;
+ dbGlobalTy->x.Struct.MemberOffsets[5] = ptrTySz;
+ dbGlobalTy->Elements[5] = BoolTy;
+ dbGlobalTy->x.Struct.MemberOffsets[6] = boolTySz;
+ dbGlobalTy->Elements[6] = BoolTy;
+ dbGlobalTy->x.Struct.TypeName = (char *)"lldb.global";
+
+ dbGlobalTy = llvm_type_get_cannonical_struct(dbGlobalTy);
+ ptrToDBGlobalTy = llvm_type_get_pointer(dbGlobalTy);
+
+
+ dbLocalTySz = uIntTySz + 3 * ptrTySz + 2 * boolTySz;
+ dbLocalTy = llvm_type_create_struct(6, dbLocalTySz);
+ dbLocalTy->x.Struct.MemberOffsets[0] = 0;
+ dbLocalTy->Elements[0] = UIntTy;
+ dbLocalTy->x.Struct.MemberOffsets[1] = uIntTySz;
+ dbLocalTy->Elements[1] = ptrToDBGlobalTy;
+ dbLocalTy->x.Struct.MemberOffsets[2] = ptrTySz;
+ dbLocalTy->Elements[2] = ptrToSByteTy;
+ dbLocalTy->x.Struct.MemberOffsets[3] = ptrTySz;
+ dbLocalTy->Elements[3] = ptrToSByteTy;
+ dbLocalTy->x.Struct.MemberOffsets[4] = ptrTySz;
+ dbLocalTy->Elements[4] = BoolTy;
+ dbLocalTy->x.Struct.MemberOffsets[5] = boolTySz;
+ dbLocalTy->Elements[5] = BoolTy;
+ dbLocalTy->x.Struct.TypeName = (char *)"lldb.local";
+
+ dbLocalTy = llvm_type_get_cannonical_struct(dbLocalTy);
+ ptrToDBLocalTy = llvm_type_get_pointer(dbLocalTy);
+
+ /* global object anchors */
+
+ emptyStructConst = llvm_constant_new(emptyStructTy, "{ }");
+
+ dbTranslationUnitsGlobal = llvm_global_new(emptyStructTy,
+ "llvm.dbg.translation_units");
+ dbTranslationUnitsGlobal->Init = V2C(emptyStructConst);
+ dbTranslationUnitsGlobal->Linkage = L_LinkOnce;
+ llvm_ilist_push_back(llvm_global, TheProgram.Globals,
+ dbTranslationUnitsGlobal);
+
+
+ dbGlobalsGlobal = llvm_global_new(emptyStructTy, "llvm.dbg.globals");
+ dbGlobalsGlobal->Init = V2C(emptyStructConst);
+ dbGlobalsGlobal->Linkage = L_LinkOnce;
+ llvm_ilist_push_back(llvm_global, TheProgram.Globals, dbGlobalsGlobal);
+
+
+ /* intrinsic function declarations */
+
+ stopPtFnTy = llvm_type_create_function(4, ptrToEmptyStructTy);
+ stopPtFnTy->Elements[1] = ptrToEmptyStructTy;
+ stopPtFnTy->Elements[2] = UIntTy;
+ stopPtFnTy->Elements[3] = UIntTy;
+ stopPtFnTy->Elements[4] = ptrToDBCompileUnitTy;
+ dbg_stoppoint_fn = CreateIntrinsicFnWithType("llvm.dbg.stoppoint",
+ stopPtFnTy);
+
+ funcStartFnTy = llvm_type_create_function(1, ptrToEmptyStructTy);
+ funcStartFnTy->Elements[1] = ptrToDBGlobalTy;
+ dbg_func_start_fn = CreateIntrinsicFnWithType("llvm.dbg.func.start",
+ funcStartFnTy);
+
+ regionStartFnTy = llvm_type_create_function(1, ptrToEmptyStructTy);
+ regionStartFnTy->Elements[1] = ptrToEmptyStructTy;
+ dbg_region_start_fn = CreateIntrinsicFnWithType("llvm.dbg.region.start",
+ regionStartFnTy);
+
+ regionEndFnTy = llvm_type_create_function(1, ptrToEmptyStructTy);
+ regionEndFnTy->Elements[1] = ptrToEmptyStructTy;
+ dbg_region_end_fn = CreateIntrinsicFnWithType("llvm.dbg.region.end",
+ regionEndFnTy);
+
+ dbgDeclareFnTy = llvm_type_create_function(1, ptrToEmptyStructTy);
+ dbgDeclareFnTy->Elements[1] = ptrToEmptyStructTy;
+ dbg_declare_fn = CreateIntrinsicFnWithType("llvm.dbg.declare",
+ dbgDeclareFnTy);
+
+}
+
+
+
+/* llvm_emit_dbg_stoppoint
+ * appends call to intrinsic llvm.dbg.stoppoint for debug line info.
+ *
+ %dbg = alloca {}* ;; In the entry block.
+
+ %tmp = call {}* %llvm.db.func.start(...)
+ store {}* %tmp, {}** %dbg
+
+ %tmp.1 = load {}** %dbg
+ %tmp.2 = call {}* %llvm.dbg.stoppoint({}* %tmp.1, ...
+ store {}* %tmp.2, {}** %dbg
+
+ */
+static void llvm_emit_dbg_stoppoint(llvm_function *Fn, unsigned lineNo,
+ unsigned colNo) {
+ llvm_instruction *stoppoint_inst;
+ llvm_instruction *load_dbg_inst;
+ llvm_instruction *store_dbg_inst;
+
+ load_dbg_inst = create_load_inst("dbg.tmp",
+ Fn->ExpandInfo->dbg_global_memloc, 0);
+
+ stoppoint_inst = llvm_instruction_new(ptrToEmptyStructTy, "dbg.tmp",
+ O_Call, 5);
+ stoppoint_inst->Operands[0] = G2V(dbg_stoppoint_fn);
+ stoppoint_inst->Operands[1] = D2V(load_dbg_inst);
+
+ stoppoint_inst->Operands[2] = llvm_constant_new_integral(UIntTy, lineNo);
+ stoppoint_inst->Operands[3] = llvm_constant_new_integral(UIntTy, colNo);
+ stoppoint_inst->Operands[4] = G2V(dbCompileUnitGlobal);
+
+ append_inst(Fn, load_dbg_inst);
+ append_inst(Fn, stoppoint_inst);
+
+ store_dbg_inst = create_store_inst(stoppoint_inst,
+ Fn->ExpandInfo->dbg_global_memloc, 0);
+ append_inst(Fn, store_dbg_inst);
+
+}
+
+/*
+ emits region end intrinsic for marking function ends
+ */
+static void llvm_emit_region_end(llvm_function *Fn){
+ llvm_instruction *dbg_call_reg_end_inst;
+ llvm_instruction *store_dbg_inst;
+ llvm_instruction *load_dbg_inst;
+ llvm_basicblock *last_block = llvm_ilist_back(llvm_basicblock,
+ Fn->BasicBlocks);
+
+ load_dbg_inst = create_load_inst("dbg.tmp",
+ Fn->ExpandInfo->dbg_global_memloc, 0);
+
+ dbg_call_reg_end_inst = llvm_instruction_new(ptrToEmptyStructTy,
+ "dbg.tmp", O_Call, 2);
+ dbg_call_reg_end_inst->Operands[0] = G2V(dbg_region_end_fn);
+ dbg_call_reg_end_inst->Operands[1] = D2V(load_dbg_inst);
+
+ /* see above for description of the 'alloca trick':*/
+
+ store_dbg_inst = create_store_inst(dbg_call_reg_end_inst,
+ Fn->ExpandInfo->dbg_global_memloc, 0);
+
+ llvm_ilist_push_front(llvm_instruction, last_block->Instructions,
+ store_dbg_inst);
+ llvm_ilist_push_front(llvm_instruction, last_block->Instructions,
+ dbg_call_reg_end_inst);
+ llvm_ilist_push_front(llvm_instruction, last_block->Instructions,
+ load_dbg_inst);
+}
+
+
+/* Emit intrinsics to mark variable declarations */
+static void llvm_emit_dbg_declare(llvm_function *Fn, tree t){
+ /* FIXME: need to actually do this.
+
+ See llvm_emit_dbg_stoppoint for an example of how to create a new
+ debug intrinsic call and chain it to the others.
+
+ To get the type of the declaration from the tree, see
+ llvm_type_get_from_tree in llvm-types.c (Used several times in this
+ file)
+
+ */
+
+}
+
Index: llvm-gcc/gcc/llvm-internals.h
diff -u llvm-gcc/gcc/llvm-internals.h:1.1 llvm-gcc/gcc/llvm-internals.h:1.2
--- llvm-gcc/gcc/llvm-internals.h:1.1 Thu Jan 8 16:35:32 2004
+++ llvm-gcc/gcc/llvm-internals.h Thu Nov 18 14:44:23 2004
@@ -103,4 +103,8 @@
void llvm_expand_catch_block(struct llvm_function *Fn, union tree_node *Hndlrs);
void llvm_expand_eh_spec(struct llvm_function *Fn, union tree_node *TypeList);
+/* Debugging info support functions. These are defined in llvm-expand.c */
+void InitDebuggerDecls(void);
+void InitDebuggerTypeDecls(void);
+
#endif /* GCC_LLVM_INTERNALS_H */
Index: llvm-gcc/gcc/llvm-out.c
diff -u llvm-gcc/gcc/llvm-out.c:1.5 llvm-gcc/gcc/llvm-out.c:1.6
--- llvm-gcc/gcc/llvm-out.c:1.5 Thu Nov 18 12:06:36 2004
+++ llvm-gcc/gcc/llvm-out.c Thu Nov 18 14:44:23 2004
@@ -60,6 +60,9 @@
llvm_InitializeProgram();
llvm_InitializeTypeSystem();
llvm_InitializeConstants();
+
+ if (debug_info_level > DINFO_LEVEL_NONE)
+ InitDebuggerTypeDecls();
}
Index: llvm-gcc/gcc/llvm-out.h
diff -u llvm-gcc/gcc/llvm-out.h:1.4 llvm-gcc/gcc/llvm-out.h:1.5
--- llvm-gcc/gcc/llvm-out.h:1.4 Fri May 7 14:20:26 2004
+++ llvm-gcc/gcc/llvm-out.h Thu Nov 18 14:44:23 2004
@@ -43,6 +43,10 @@
the command line, possibly NULL. */
void llvm_init_asm_output(const char *Filename);
+/* emit global debug info for the file */
+void llvm_emit_debug_context_info(const char *fileName, const char *path,
+ const char *producer);
+
/* llvm_assemble_external - This function is called once for each external
* function and variable as they are used.
*/
Index: llvm-gcc/gcc/toplev.c
diff -u llvm-gcc/gcc/toplev.c:1.5 llvm-gcc/gcc/toplev.c:1.6
--- llvm-gcc/gcc/toplev.c:1.5 Fri May 7 14:20:26 2004
+++ llvm-gcc/gcc/toplev.c Thu Nov 18 14:44:23 2004
@@ -4304,7 +4304,7 @@
error ("target system does not support the \"%s\" debug format",
debug_type_names[write_symbols]);
- if (EMIT_LLVM) /* Disable debug output for LLVM output */
+ if (EMIT_LLVM) /* LLVM does not use the standard GCC hooks for debug info */
debug_hooks = &do_nothing_debug_hooks;
/* If auxiliary info generation is desired, open the output file.
@@ -4407,8 +4407,24 @@
if (dump_base_name == 0)
dump_base_name = name ? name : "gccdump";
- if (EMIT_LLVM)
+ if (EMIT_LLVM) {
llvm_init_codegen();
+ if (debug_info_level > DINFO_LEVEL_NONE) {
+ char *buf = xstrdup(name);
+ char *path = buf;
+ char *fileName = strrchr(buf, '/');
+ if(fileName){
+ *fileName = '\0';
+ fileName++;
+ }else{
+ path = ".";
+ fileName = buf;
+ }
+
+ llvm_emit_debug_context_info(path, fileName, "llvm 3.4.x");
+ free(buf);
+ }
+ }
/* Other front-end initialization. */
if ((*lang_hooks.init) () == 0)
More information about the llvm-commits
mailing list