diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -369,7 +369,8 @@ } BuiltinVaListKind getBuiltinVaListKind() const override { - // This is the ELF definition, and is overridden by the Darwin sub-target + // This is the ELF definition, and is overridden by the Darwin and AIX + // sub-targets. return TargetInfo::PowerABIBuiltinVaList; } }; diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -4172,14 +4172,15 @@ // PowerPC-32 namespace { -/// PPC32_SVR4_ABIInfo - The 32-bit PowerPC ELF (SVR4) ABI information. -class PPC32_SVR4_ABIInfo : public DefaultABIInfo { +/// PowerPC32ABIInfo - The 32-bit PowerPC ABI information, used by PowerPC ELF +/// (SVR4), Darwin, and AIX. +class PowerPC32ABIInfo : public DefaultABIInfo { bool IsSoftFloatABI; CharUnits getParamTypeAlignment(QualType Ty) const; public: - PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, bool SoftFloatABI) + PowerPC32ABIInfo(CodeGen::CodeGenTypes &CGT, bool SoftFloatABI) : DefaultABIInfo(CGT), IsSoftFloatABI(SoftFloatABI) {} Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, @@ -4189,7 +4190,7 @@ class PPC32TargetCodeGenInfo : public TargetCodeGenInfo { public: PPC32TargetCodeGenInfo(CodeGenTypes &CGT, bool SoftFloatABI) - : TargetCodeGenInfo(new PPC32_SVR4_ABIInfo(CGT, SoftFloatABI)) {} + : TargetCodeGenInfo(new PowerPC32ABIInfo(CGT, SoftFloatABI)) {} int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { // This is recovered from gcc output. @@ -4201,7 +4202,7 @@ }; } -CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { +CharUnits PowerPC32ABIInfo::getParamTypeAlignment(QualType Ty) const { // Complex types are passed just like their elements if (const ComplexType *CTy = Ty->getAs()) Ty = CTy->getElementType(); @@ -4227,9 +4228,12 @@ // TODO: this implementation is now likely redundant with // DefaultABIInfo::EmitVAArg. -Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, +Address PowerPC32ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, QualType Ty) const { - if (getTarget().getTriple().isOSDarwin()) { + // TODO: Add AIX ABI Info. Currently, we are relying on PowerPC32ABIInfo to + // emit correct VAArg. + if (getTarget().getTriple().isOSDarwin() || + getTarget().getTriple().isOSAIX()) { auto TI = getContext().getTypeInfoInChars(Ty); TI.second = getParamTypeAlignment(Ty); diff --git a/clang/test/CodeGen/aix-vararg.c b/clang/test/CodeGen/aix-vararg.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/aix-vararg.c @@ -0,0 +1,39 @@ +// REQUIRES: powerpc-registered-target +// REQUIRES: asserts +// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -emit-llvm -o - %s | FileCheck %s --check-prefix=32BIT +// +void aix_varg(int a, ...) { + __builtin_va_list arg; + __builtin_va_start(arg, a); + __builtin_va_list arg2; + __builtin_va_arg(arg, int); + __builtin_va_copy(arg2, arg); + __builtin_va_end(arg); + __builtin_va_end(arg2); +} + +// 32BIT: define void @aix_varg(i32 %a, ...) #0 { +// 32BIT-NEXT: entry: +// 32BIT-NEXT: %a.addr = alloca i32, align 4 +// 32BIT-NEXT: %arg = alloca i8*, align 4 +// 32BIT-NEXT: %arg2 = alloca i8*, align 4 +// 32BIT-NEXT: store i32 %a, i32* %a.addr, align 4 +// 32BIT-NEXT: %arg1 = bitcast i8** %arg to i8* +// 32BIT-NEXT: call void @llvm.va_start(i8* %arg1) +// 32BIT-NEXT: %argp.cur = load i8*, i8** %arg, align 4 +// 32BIT-NEXT: %argp.next = getelementptr inbounds i8, i8* %argp.cur, i32 4 +// 32BIT-NEXT: store i8* %argp.next, i8** %arg, align 4 +// 32BIT-NEXT: %0 = bitcast i8* %argp.cur to i32* +// 32BIT-NEXT: %1 = load i32, i32* %0, align 4 +// 32BIT-NEXT: %2 = bitcast i8** %arg2 to i8* +// 32BIT-NEXT: %3 = bitcast i8** %arg to i8* +// 32BIT-NEXT: call void @llvm.va_copy(i8* %2, i8* %3) +// 32BIT-NEXT: %arg3 = bitcast i8** %arg to i8* +// 32BIT-NEXT: call void @llvm.va_end(i8* %arg3) +// 32BIT-NEXT: %arg24 = bitcast i8** %arg2 to i8* +// 32BIT-NEXT: call void @llvm.va_end(i8* %arg24) +// 32BIT-NEXT: ret void +// 32BIT-NEXT: } +// 32BIT: declare void @llvm.va_start(i8*) #1 +// 32BIT: declare void @llvm.va_copy(i8*, i8*) #1 +// 32BIT: declare void @llvm.va_end(i8*) #1