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 @@ -4709,13 +4709,12 @@ // }; bool isI64 = Ty->isIntegerType() && getContext().getTypeSize(Ty) == 64; - bool isInt = - Ty->isIntegerType() || Ty->isPointerType() || Ty->isAggregateType(); + bool isInt = !Ty->isFloatingType(); bool isF64 = Ty->isFloatingType() && getContext().getTypeSize(Ty) == 64; // All aggregates are passed indirectly? That doesn't seem consistent // with the argument-lowering code. - bool isIndirect = Ty->isAggregateType(); + bool isIndirect = isAggregateTypeForABI(Ty); CGBuilderTy &Builder = CGF.Builder; diff --git a/clang/test/CodeGenCXX/ppc32-varargs-method.cpp b/clang/test/CodeGenCXX/ppc32-varargs-method.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/ppc32-varargs-method.cpp @@ -0,0 +1,20 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc-unknown-openbsd -emit-llvm -o - %s | FileCheck %s + +#include + +class something; +typedef void (something::*method)(); + +method test(va_list ap) { + return va_arg(ap, method); +} +// CHECK: using_regs: +// CHECK-NEXT: getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %{{[0-9]+}}, i32 0, i32 4 +// CHECK-NEXT: load i8*, i8** %{{[0-9]+}}, align 4 +// CHECK-NEXT: mul i8 %numUsedRegs, 4 +// CHECK-NEXT: getelementptr inbounds i8, i8* %{{[0-9]+}}, i8 %{{[0-9]+}} +// CHECK-NEXT: bitcast i8* %{{[0-9]+}} to { i32, i32 }** +// CHECK-NEXT: add i8 %numUsedRegs, 1 +// CHECK-NEXT: store i8 %{{[0-9]+}}, i8* %gpr, align 4 +// CHECK-NEXT: br label %cont diff --git a/clang/test/CodeGenObjC/ppc32-varargs-id.m b/clang/test/CodeGenObjC/ppc32-varargs-id.m new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenObjC/ppc32-varargs-id.m @@ -0,0 +1,33 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc-unknown-openbsd -fblocks -emit-llvm -o - %s | FileCheck %s + +#include + +id testObject(va_list ap) { + return va_arg(ap, id); +} +// CHECK: @testObject +// CHECK: using_regs: +// CHECK-NEXT: getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %{{[0-9]+}}, i32 0, i32 4 +// CHECK-NEXT: load i8*, i8** %{{[0-9]+}}, align 4 +// CHECK-NEXT: mul i8 %numUsedRegs, 4 +// CHECK-NEXT: getelementptr inbounds i8, i8* %{{[0-9]+}}, i8 %{{[0-9]+}} +// CHECK-NEXT: bitcast i8* %{{[0-9]+}} to i8** +// CHECK-NEXT: add i8 %numUsedRegs, 1 +// CHECK-NEXT: store i8 %{{[0-9]+}}, i8* %gpr, align 4 +// CHECK-NEXT: br label %cont + +typedef void (^block)(void); +block testBlock(va_list ap) { + return va_arg(ap, block); +} +// CHECK: @testBlock +// CHECK: using_regs: +// CHECK-NEXT: getelementptr inbounds %struct.__va_list_tag, %struct.__va_list_tag* %{{[0-9]+}}, i32 0, i32 4 +// CHECK-NEXT: load i8*, i8** %{{[0-9]+}}, align 4 +// CHECK-NEXT: mul i8 %numUsedRegs, 4 +// CHECK-NEXT: getelementptr inbounds i8, i8* %{{[0-9]+}}, i8 %{{[0-9]+}} +// CHECK-NEXT: bitcast i8* %{{[0-9]+}} to void ()** +// CHECK-NEXT: add i8 %numUsedRegs, 1 +// CHECK-NEXT: store i8 %{{[0-9]+}}, i8* %gpr, align 4 +// CHECK-NEXT: br label %cont