[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