[llvm-commits] [129555] Implement missing dwarf builtins, used by the libstdc++ unwinder.
clattner at apple.com
clattner at apple.com
Sat Jul 14 11:39:13 PDT 2007
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 = 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: apple-local/branches/llvm/gcc/llvm-internal.h
===================================================================
--- apple-local/branches/llvm/gcc/llvm-internal.h 2007-07-14 07:20:19 UTC (rev 129554)
+++ apple-local/branches/llvm/gcc/llvm-internal.h 2007-07-14 18:39:13 UTC (rev 129555)
@@ -562,6 +562,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