Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -4444,6 +4444,39 @@ } }; +class EFIMachOX86_64TargetInfo : public DarwinX86_64TargetInfo { +public: + EFIMachOX86_64TargetInfo(const llvm::Triple &Triple, + const TargetOptions &Opts) + : DarwinX86_64TargetInfo(Triple, Opts) {} + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + DarwinX86_64TargetInfo::getTargetDefines(Opts, Builder); + addCygMingDefines(Opts, Builder); + } + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::CharPtrBuiltinVaList; + } + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + switch (CC) { + case CC_X86StdCall: + case CC_X86ThisCall: + case CC_X86FastCall: + return CCCR_Ignore; + case CC_C: + case CC_X86VectorCall: + case CC_IntelOclBicc: + case CC_X86_64SysV: + return CCCR_OK; + default: + return CCCR_Warning; + } + } +}; + class OpenBSDX86_64TargetInfo : public OpenBSDTargetInfo { public: OpenBSDX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) @@ -8362,8 +8395,11 @@ } case llvm::Triple::x86_64: - if (Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) + if (Triple.isOSDarwin() || + (!Triple.isOSWindows() && Triple.isOSBinFormatMachO())) return new DarwinX86_64TargetInfo(Triple, Opts); + if (Triple.isOSWindows() && Triple.isOSBinFormatMachO()) + return new EFIMachOX86_64TargetInfo(Triple, Opts); switch (os) { case llvm::Triple::CloudABI: Index: test/CodeGen/windows-macho.c =================================================================== --- /dev/null +++ test/CodeGen/windows-macho.c @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-windows-macho -emit-llvm -Os %s -o - \ +// RUN: | FileCheck %s + +// Test that, when we compile a function that uses varargs on a +// Windows-with-Mach-O triple, we can actually compile it, and it actually +// conforms to the Win64 ABI. + +// PR27663 + +// CHECK-LABEL: i32 @va_sum +int va_sum(unsigned int count, ...) { + int sum = 0; + __builtin_ms_va_list ap; + + __builtin_ms_va_start(ap, count); + // CHECK: %[[AP:.*]] = alloca i8* + // CHECK: call void @llvm.va_start + while (count) { + sum += __builtin_va_arg(ap, int); + // CHECK: %[[AP_CUR_PRE:.*]] = load i8*, i8** %[[AP]] + // CHECK: %[[AP_CUR:.*]] = phi i8* [ %[[AP_NEXT:.*]], {{.*}} ], [ %[[AP_CUR_PRE]], {{.*}} ] + // CHECK: %[[AP_NEXT]] = getelementptr inbounds i8, i8* %[[AP_CUR]], i64 8 + // CHECK-NEXT: store i8* %[[AP_NEXT]], i8** %[[AP]] + // CHECK-NEXT: bitcast i8* %[[AP_CUR]] to i32* + --count; + } + __builtin_ms_va_end(ap); + return sum; +}