aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/ABIInfo.h19
-rw-r--r--lib/CodeGen/CGCall.cpp24
-rw-r--r--lib/CodeGen/TargetInfo.cpp3
3 files changed, 37 insertions, 9 deletions
diff --git a/lib/CodeGen/ABIInfo.h b/lib/CodeGen/ABIInfo.h
index 91b7742557..c90c84a352 100644
--- a/lib/CodeGen/ABIInfo.h
+++ b/lib/CodeGen/ABIInfo.h
@@ -70,11 +70,12 @@ namespace clang {
Kind TheKind;
llvm::PATypeHolder TypeData;
unsigned UIntData;
- bool BoolData;
+ bool BoolData0;
+ bool BoolData1;
ABIArgInfo(Kind K, const llvm::Type *TD=0,
- unsigned UI=0, bool B = false)
- : TheKind(K), TypeData(TD), UIntData(UI), BoolData(B) {}
+ unsigned UI=0, bool B0 = false, bool B1 = false)
+ : TheKind(K), TypeData(TD), UIntData(UI), BoolData0(B0), BoolData1(B1) {}
public:
ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
@@ -88,8 +89,9 @@ namespace clang {
static ABIArgInfo getIgnore() {
return ABIArgInfo(Ignore);
}
- static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true) {
- return ABIArgInfo(Indirect, 0, Alignment, ByVal);
+ static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true
+ , bool Realign = false) {
+ return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign);
}
static ABIArgInfo getExpand() {
return ABIArgInfo(Expand);
@@ -129,7 +131,12 @@ namespace clang {
bool getIndirectByVal() const {
assert(TheKind == Indirect && "Invalid kind!");
- return BoolData;
+ return BoolData0;
+ }
+
+ bool getIndirectRealign() const {
+ assert(TheKind == Indirect && "Invalid kind!");
+ return BoolData1;
}
void dump() const;
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 475dfa5c10..ae00040ec7 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -866,9 +866,29 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
switch (ArgI.getKind()) {
case ABIArgInfo::Indirect: {
llvm::Value *V = AI;
+
if (hasAggregateLLVMType(Ty)) {
- // Do nothing, aggregates and complex variables are accessed by
- // reference.
+ // Aggregates and complex variables are accessed by reference. All we
+ // need to do is realign the value, if requested
+ if (ArgI.getIndirectRealign()) {
+ llvm::Value *AlignedTemp = CreateMemTemp(Ty, "coerce");
+
+ // Copy from the incoming argument pointer to the temporary with the
+ // appropriate alignment.
+ //
+ // FIXME: We should have a common utility for generating an aggregate
+ // copy.
+ const llvm::Type *I8PtrTy = llvm::Type::getInt8PtrTy(VMContext, 0);
+ unsigned Size = getContext().getTypeSize(Ty) / 8;
+ Builder.CreateCall5(CGM.getMemCpyFn(I8PtrTy, I8PtrTy, IntPtrTy),
+ Builder.CreateBitCast(AlignedTemp, I8PtrTy),
+ Builder.CreateBitCast(V, I8PtrTy),
+ llvm::ConstantInt::get(IntPtrTy, Size),
+ Builder.getInt32(ArgI.getIndirectAlign()),
+ /*Volatile=*/Builder.getInt1(false));
+
+ V = AlignedTemp;
+ }
} else {
// Load scalar value from indirect argument.
unsigned Alignment = getContext().getTypeAlignInChars(Ty).getQuantity();
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index ab6f7c7dd0..3ee4d1ad6d 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -75,7 +75,8 @@ void ABIArgInfo::dump() const {
break;
case Indirect:
OS << "Indirect Align=" << getIndirectAlign()
- << " Byal=" << getIndirectByVal();
+ << " Byal=" << getIndirectByVal()
+ << " Realign=" << getIndirectRealign();
break;
case Expand:
OS << "Expand";