From 6374c3307e2d73348f7b8cc73eeeb0998ad0ac94 Mon Sep 17 00:00:00 2001 From: John McCall Date: Sat, 6 Mar 2010 00:35:14 +0000 Subject: [PATCH] Implement __builtin_dwarf_sp_column for i386 (Darwin and not), x86-64 (all), and ARM. Implement __builtin_init_dwarf_reg_size_table for i386 (both) and x86-64 (all). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97859 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 16 +++++++ lib/CodeGen/CodeGenModule.cpp | 5 +++ lib/CodeGen/CodeGenModule.h | 1 + lib/CodeGen/TargetInfo.cpp | 81 +++++++++++++++++++++++++++++++++++ lib/CodeGen/TargetInfo.h | 17 ++++++++ 5 files changed, 120 insertions(+) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index df6ac7fc24..8703c381b2 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -387,6 +387,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *Result = getTargetHooks().encodeReturnAddress(*this, Address); return RValue::get(Result); } + case Builtin::BI__builtin_dwarf_sp_column: { + const llvm::IntegerType *Ty + = cast(ConvertType(E->getType())); + int Column = getTargetHooks().getDwarfEHStackPointer(CGM); + if (Column == -1) { + CGM.ErrorUnsupported(E, "__builtin_dwarf_sp_column"); + return RValue::get(llvm::UndefValue::get(Ty)); + } + return RValue::get(llvm::ConstantInt::get(Ty, Column, true)); + } + case Builtin::BI__builtin_init_dwarf_reg_size_table: { + Value *Address = EmitScalarExpr(E->getArg(0)); + if (getTargetHooks().initDwarfEHRegSizeTable(*this, Address)) + CGM.ErrorUnsupported(E, "__builtin_init_dwarf_reg_size_table"); + return RValue::get(llvm::UndefValue::get(ConvertType(E->getType()))); + } case Builtin::BI__builtin_eh_return: { Value *Int = EmitScalarExpr(E->getArg(0)); Value *Ptr = EmitScalarExpr(E->getArg(1)); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index e6e9b1a595..f664b76783 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -33,6 +33,7 @@ #include "llvm/Module.h" #include "llvm/Intrinsics.h" #include "llvm/LLVMContext.h" +#include "llvm/ADT/Triple.h" #include "llvm/Target/TargetData.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -89,6 +90,10 @@ void CodeGenModule::Release() { EmitLLVMUsed(); } +bool CodeGenModule::isTargetDarwin() const { + return getContext().Target.getTriple().getOS() == llvm::Triple::Darwin; +} + /// ErrorUnsupported - Print out an error that codegen doesn't support the /// specified stmt yet. void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type, diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index c839b42559..c86f8b45bc 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -204,6 +204,7 @@ public: const llvm::TargetData &getTargetData() const { return TheTargetData; } llvm::LLVMContext &getLLVMContext() { return VMContext; } const TargetCodeGenInfo &getTargetCodeGenInfo() const; + bool isTargetDarwin() const; /// getDeclVisibilityMode - Compute the visibility of the decl \arg D. LangOptions::VisibilityMode getDeclVisibilityMode(const Decl *D) const; diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index f4ec914a4e..cb6a7df68d 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -328,6 +328,16 @@ public: void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const; + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { + // Darwin uses different dwarf register numbers for EH. + if (CGM.isTargetDarwin()) return 5; + + return 4; + } + + bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const; }; } @@ -568,6 +578,51 @@ void X86_32TargetCodeGenInfo::SetTargetAttributes(const Decl *D, } } +bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable( + CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + CodeGen::CGBuilderTy &Builder = CGF.Builder; + llvm::LLVMContext &Context = CGF.getLLVMContext(); + + const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); + + // 0-7 are the eight integer registers; the order is different + // on Darwin (for EH), but the range is the same. + // 8 is %eip. + for (unsigned I = 0, E = 9; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Four8, Slot); + } + + if (CGF.CGM.isTargetDarwin()) { + // 12-16 are st(0..4). Not sure why we stop at 4. + // These have size 16, which is sizeof(long double) on + // platforms with 8-byte alignment for that type. + llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16); + for (unsigned I = 12, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Sixteen8, Slot); + } + + } else { + // 9 is %eflags, which doesn't get a size on Darwin for some + // reason. + Builder.CreateStore(Four8, Builder.CreateConstInBoundsGEP1_32(Address, 9)); + + // 11-16 are st(0..5). Not sure why we stop at 5. + // These have size 12, which is sizeof(long double) on + // platforms with 4-byte alignment for that type. + llvm::Value *Twelve8 = llvm::ConstantInt::get(i8, 12); + for (unsigned I = 11, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Twelve8, Slot); + } + } + + return false; +} + namespace { /// X86_64ABIInfo - The X86_64 ABI information. class X86_64ABIInfo : public ABIInfo { @@ -656,6 +711,28 @@ public: class X86_64TargetCodeGenInfo : public TargetCodeGenInfo { public: X86_64TargetCodeGenInfo():TargetCodeGenInfo(new X86_64ABIInfo()) {} + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { + return 7; + } + + bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + CodeGen::CGBuilderTy &Builder = CGF.Builder; + llvm::LLVMContext &Context = CGF.getLLVMContext(); + + const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); + + // 0-16 are the 16 integer registers. + // 17 is %rip. + for (unsigned I = 0, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Eight8, Slot); + } + + return false; + } }; } @@ -1559,6 +1636,10 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo { public: ARMTargetCodeGenInfo(ARMABIInfo::ABIKind K) :TargetCodeGenInfo(new ARMABIInfo(K)) {} + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { + return 13; + } }; } diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h index 9e80081429..f0a78243ff 100644 --- a/lib/CodeGen/TargetInfo.h +++ b/lib/CodeGen/TargetInfo.h @@ -56,6 +56,23 @@ namespace clang { /// through such registers. virtual bool extendPointerWithSExt() const { return false; } + /// Determines the DWARF register number for the stack pointer, for + /// exception-handling purposes. Implements __builtin_dwarf_sp_column. + /// + /// Returns -1 if the operation is unsupported by this target. + virtual int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { + return -1; + } + + /// Initializes the given DWARF EH register-size table, a char*. + /// Implements __builtin_init_dwarf_reg_size_table. + /// + /// Returns true if the operation is unsupported by this target. + virtual bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + return true; + } + /// Performs the code-generation required to convert a return /// address as stored by the system into the actual address of the /// next instruction that will be executed.