summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/ABIInfo.h32
-rw-r--r--clang/lib/CodeGen/CGCall.cpp42
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp21
-rw-r--r--clang/test/CodeGen/stdcall-fastcall.c4
4 files changed, 64 insertions, 35 deletions
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h
index 1dd1d195c21..da6d035dfaf 100644
--- a/clang/lib/CodeGen/ABIInfo.h
+++ b/clang/lib/CodeGen/ABIInfo.h
@@ -70,46 +70,52 @@ namespace clang {
private:
Kind TheKind;
llvm::Type *TypeData;
- llvm::Type *PaddingType; // Currently allowed only for Direct.
+ llvm::Type *PaddingType;
unsigned UIntData;
bool BoolData0;
bool BoolData1;
bool InReg;
+ bool PaddingInReg;
ABIArgInfo(Kind K, llvm::Type *TD, unsigned UI, bool B0, bool B1, bool IR,
- llvm::Type* P)
+ bool PIR, llvm::Type* P)
: TheKind(K), TypeData(TD), PaddingType(P), UIntData(UI), BoolData0(B0),
- BoolData1(B1), InReg(IR) {}
+ BoolData1(B1), InReg(IR), PaddingInReg(PIR) {}
public:
ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
static ABIArgInfo getDirect(llvm::Type *T = 0, unsigned Offset = 0,
llvm::Type *Padding = 0) {
- return ABIArgInfo(Direct, T, Offset, false, false, false, Padding);
+ return ABIArgInfo(Direct, T, Offset, false, false, false, false, Padding);
}
static ABIArgInfo getDirectInReg(llvm::Type *T = 0) {
- return ABIArgInfo(Direct, T, 0, false, false, true, 0);
+ return ABIArgInfo(Direct, T, 0, false, false, true, false, 0);
}
static ABIArgInfo getExtend(llvm::Type *T = 0) {
- return ABIArgInfo(Extend, T, 0, false, false, false, 0);
+ return ABIArgInfo(Extend, T, 0, false, false, false, false, 0);
}
static ABIArgInfo getExtendInReg(llvm::Type *T = 0) {
- return ABIArgInfo(Extend, T, 0, false, false, true, 0);
+ return ABIArgInfo(Extend, T, 0, false, false, true, false, 0);
}
static ABIArgInfo getIgnore() {
- return ABIArgInfo(Ignore, 0, 0, false, false, false, 0);
+ return ABIArgInfo(Ignore, 0, 0, false, false, false, false, 0);
}
static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true
, bool Realign = false) {
- return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, false, 0);
+ return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, false, false, 0);
}
static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true
, bool Realign = false) {
- return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, true, 0);
+ return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, true, false, 0);
}
static ABIArgInfo getExpand() {
- return ABIArgInfo(Expand, 0, 0, false, false, false, 0);
+ return ABIArgInfo(Expand, 0, 0, false, false, false, false, 0);
+ }
+ static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
+ llvm::Type *Padding) {
+ return ABIArgInfo(Expand, 0, 0, false, false, false, PaddingInReg,
+ Padding);
}
Kind getKind() const { return TheKind; }
@@ -133,6 +139,10 @@ namespace clang {
return PaddingType;
}
+ bool getPaddingInReg() const {
+ return PaddingInReg;
+ }
+
llvm::Type *getCoerceToType() const {
assert(canHaveCoerceToType() && "Invalid kind!");
return TypeData;
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index afcf541a3d3..b356e640a1c 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -867,6 +867,10 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
ie = FI.arg_end(); it != ie; ++it) {
const ABIArgInfo &argAI = it->info;
+ // Insert a padding type to ensure proper alignment.
+ if (llvm::Type *PaddingType = argAI.getPaddingType())
+ argTypes.push_back(PaddingType);
+
switch (argAI.getKind()) {
case ABIArgInfo::Ignore:
break;
@@ -880,9 +884,6 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
case ABIArgInfo::Extend:
case ABIArgInfo::Direct: {
- // Insert a padding type to ensure proper alignment.
- if (llvm::Type *PaddingType = argAI.getPaddingType())
- argTypes.push_back(PaddingType);
// If the coerce-to type is a first class aggregate, flatten it. Either
// way is semantically identical, but fast-isel and the optimizer
// generally likes scalar values better than FCAs.
@@ -1019,6 +1020,18 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
const ABIArgInfo &AI = it->info;
llvm::AttrBuilder Attrs;
+ if (AI.getPaddingType()) {
+ if (AI.getPaddingInReg()) {
+ llvm::AttrBuilder PadAttrs;
+ PadAttrs.addAttribute(llvm::Attributes::InReg);
+
+ llvm::Attributes A =llvm::Attributes::get(getLLVMContext(), PadAttrs);
+ PAL.push_back(llvm::AttributeWithIndex::get(Index, A));
+ }
+ // Increment Index if there is padding.
+ ++Index;
+ }
+
// 'restrict' -> 'noalias' is done in EmitFunctionProlog when we
// have the corresponding parameter variable. It doesn't make
// sense to do it here because parameters are so messed up.
@@ -1035,9 +1048,6 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// FIXME: handle sseregparm someday...
- // Increment Index if there is padding.
- Index += (AI.getPaddingType() != 0);
-
if (llvm::StructType *STy =
dyn_cast<llvm::StructType>(AI.getCoerceToType())) {
unsigned Extra = STy->getNumElements()-1; // 1 will be added below.
@@ -1155,6 +1165,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
bool isPromoted =
isa<ParmVarDecl>(Arg) && cast<ParmVarDecl>(Arg)->isKNRPromoted();
+ // Skip the dummy padding argument.
+ if (ArgI.getPaddingType())
+ ++AI;
+
switch (ArgI.getKind()) {
case ABIArgInfo::Indirect: {
llvm::Value *V = AI;
@@ -1196,9 +1210,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
case ABIArgInfo::Extend:
case ABIArgInfo::Direct: {
- // Skip the dummy padding argument.
- if (ArgI.getPaddingType())
- ++AI;
// If we have the trivial case, handle it with no muss and fuss.
if (!isa<llvm::StructType>(ArgI.getCoerceToType()) &&
@@ -1976,6 +1987,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
unsigned TypeAlign =
getContext().getTypeAlignInChars(I->Ty).getQuantity();
+
+ // Insert a padding argument to ensure proper alignment.
+ if (llvm::Type *PaddingType = ArgInfo.getPaddingType()) {
+ Args.push_back(llvm::UndefValue::get(PaddingType));
+ ++IRArgNo;
+ }
+
switch (ArgInfo.getKind()) {
case ABIArgInfo::Indirect: {
if (RV.isScalar() || RV.isComplex()) {
@@ -2031,12 +2049,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
case ABIArgInfo::Extend:
case ABIArgInfo::Direct: {
- // Insert a padding argument to ensure proper alignment.
- if (llvm::Type *PaddingType = ArgInfo.getPaddingType()) {
- Args.push_back(llvm::UndefValue::get(PaddingType));
- ++IRArgNo;
- }
-
if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) &&
ArgInfo.getCoerceToType() == ConvertType(info_it->type) &&
ArgInfo.getDirectOffset() == 0) {
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 534c8f685d5..2c2d17df77b 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -531,7 +531,7 @@ class X86_32ABIInfo : public ABIInfo {
ABIArgInfo classifyArgumentType(QualType RetTy, unsigned &FreeRegs,
bool IsFastCall) const;
bool shouldUseInReg(QualType Ty, unsigned &FreeRegs,
- bool IsFastCall) const;
+ bool IsFastCall, bool &NeedsPadding) const;
public:
@@ -807,7 +807,8 @@ X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const {
}
bool X86_32ABIInfo::shouldUseInReg(QualType Ty, unsigned &FreeRegs,
- bool IsFastCall) const {
+ bool IsFastCall, bool &NeedsPadding) const {
+ NeedsPadding = false;
Class C = classify(Ty);
if (C == Float)
return false;
@@ -838,6 +839,9 @@ bool X86_32ABIInfo::shouldUseInReg(QualType Ty, unsigned &FreeRegs,
if (Ty->isReferenceType())
return true;
+ if (FreeRegs)
+ NeedsPadding = true;
+
return false;
}
@@ -864,16 +868,18 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
if (isEmptyRecord(getContext(), Ty, true))
return ABIArgInfo::getIgnore();
- if (shouldUseInReg(Ty, FreeRegs, IsFastCall)) {
+ llvm::LLVMContext &LLVMContext = getVMContext();
+ llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
+ bool NeedsPadding;
+ if (shouldUseInReg(Ty, FreeRegs, IsFastCall, NeedsPadding)) {
unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32;
- llvm::LLVMContext &LLVMContext = getVMContext();
- llvm::Type *Int32 = llvm::Type::getInt32Ty(LLVMContext);
SmallVector<llvm::Type*, 3> Elements;
for (unsigned I = 0; I < SizeInRegs; ++I)
Elements.push_back(Int32);
llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
return ABIArgInfo::getDirectInReg(Result);
}
+ llvm::IntegerType *PaddingType = NeedsPadding ? Int32 : 0;
// Expand small (<= 128-bit) record types when we know that the stack layout
// of those arguments will match the struct. This is important because the
@@ -881,7 +887,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
// optimizations.
if (getContext().getTypeSize(Ty) <= 4*32 &&
canExpandIndirectArgument(Ty, getContext()))
- return ABIArgInfo::getExpand();
+ return ABIArgInfo::getExpandWithPadding(IsFastCall, PaddingType);
return getIndirectResult(Ty, true, FreeRegs);
}
@@ -914,7 +920,8 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
- bool InReg = shouldUseInReg(Ty, FreeRegs, IsFastCall);
+ bool NeedsPadding;
+ bool InReg = shouldUseInReg(Ty, FreeRegs, IsFastCall, NeedsPadding);
if (Ty->isPromotableIntegerType()) {
if (InReg)
diff --git a/clang/test/CodeGen/stdcall-fastcall.c b/clang/test/CodeGen/stdcall-fastcall.c
index dac2a3a1428..d5181788228 100644
--- a/clang/test/CodeGen/stdcall-fastcall.c
+++ b/clang/test/CodeGen/stdcall-fastcall.c
@@ -62,7 +62,7 @@ struct S1 {
void __attribute__((fastcall)) foo2(struct S1 y);
void bar2(struct S1 y) {
// CHECK: define void @bar2
- // CHECK: call x86_fastcallcc void @foo2(i32 %
+ // CHECK: call x86_fastcallcc void @foo2(i32 inreg undef, i32 %
foo2(y);
}
@@ -110,7 +110,7 @@ void bar7(int a, struct S1 b, int c) {
void __attribute__((fastcall)) foo8(struct S1 a, int b);
void bar8(struct S1 a, int b) {
// CHECK: define void @bar8
- // CHECK: call x86_fastcallcc void @foo8(i32 %{{.*}}, i32 inreg %
+ // CHECK: call x86_fastcallcc void @foo8(i32 inreg undef, i32 %{{.*}}, i32 inreg %
foo8(a, b);
}
OpenPOWER on IntegriCloud