Skip to content

Commit 402257b

Browse files
committedDec 4, 2015
[PowerPC] Fix calculating address of arguments on stack for variadic func
Fix calculating address of arguments larger than 32 bit on stack for variadic functions (rounding up address to alignment) on ppc32 architecture. Patch by Strahinja Petrovic. Differential Revision: http://reviews.llvm.org/D14871 llvm-svn: 254670
1 parent 2a3dbe8 commit 402257b

File tree

3 files changed

+43
-32
lines changed

3 files changed

+43
-32
lines changed
 

‎clang/lib/CodeGen/TargetInfo.cpp

+34-28
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,23 @@ void ABIArgInfo::dump() const {
162162
OS << ")\n";
163163
}
164164

165+
// Dynamically round a pointer up to a multiple of the given alignment.
166+
static llvm::Value *emitRoundPointerUpToAlignment(CodeGenFunction &CGF,
167+
llvm::Value *Ptr,
168+
CharUnits Align) {
169+
llvm::Value *PtrAsInt = Ptr;
170+
// OverflowArgArea = (OverflowArgArea + Align - 1) & -Align;
171+
PtrAsInt = CGF.Builder.CreatePtrToInt(PtrAsInt, CGF.IntPtrTy);
172+
PtrAsInt = CGF.Builder.CreateAdd(PtrAsInt,
173+
llvm::ConstantInt::get(CGF.IntPtrTy, Align.getQuantity() - 1));
174+
PtrAsInt = CGF.Builder.CreateAnd(PtrAsInt,
175+
llvm::ConstantInt::get(CGF.IntPtrTy, -Align.getQuantity()));
176+
PtrAsInt = CGF.Builder.CreateIntToPtr(PtrAsInt,
177+
Ptr->getType(),
178+
Ptr->getName() + ".aligned");
179+
return PtrAsInt;
180+
}
181+
165182
/// Emit va_arg for a platform using the common void* representation,
166183
/// where arguments are simply emitted in an array of slots on the stack.
167184
///
@@ -193,17 +210,10 @@ static Address emitVoidPtrDirectVAArg(CodeGenFunction &CGF,
193210
// If the CC aligns values higher than the slot size, do so if needed.
194211
Address Addr = Address::invalid();
195212
if (AllowHigherAlign && DirectAlign > SlotSize) {
196-
llvm::Value *PtrAsInt = Ptr;
197-
PtrAsInt = CGF.Builder.CreatePtrToInt(PtrAsInt, CGF.IntPtrTy);
198-
PtrAsInt = CGF.Builder.CreateAdd(PtrAsInt,
199-
llvm::ConstantInt::get(CGF.IntPtrTy, DirectAlign.getQuantity() - 1));
200-
PtrAsInt = CGF.Builder.CreateAnd(PtrAsInt,
201-
llvm::ConstantInt::get(CGF.IntPtrTy, -DirectAlign.getQuantity()));
202-
Addr = Address(CGF.Builder.CreateIntToPtr(PtrAsInt, Ptr->getType(),
203-
"argp.cur.aligned"),
204-
DirectAlign);
213+
Addr = Address(emitRoundPointerUpToAlignment(CGF, Ptr, DirectAlign),
214+
DirectAlign);
205215
} else {
206-
Addr = Address(Ptr, SlotSize);
216+
Addr = Address(Ptr, SlotSize);
207217
}
208218

209219
// Advance the pointer past the argument, then store that back.
@@ -3072,19 +3082,10 @@ static Address EmitX86_64VAArgFromMemory(CodeGenFunction &CGF,
30723082
// byte boundary if alignment needed by type exceeds 8 byte boundary.
30733083
// It isn't stated explicitly in the standard, but in practice we use
30743084
// alignment greater than 16 where necessary.
3075-
uint64_t Align = CGF.getContext().getTypeAlignInChars(Ty).getQuantity();
3076-
if (Align > 8) {
3077-
// overflow_arg_area = (overflow_arg_area + align - 1) & -align;
3078-
llvm::Value *Offset =
3079-
llvm::ConstantInt::get(CGF.Int64Ty, Align - 1);
3080-
overflow_arg_area = CGF.Builder.CreateGEP(overflow_arg_area, Offset);
3081-
llvm::Value *AsInt = CGF.Builder.CreatePtrToInt(overflow_arg_area,
3082-
CGF.Int64Ty);
3083-
llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int64Ty, -(uint64_t)Align);
3084-
overflow_arg_area =
3085-
CGF.Builder.CreateIntToPtr(CGF.Builder.CreateAnd(AsInt, Mask),
3086-
overflow_arg_area->getType(),
3087-
"overflow_arg_area.align");
3085+
CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty);
3086+
if (Align > CharUnits::fromQuantity(8)) {
3087+
overflow_arg_area = emitRoundPointerUpToAlignment(CGF, overflow_arg_area,
3088+
Align);
30883089
}
30893090

30903091
// AMD64-ABI 3.5.7p5: Step 8. Fetch type from l->overflow_arg_area.
@@ -3106,7 +3107,7 @@ static Address EmitX86_64VAArgFromMemory(CodeGenFunction &CGF,
31063107
CGF.Builder.CreateStore(overflow_arg_area, overflow_arg_area_p);
31073108

31083109
// AMD64-ABI 3.5.7p5: Step 11. Return the fetched type.
3109-
return Address(Res, CharUnits::fromQuantity(Align));
3110+
return Address(Res, Align);
31103111
}
31113112

31123113
Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
@@ -3541,11 +3542,16 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList,
35413542

35423543
Address OverflowAreaAddr =
35433544
Builder.CreateStructGEP(VAList, 3, CharUnits::fromQuantity(4));
3544-
Address OverflowArea(Builder.CreateLoad(OverflowAreaAddr),
3545+
Address OverflowArea(Builder.CreateLoad(OverflowAreaAddr, "argp.cur"),
35453546
OverflowAreaAlign);
3546-
3547-
// The current address is the address of the varargs element.
3548-
// FIXME: do we not need to round up to alignment?
3547+
// Round up address of argument to alignment
3548+
CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty);
3549+
if (Align > OverflowAreaAlign) {
3550+
llvm::Value *Ptr = OverflowArea.getPointer();
3551+
OverflowArea = Address(emitRoundPointerUpToAlignment(CGF, Ptr, Align),
3552+
Align);
3553+
}
3554+
35493555
MemAddr = Builder.CreateElementBitCast(OverflowArea, DirectTy);
35503556

35513557
// Increase the overflow area.

‎clang/test/CodeGen/ppc-varargs-struct.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,13 @@ void testva (int n, ...)
3939
// CHECK-PPC:[[USING_OVERFLOW]]
4040
// CHECK-PPC-NEXT: [[OVERFLOW_AREA_P:%[0-9]+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* [[ARRAYDECAY]], i32 0, i32 3
4141
// CHECK-PPC-NEXT: [[OVERFLOW_AREA:%.+]] = load i8*, i8** [[OVERFLOW_AREA_P]], align 4
42-
// CHECK-PPC-NEXT: [[MEMADDR:%.+]] = bitcast i8* [[OVERFLOW_AREA]] to %struct.x**
43-
// CHECK-PPC-NEXT: [[NEW_OVERFLOW_AREA:%[0-9]+]] = getelementptr inbounds i8, i8* [[OVERFLOW_AREA]], i32 4
44-
// CHECK-PPC-NEXT: store i8* [[NEW_OVERFLOW_AREA]], i8** [[OVERFLOW_AREA_P]]
42+
// CHECK-PPC-NEXT: %{{[0-9]+}} = ptrtoint i8* %argp.cur to i32
43+
// CHECK-PPC-NEXT: %{{[0-9]+}} = add i32 %{{[0-9]+}}, 7
44+
// CHECK-PPC-NEXT: %{{[0-9]+}} = and i32 %{{[0-9]+}}, -8
45+
// CHECK-PPC-NEXT: %argp.cur.aligned = inttoptr i32 %{{[0-9]+}} to i8*
46+
// CHECK-PPC-NEXT: [[MEMADDR:%.+]] = bitcast i8* %argp.cur.aligned to %struct.x**
47+
// CHECK-PPC-NEXT: [[NEW_OVERFLOW_AREA:%[0-9]+]] = getelementptr inbounds i8, i8* %argp.cur.aligned, i32 4
48+
// CHECK-PPC-NEXT: store i8* [[NEW_OVERFLOW_AREA:%[0-9]+]], i8** [[OVERFLOW_AREA_P]], align 4
4549
// CHECK-PPC-NEXT: br label %[[CONT]]
4650
//
4751
// CHECK-PPC:[[CONT]]

‎clang/test/CodeGen/x86_64-arguments.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,8 @@ void func43(SA s) {
336336

337337
// CHECK-LABEL: define i32 @f44
338338
// CHECK: ptrtoint
339-
// CHECK-NEXT: and {{.*}}, -32
339+
// CHECK-NEXT: add i64 %{{[0-9]+}}, 31
340+
// CHECK-NEXT: and i64 %{{[0-9]+}}, -32
340341
// CHECK-NEXT: inttoptr
341342
typedef int T44 __attribute((vector_size(32)));
342343
struct s44 { T44 x; int y; };

0 commit comments

Comments
 (0)