Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -223,6 +223,23 @@ return Addr; } +static Address emitRoundPointerUpToAlignment(CodeGenFunction &CGF, + llvm::Value *OverflowArgArea, + CharUnits Align) { + llvm::Value *PtrAsInt = OverflowArgArea; + // OverflowArgArea = (OverflowArgArea + Align - 1) & -Align; + PtrAsInt = CGF.Builder.CreatePtrToInt(PtrAsInt, CGF.IntPtrTy); + PtrAsInt = CGF.Builder.CreateAdd(PtrAsInt, + llvm::ConstantInt::get(CGF.IntPtrTy, Align.getQuantity() - 1)); + llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int32Ty, + -Align.getQuantity()); + PtrAsInt = CGF.Builder.CreateAnd(PtrAsInt, Mask); + PtrAsInt = CGF.Builder.CreateIntToPtr(PtrAsInt, + OverflowArgArea->getType(), + "overflow_arg_area.align"); + return Address(PtrAsInt, Align); +} + /// Emit va_arg for a platform using the common void* representation, /// where arguments are simply emitted in an array of slots on the stack. /// @@ -3543,9 +3560,14 @@ Builder.CreateStructGEP(VAList, 3, CharUnits::fromQuantity(4)); Address OverflowArea(Builder.CreateLoad(OverflowAreaAddr), OverflowAreaAlign); - - // The current address is the address of the varargs element. - // FIXME: do we not need to round up to alignment? + // Round up address of argument to alignment + llvm::Value *OverflowArgArea = OverflowArea.getPointer(); + CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty); + if (Align > OverflowAreaAlign) { + OverflowArea = emitRoundPointerUpToAlignment(CGF, OverflowArgArea, + Align); + } + MemAddr = Builder.CreateElementBitCast(OverflowArea, DirectTy); // Increase the overflow area. Index: test/CodeGen/ppc-varargs-struct.c =================================================================== --- test/CodeGen/ppc-varargs-struct.c +++ test/CodeGen/ppc-varargs-struct.c @@ -39,9 +39,13 @@ // CHECK-PPC:[[USING_OVERFLOW]] // CHECK-PPC-NEXT: [[OVERFLOW_AREA_P:%[0-9]+]] = getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* [[ARRAYDECAY]], i32 0, i32 3 // CHECK-PPC-NEXT: [[OVERFLOW_AREA:%.+]] = load i8*, i8** [[OVERFLOW_AREA_P]], align 4 -// CHECK-PPC-NEXT: [[MEMADDR:%.+]] = bitcast i8* [[OVERFLOW_AREA]] to %struct.x** -// CHECK-PPC-NEXT: [[NEW_OVERFLOW_AREA:%[0-9]+]] = getelementptr inbounds i8, i8* [[OVERFLOW_AREA]], i32 4 -// CHECK-PPC-NEXT: store i8* [[NEW_OVERFLOW_AREA]], i8** [[OVERFLOW_AREA_P]] +// CHECK-PPC-NEXT: %{{[0-9]+}} = ptrtoint i8* %{{[0-9]+}} to i32 +// CHECK-PPC-NEXT: %{{[0-9]+}} = add i32 %{{[0-9]+}}, 7 +// CHECK-PPC-NEXT: %{{[0-9]+}} = and i32 %{{[0-9]+}}, -8 +// CHECK-PPC-NEXT: %overflow_arg_area.align = inttoptr i32 %{{[0-9]+}} to i8* +// CHECK-PPC-NEXT: [[MEMADDR:%.+]] = bitcast i8* %overflow_arg_area.align to %struct.x** +// CHECK-PPC-NEXT: [[NEW_OVERFLOW_AREA:%[0-9]+]] = getelementptr inbounds i8, i8* %overflow_arg_area.align, i32 4 +// CHECK-PPC-NEXT: store i8* [[NEW_OVERFLOW_AREA:%[0-9]+]], i8** [[OVERFLOW_AREA_P]], align 4 // CHECK-PPC-NEXT: br label %[[CONT]] // // CHECK-PPC:[[CONT]]