[llvm-commits] [llvm-gcc-4.2] r39999 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-internal.h

Duncan Sands baldrick at free.fr
Wed Jul 18 02:48:41 PDT 2007


Author: baldrick
Date: Wed Jul 18 04:48:39 2007
New Revision: 39999

URL: http://llvm.org/viewvc/llvm-project?rev=39999&view=rev
Log:
Forward port of [129555].

Implement missing dwarf builtins, used by the libstdc++ unwinder.
This is more or less workable on x86-32/linux only

Patch by Anton Korobeynikov

Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
    llvm-gcc-4.2/trunk/gcc/llvm-internal.h

Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=39999&r1=39998&r2=39999&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Wed Jul 18 04:48:39 2007
@@ -60,8 +60,10 @@
 #include "target.h"
 #include "hard-reg-set.h"
 #include "except.h"
+#include "rtl.h"
 extern bool tree_could_throw_p(tree);  // tree-flow.h uses non-C++ C constructs.
 extern int get_pointer_alignment (tree exp, unsigned int max_align);
+extern enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
 }
 
 #define ITANIUM_STYLE_EXCEPTIONS
@@ -4210,7 +4212,25 @@
    return EmitBuiltinExtractReturnAddr(exp, Result);
   case BUILT_IN_FROB_RETURN_ADDR:
    return EmitBuiltinFrobReturnAddr(exp, Result);
-    
+
+  // Builtins used by the exception handling runtime.
+  case BUILT_IN_DWARF_CFA:
+    return EmitBuiltinDwarfCFA(exp, Result);
+#ifdef DWARF2_UNWIND_INFO
+  case BUILT_IN_DWARF_SP_COLUMN:
+    return EmitBuiltinDwarfSPColumn(exp, Result);
+  case BUILT_IN_INIT_DWARF_REG_SIZES:
+    return EmitBuiltinInitDwarfRegSizes(exp, Result);
+#endif
+  case BUILT_IN_EH_RETURN:
+    return EmitBuiltinEHReturn(exp, Result);
+#ifdef EH_RETURN_DATA_REGNO
+  case BUILT_IN_EH_RETURN_DATA_REGNO:
+    return EmitBuiltinEHReturnDataRegno(exp, Result);
+#endif
+  case BUILT_IN_UNWIND_INIT:
+    return EmitBuiltinUnwindInit(exp, Result);
+
 #define HANDLE_UNARY_FP(F32, F64, V) \
         Result = EmitBuiltinUnaryFPOp(V, Intrinsic::F32, Intrinsic::F64)
 
@@ -4286,19 +4306,8 @@
     case BUILT_IN_LONGJMP:
     case BUILT_IN_UPDATE_SETJMP_BUF:
     case BUILT_IN_TRAP:
-      
-      // Various hooks for the DWARF 2 __throw routine.
-    case BUILT_IN_UNWIND_INIT:
-    case BUILT_IN_DWARF_CFA:
-#ifdef DWARF2_UNWIND_INFO
-    case BUILT_IN_DWARF_SP_COLUMN:
-    case BUILT_IN_INIT_DWARF_REG_SIZES:
-#endif
-    case BUILT_IN_EH_RETURN:
-#ifdef EH_RETURN_DATA_REGNO
-    case BUILT_IN_EH_RETURN_DATA_REGNO:
-#endif
-      // FIXME: HACK: Just ignore these.
+
+    // FIXME: HACK: Just ignore these.
     {
       const Type *Ty = ConvertType(TREE_TYPE(exp));
       if (Ty != Type::VoidTy)
@@ -4579,6 +4588,171 @@
   return true;
 }
 
