Revision: 129555
Author: clattner
Date: 2007-07-14 11:39:13 -0700 (Sat, 14 Jul 2007)
Log Message:
---
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 Paths:
--
apple-local/branches/llvm/gcc/llvm-convert.cpp
apple-local/branches/llvm/gcc/llvm-internal.h
Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp
===
--- apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-07-14 07:20:19 UTC
(rev 129554)
+++ apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-07-14 18:39:13 UTC
(rev 129555)
@@ -59,8 +59,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
@@ -4140,7 +4142,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)
@@ -4216,19 +4236,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)
@@ -4509,6 +4518,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 =