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 @@ -4173,14 +4173,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, @@ -4190,7 +4191,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. @@ -4200,9 +4201,22 @@ bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const override; }; + +class PPCAIX32TargetCodeGenInfo : public TargetCodeGenInfo { +public: + PPCAIX32TargetCodeGenInfo(CodeGenTypes &CGT, bool SoftFloatABI) + : TargetCodeGenInfo(new PowerPC32ABIInfo(CGT, SoftFloatABI)) {} + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { + return 1; // r1 is the dedicated stack pointer + } + + bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const override; +}; } -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(); @@ -4228,9 +4242,12 @@ // TODO: this implementation is now likely redundant with // DefaultABIInfo::EmitVAArg. -Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, - QualType Ty) const { - if (getTarget().getTriple().isOSDarwin()) { +Address PowerPC32ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, + QualType Ty) const { + // TODO: Add AIX ABI Info. Currently, we are relying on PowerPC32ABIInfo to + // emit the correct VAArg for AIX. + if (getTarget().getTriple().isOSDarwin() || + getTarget().getTriple().isOSAIX()) { auto TI = getContext().getTypeInfoInChars(Ty); TI.second = getParamTypeAlignment(Ty); @@ -4422,6 +4439,13 @@ return false; } +// TODO: Return true here until we verify that +// PPC32TargetCodeGenInfo::initDwarfEHRegSizeTable is correct for AIX as well +// and/or we have implemented Dwarf EH on AIX. +bool PPCAIX32TargetCodeGenInfo::initDwarfEHRegSizeTable( + CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const { + return true; +} // PowerPC-64 namespace { @@ -9990,9 +10014,12 @@ } case llvm::Triple::ppc: + if (Triple.isOSAIX()) + return SetCGInfo( + new PPCAIX32TargetCodeGenInfo(Types, CodeGenOpts.FloatABI == "soft")); return SetCGInfo( new PPC32TargetCodeGenInfo(Types, CodeGenOpts.FloatABI == "soft" || - getTarget().hasFeature("spe"))); + getTarget().hasFeature("spe"))); case llvm::Triple::ppc64: if (Triple.isOSBinFormatELF()) { PPC64_SVR4_ABIInfo::ABIKind Kind = PPC64_SVR4_ABIInfo::ELFv1; 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,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 diff --git a/clang/test/CodeGen/aix32-dwarf-error.c b/clang/test/CodeGen/aix32-dwarf-error.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/aix32-dwarf-error.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -verify -emit-llvm %s + +static unsigned char dwarf_reg_size_table[1024]; + +int test() { + __builtin_init_dwarf_reg_size_table(dwarf_reg_size_table); //expected-error {{cannot compile this __builtin_init_dwarf_reg_size_table yet}} + return __builtin_dwarf_sp_column(); +}