+
+// Builtins used by the exception handling runtime.
+
+// On most machines, the CFA coincides with the first incoming parm.
+#ifndef ARG_POINTER_CFA_OFFSET
+#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL)
+#endif
+
+// The mapping from gcc register number to DWARF 2 CFA column number.  By
+// default, we just provide columns for all registers.
+#ifndef DWARF_FRAME_REGNUM
+#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
+#endif
+
+// Map register numbers held in the call frame info that gcc has
+// collected using DWARF_FRAME_REGNUM to those that should be output in
+// .debug_frame and .eh_frame.
+#ifndef DWARF2_FRAME_REG_OUT
+#define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO)
+#endif
+
+/* Registers that get partially clobbered by a call in a given mode.
+   These must not be call used registers.  */
+#ifndef HARD_REGNO_CALL_PART_CLOBBERED
+#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) 0
+#endif
+
+bool TreeToLLVM::EmitBuiltinDwarfCFA(tree exp, Value *&Result) {
+  if (!validate_arglist(TREE_OPERAND(exp, 1), VOID_TYPE))
+    return false;
+
+  int cfa_offset = ARG_POINTER_CFA_OFFSET(0);
+
+  Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule,
+                                                      Intrinsic::eh_dwarf_cfa),
+                              ConstantInt::get(Type::Int32Ty, cfa_offset));
+
+  return true;
+}
+
+bool TreeToLLVM::EmitBuiltinDwarfSPColumn(tree exp, Value *&Result) {
+  if (!validate_arglist(TREE_OPERAND(exp, 1), VOID_TYPE))
+    return false;
+
+  unsigned int dwarf_regnum = DWARF_FRAME_REGNUM(STACK_POINTER_REGNUM);
+  Result = ConstantInt::get(ConvertType(TREE_TYPE(exp)), dwarf_regnum);
+
+  return true;
+}
+
+bool TreeToLLVM::EmitBuiltinEHReturnDataRegno(tree exp, Value *&Result) {
+  tree arglist = TREE_OPERAND(exp, 1);
+
+  if (!validate_arglist(arglist, INTEGER_TYPE, VOID_TYPE))
+    return false;
+
+  tree which = TREE_VALUE (arglist);
+  unsigned HOST_WIDE_INT iwhich;
+
+  if (TREE_CODE (which) != INTEGER_CST) {
+    error ("argument of %<__builtin_eh_return_regno%> must be constant");
+    return false;
+  }
+
+  iwhich = tree_low_cst (which, 1);
+  iwhich = EH_RETURN_DATA_REGNO (iwhich);
+  if (iwhich == INVALID_REGNUM)
+    return false;
+
+  iwhich = DWARF_FRAME_REGNUM (iwhich);
+
+  Result = ConstantInt::get(ConvertType(TREE_TYPE(exp)), iwhich);
+
+  return true;
+}
+
+bool TreeToLLVM::EmitBuiltinEHReturn(tree exp, Value *&Result) {
+  tree arglist = TREE_OPERAND(exp, 1);
+
+  if (!validate_arglist(arglist, INTEGER_TYPE, POINTER_TYPE, VOID_TYPE))
+    return false;
+
+  Value *Offset = Emit(TREE_VALUE(arglist), 0);
+  Value *Handler = Emit(TREE_VALUE(TREE_CHAIN(arglist)), 0);
+  Offset = Builder.CreateIntCast(Offset, Type::Int32Ty, true, "tmp");
+  Handler = CastToType(Instruction::BitCast, Handler,
+                       PointerType::get(Type::Int8Ty));
+
+  Builder.CreateCall(Intrinsic::getDeclaration(TheModule,
+                                               Intrinsic::eh_return),
+                     Offset, Handler);
+  Result = Builder.CreateUnreachable();
+
+  return true;
+}
+
+bool TreeToLLVM::EmitBuiltinInitDwarfRegSizes(tree exp, Value *&Result) {
+  unsigned int i;
+  bool wrote_return_column = false;
+  static bool reg_modes_initialized = false;
+
+  tree arglist = TREE_OPERAND(exp, 1);
+  if (!validate_arglist(arglist, POINTER_TYPE, VOID_TYPE))
+    return false;
+
+  if (!reg_modes_initialized) {
+    init_reg_modes_once();
+    reg_modes_initialized = true;
+  }
+
+  Value *Addr = BitCastToType(Emit(TREE_VALUE(arglist), 0),
+                              PointerType::get(Type::Int8Ty));
+  Constant *Size, *Idx;
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) {
+    int rnum = DWARF2_FRAME_REG_OUT (DWARF_FRAME_REGNUM (i), 1);
+
+    if (rnum < DWARF_FRAME_REGISTERS) {
+      enum machine_mode save_mode = reg_raw_mode[i];
+      HOST_WIDE_INT size;
+
+      if (HARD_REGNO_CALL_PART_CLOBBERED (i, save_mode))
+        save_mode = choose_hard_reg_mode (i, 1, true);
+      if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN) {
+        if (save_mode == VOIDmode)
+          continue;
+        wrote_return_column = true;
+      }
+      size = GET_MODE_SIZE (save_mode);
+      if (rnum < 0)
+        continue;
+
+      Size = ConstantInt::get(Type::Int8Ty, size);
+      Idx  = ConstantInt::get(Type::Int32Ty, rnum);
+      Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx, "tmp"), false);
+    }
+  }
+
+  if (!wrote_return_column) {
+    Size = ConstantInt::get(Type::Int8Ty, GET_MODE_SIZE (Pmode));
+    Idx  = ConstantInt::get(Type::Int32Ty, DWARF_FRAME_RETURN_COLUMN);
+    Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx, "tmp"), false);
+  }
+
+#ifdef DWARF_ALT_FRAME_RETURN_COLUMN
+  Size = ConstantInt::get(Type::Int8Ty, GET_MODE_SIZE (Pmode));
+  Idx  = ConstantInt::get(Type::Int32Ty, DWARF_ALT_FRAME_RETURN_COLUMN);
+  Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx, "tmp"), false);
+#endif
+
+  // TODO: the RS6000 target needs extra initialization [gcc changeset 122468].
+
+  return true;
+}
+
+bool TreeToLLVM::EmitBuiltinUnwindInit(tree exp, Value *&Result) {
+  if (!validate_arglist(TREE_OPERAND(exp, 1), VOID_TYPE))
+    return false;
+
+  Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule,
+                                                    Intrinsic::eh_unwind_init));
+
+  return true;
+}
+
 bool TreeToLLVM::EmitBuiltinStackRestore(tree exp) {
   tree arglist = TREE_OPERAND(exp, 1);
   if (!validate_arglist(arglist, POINTER_TYPE, VOID_TYPE))

Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=39999&r1=39998&r2=39999&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Wed Jul 18 04:48:39 2007
@@ -583,6 +583,12 @@
   bool EmitBuiltinFrobReturnAddr(tree_node *exp, Value *&Result);
   bool EmitBuiltinStackSave(tree_node *exp, Value *&Result);
   bool EmitBuiltinStackRestore(tree_node *exp);
+  bool EmitBuiltinDwarfCFA(tree_node *exp, Value *&Result);
+  bool EmitBuiltinDwarfSPColumn(tree_node *exp, Value *&Result);
+  bool EmitBuiltinEHReturnDataRegno(tree_node *exp, Value *&Result);
+  bool EmitBuiltinEHReturn(tree_node *exp, Value *&Result);
+  bool EmitBuiltinInitDwarfRegSizes(tree_node *exp, Value *&Result);
+  bool EmitBuiltinUnwindInit(tree_node *exp, Value *&Result);
 
   // Complex Math Expressions.
   void EmitLoadFromComplex(Value *&Real, Value *&Imag, Value *SrcComplex,





More information about the llvm-commits mailing list