summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-03-06 00:35:14 +0000
committerJohn McCall <rjmccall@apple.com>2010-03-06 00:35:14 +0000
commit6374c3307e2d73348f7b8cc73eeeb0998ad0ac94 (patch)
treea861c0e7420f3ff6928a945d6aa09391643442cd
parent6d1828949df82e2f2bb2606ea7a3b40029a7f9e2 (diff)
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
-rw-r--r--lib/CodeGen/CGBuiltin.cpp16
-rw-r--r--lib/CodeGen/CodeGenModule.cpp5
-rw-r--r--lib/CodeGen/CodeGenModule.h1
-rw-r--r--lib/CodeGen/TargetInfo.cpp81
-rw-r--r--lib/CodeGen/TargetInfo.h17
5 files changed, 120 insertions, 0 deletions
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<llvm::IntegerType>(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.