Index: clang/lib/Basic/Targets/PPC.h =================================================================== --- clang/lib/Basic/Targets/PPC.h +++ 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; } }; Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -4172,7 +4172,8 @@ // PowerPC-32 namespace { -/// PPC32_SVR4_ABIInfo - The 32-bit PowerPC ELF (SVR4) ABI information. +/// PPC32_SVR4_ABIInfo - The 32-bit PowerPC ABI information, used by PowerPC ELF +/// (SVR4), Darwin and AIX. class PPC32_SVR4_ABIInfo : public DefaultABIInfo { bool IsSoftFloatABI; @@ -4229,7 +4230,10 @@ // DefaultABIInfo::EmitVAArg. Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, QualType Ty) const { - if (getTarget().getTriple().isOSDarwin()) { + // TODO: Add AIX ABI Info. Currently, we are relying on PPC32_SVR4_ABIInfo to + // emit correct VAArg. + if (getTarget().getTriple().isOSDarwin() || + getTarget().getTriple().isOSAIX()) { auto TI = getContext().getTypeInfoInChars(Ty); TI.second = getParamTypeAlignment(Ty); Index: clang/test/CodeGen/aix-vararg.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aix-vararg.c @@ -0,0 +1,40 @@ +// REQUIRES: powerpc-registered-target +// REQUIRES: asserts +// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -emit-llvm -o - %s | FileCheck %s --check-prefix=32BIT +#include + +void aix_varg(int a, ...) { + va_list arg; + va_start(arg, a); + va_list arg2; + va_arg(arg, int); + va_copy(arg2, arg); + va_end(arg); + 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