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
This commit is contained in:
John McCall 2010-03-06 00:35:14 +00:00
Родитель 6d1828949d
Коммит 6374c3307e
5 изменённых файлов: 120 добавлений и 0 удалений

Просмотреть файл

@ -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));

Просмотреть файл

@ -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,

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;
}
};
}

Просмотреть файл

@ -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.