Index: clang/include/clang/Basic/CodeGenOptions.h =================================================================== --- clang/include/clang/Basic/CodeGenOptions.h +++ clang/include/clang/Basic/CodeGenOptions.h @@ -97,6 +97,11 @@ Embed_Marker // Embed a marker as a placeholder for bitcode. }; + enum InlineAsmDialectKind { + IAD_ATT, + IAD_Intel, + }; + // This field stores one of the allowed values for the option // -fbasic-block-sections=. The allowed values with this option are: // {"labels", "all", "list=", "none"}. Index: clang/include/clang/Basic/CodeGenOptions.def =================================================================== --- clang/include/clang/Basic/CodeGenOptions.def +++ clang/include/clang/Basic/CodeGenOptions.def @@ -92,6 +92,8 @@ CODEGENOPT(ExplicitEmulatedTLS , 1, 0) ///< Set if -f[no-]emulated-tls is used. /// Embed Bitcode mode (off/all/bitcode/marker). ENUM_CODEGENOPT(EmbedBitcode, EmbedBitcodeKind, 2, Embed_Off) +/// Inline asm dialect, -masm=(att|intel) +ENUM_CODEGENOPT(InlineAsmDialect, InlineAsmDialectKind, 1, IAD_ATT) CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables ///< are required. CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled. Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -3131,6 +3131,7 @@ def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min=">, Alias; def march_EQ : Joined<["-"], "march=">, Group, Flags<[CoreOption]>; def masm_EQ : Joined<["-"], "masm=">, Group, Flags<[NoXarchOption]>; +def inline_asm_EQ : Joined<["-"], "inline-asm=">, Group, Flags<[CC1Option]>; def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group, Flags<[CC1Option]>, MarshallingInfoString, [{"default"}]>; def mtls_size_EQ : Joined<["-"], "mtls-size=">, Group, Flags<[NoXarchOption, CC1Option]>, Index: clang/lib/CodeGen/CGStmt.cpp =================================================================== --- clang/lib/CodeGen/CGStmt.cpp +++ clang/lib/CodeGen/CGStmt.cpp @@ -2629,8 +2629,14 @@ llvm::FunctionType::get(ResultType, ArgTypes, false); bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0; + + llvm::InlineAsm::AsmDialect GnuAsmDialect = + CGM.getCodeGenOpts().getInlineAsmDialect() == CodeGenOptions::IAD_ATT + ? llvm::InlineAsm::AD_ATT + : llvm::InlineAsm::AD_Intel; llvm::InlineAsm::AsmDialect AsmDialect = isa(&S) ? - llvm::InlineAsm::AD_Intel : llvm::InlineAsm::AD_ATT; + llvm::InlineAsm::AD_Intel : GnuAsmDialect; + llvm::InlineAsm *IA = llvm::InlineAsm::get( FTy, AsmString, Constraints, HasSideEffect, /* IsAlignStack */ false, AsmDialect, HasUnwindClobber); Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -2200,6 +2200,7 @@ if (Value == "intel" || Value == "att") { CmdArgs.push_back("-mllvm"); CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value)); + CmdArgs.push_back(Args.MakeArgString("-inline-asm=" + Value)); } else { D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -1614,6 +1614,18 @@ } } + if (Arg *A = Args.getLastArg(options::OPT_inline_asm_EQ)) { + StringRef Value = A->getValue(); + if (Value == "att") { + Opts.InlineAsmDialect = CodeGenOptions::IAD_ATT; + } else if (Value == "intel") { + Opts.InlineAsmDialect = CodeGenOptions::IAD_Intel; + } else { + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) + << A->getValue(); + } + } + // PIC defaults to -fno-direct-access-external-data while non-PIC defaults to // -fdirect-access-external-data. Opts.DirectAccessExternalData = Index: clang/lib/Headers/immintrin.h =================================================================== --- clang/lib/Headers/immintrin.h +++ clang/lib/Headers/immintrin.h @@ -543,13 +543,13 @@ #if defined(__i386__) || defined(__x86_64__) static __inline__ long __DEFAULT_FN_ATTRS _InterlockedExchange_HLEAcquire(long volatile *_Target, long _Value) { - __asm__ __volatile__(".byte 0xf2 ; lock ; xchg %0, %1" + __asm__ __volatile__(".byte 0xf2 ; lock ; xchg {%0, %1|%1, %0}" : "+r" (_Value), "+m" (*_Target) :: "memory"); return _Value; } static __inline__ long __DEFAULT_FN_ATTRS _InterlockedExchange_HLERelease(long volatile *_Target, long _Value) { - __asm__ __volatile__(".byte 0xf3 ; lock ; xchg %0, %1" + __asm__ __volatile__(".byte 0xf3 ; lock ; xchg {%0, %1|%1, %0}" : "+r" (_Value), "+m" (*_Target) :: "memory"); return _Value; } @@ -557,13 +557,13 @@ #if defined(__x86_64__) static __inline__ __int64 __DEFAULT_FN_ATTRS _InterlockedExchange64_HLEAcquire(__int64 volatile *_Target, __int64 _Value) { - __asm__ __volatile__(".byte 0xf2 ; lock ; xchg %0, %1" + __asm__ __volatile__(".byte 0xf2 ; lock ; xchg {%0, %1|%1, %0}" : "+r" (_Value), "+m" (*_Target) :: "memory"); return _Value; } static __inline__ __int64 __DEFAULT_FN_ATTRS _InterlockedExchange64_HLERelease(__int64 volatile *_Target, __int64 _Value) { - __asm__ __volatile__(".byte 0xf3 ; lock ; xchg %0, %1" + __asm__ __volatile__(".byte 0xf3 ; lock ; xchg {%0, %1|%1, %0}" : "+r" (_Value), "+m" (*_Target) :: "memory"); return _Value; } @@ -575,7 +575,7 @@ static __inline__ long __DEFAULT_FN_ATTRS _InterlockedCompareExchange_HLEAcquire(long volatile *_Destination, long _Exchange, long _Comparand) { - __asm__ __volatile__(".byte 0xf2 ; lock ; cmpxchg %2, %1" + __asm__ __volatile__(".byte 0xf2 ; lock ; cmpxchg {%2, %1|%1, %2}" : "+a" (_Comparand), "+m" (*_Destination) : "r" (_Exchange) : "memory"); return _Comparand; @@ -583,7 +583,7 @@ static __inline__ long __DEFAULT_FN_ATTRS _InterlockedCompareExchange_HLERelease(long volatile *_Destination, long _Exchange, long _Comparand) { - __asm__ __volatile__(".byte 0xf3 ; lock ; cmpxchg %2, %1" + __asm__ __volatile__(".byte 0xf3 ; lock ; cmpxchg {%2, %1|%1, %2}" : "+a" (_Comparand), "+m" (*_Destination) : "r" (_Exchange) : "memory"); return _Comparand; @@ -593,7 +593,7 @@ static __inline__ __int64 __DEFAULT_FN_ATTRS _InterlockedCompareExchange64_HLEAcquire(__int64 volatile *_Destination, __int64 _Exchange, __int64 _Comparand) { - __asm__ __volatile__(".byte 0xf2 ; lock ; cmpxchg %2, %1" + __asm__ __volatile__(".byte 0xf2 ; lock ; cmpxchg {%2, %1|%1, %2}" : "+a" (_Comparand), "+m" (*_Destination) : "r" (_Exchange) : "memory"); return _Comparand; @@ -601,7 +601,7 @@ static __inline__ __int64 __DEFAULT_FN_ATTRS _InterlockedCompareExchange64_HLERelease(__int64 volatile *_Destination, __int64 _Exchange, __int64 _Comparand) { - __asm__ __volatile__(".byte 0xf3 ; lock ; cmpxchg %2, %1" + __asm__ __volatile__(".byte 0xf3 ; lock ; cmpxchg {%2, %1|%1, %2}" : "+a" (_Comparand), "+m" (*_Destination) : "r" (_Exchange) : "memory"); return _Comparand; Index: clang/lib/Headers/intrin.h =================================================================== --- clang/lib/Headers/intrin.h +++ clang/lib/Headers/intrin.h @@ -455,7 +455,9 @@ : : "memory"); #else - __asm__ __volatile__("xchg %%esi, %1\nrep movsb\nxchg %%esi, %1" + __asm__ __volatile__("xchg {%%esi, %1|%1, esi}\n" + "rep movsb\n" + "xchg {%%esi, %1|%1, esi}" : "+D"(__dst), "+r"(__src), "+c"(__n) : : "memory"); @@ -465,12 +467,14 @@ unsigned long const *__src, size_t __n) { #if defined(__x86_64__) - __asm__ __volatile__("rep movsl" + __asm__ __volatile__("rep movs{l|d}" : "+D"(__dst), "+S"(__src), "+c"(__n) : : "memory"); #else - __asm__ __volatile__("xchg %%esi, %1\nrep movsl\nxchg %%esi, %1" + __asm__ __volatile__("xchg {%%esi, %1|%1, esi}\n" + "rep movs{l|d}\n" + "xchg {%%esi, %1|%1, esi}" : "+D"(__dst), "+r"(__src), "+c"(__n) : : "memory"); @@ -485,7 +489,9 @@ : : "memory"); #else - __asm__ __volatile__("xchg %%esi, %1\nrep movsw\nxchg %%esi, %1" + __asm__ __volatile__("xchg {%%esi, %1|%1, esi}\n" + "rep movsw\n" + "xchg {%%esi, %1|%1, esi}" : "+D"(__dst), "+r"(__src), "+c"(__n) : : "memory"); @@ -494,7 +500,7 @@ static __inline__ void __DEFAULT_FN_ATTRS __stosd(unsigned long *__dst, unsigned long __x, size_t __n) { - __asm__ __volatile__("rep stosl" + __asm__ __volatile__("rep stos{l|d}" : "+D"(__dst), "+c"(__n) : "a"(__x) : "memory"); @@ -536,9 +542,9 @@ #else /* x86-64 uses %rbx as the base register, so preserve it. */ #define __cpuid_count(__leaf, __count, __eax, __ebx, __ecx, __edx) \ - __asm("xchgq %%rbx,%q1\n" \ + __asm("xchg{q} {%%rbx, %q1|%q1, rbx}\n" \ "cpuid\n" \ - "xchgq %%rbx,%q1" \ + "xchg{q} {%%rbx, %q1|%q1, rbx}" \ : "=a"(__eax), "=r"(__ebx), "=c"(__ecx), "=d"(__edx) \ : "0"(__leaf), "2"(__count)) #endif @@ -598,13 +604,17 @@ static __inline__ unsigned __LPTRINT_TYPE__ __DEFAULT_FN_ATTRS __readcr3(void) { unsigned __LPTRINT_TYPE__ __cr3_val; - __asm__ __volatile__ ("mov %%cr3, %0" : "=r"(__cr3_val) : : "memory"); + __asm__ __volatile__( + "mov {%%cr3, %0|%0, cr3}" + : "=r"(__cr3_val) + : + : "memory"); return __cr3_val; } static __inline__ void __DEFAULT_FN_ATTRS __writecr3(unsigned __INTPTR_TYPE__ __cr3_val) { - __asm__ ("mov %0, %%cr3" : : "r"(__cr3_val) : "memory"); + __asm__ ("mov {%0, %%cr3|cr3, %0}" : : "r"(__cr3_val) : "memory"); } #ifdef __cplusplus Index: clang/lib/Headers/x86gprintrin.h =================================================================== --- clang/lib/Headers/x86gprintrin.h +++ clang/lib/Headers/x86gprintrin.h @@ -26,8 +26,10 @@ #endif #define __SSC_MARK(Tag) \ - __asm__ __volatile__("movl %%ebx, %%eax; movl %0, %%ebx; .byte 0x64, 0x67, " \ - "0x90; movl %%eax, %%ebx;" ::"i"(Tag) \ + __asm__ __volatile__("mov{l} {%%ebx, %%eax|eax, ebx}; " \ + "mov{l} {%0, %%ebx|ebx, %0}; " \ + ".byte 0x64, 0x67, 0x90; " \ + "mov{l} {%%eax, %%ebx|ebx, eax};" ::"i"(Tag) \ : "%eax"); #endif /* __X86GPRINTRIN_H */ Index: clang/test/CodeGen/inline-asm-intel.c =================================================================== --- /dev/null +++ clang/test/CodeGen/inline-asm-intel.c @@ -0,0 +1,82 @@ +// REQUIRES: x86-registered-target + +/// Accept intel inline asm but write it out as att: +// RUN: %clang_cc1 -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -triple i386-unknown-unknown -mllvm -x86-asm-syntax=att -inline-asm=intel -O0 -S %s -o - | FileCheck --check-prefix=ATT %s +// RUN: %clang_cc1 -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -triple x86_64-unknown-unknown -mllvm -x86-asm-syntax=att -inline-asm=intel -O0 -S %s -o - | FileCheck --check-prefix=ATT %s + +/// Accept intel inline asm and write it out as intel: +// RUN: %clang_cc1 -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -triple i386-unknown-unknown -mllvm -x86-asm-syntax=intel -inline-asm=intel -O0 -S %s -o - | FileCheck --check-prefix=INTEL %s +// RUN: %clang_cc1 -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -triple x86_64-unknown-unknown -mllvm -x86-asm-syntax=intel -inline-asm=intel -O0 -S %s -o - | FileCheck --check-prefix=INTEL %s + +// RUN: %clang_cc1 -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -triple i386-pc-win32 -mllvm -x86-asm-syntax=intel -inline-asm=intel -O0 -S %s -o - -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 | FileCheck --check-prefix=INTEL %s +// RUN: %clang_cc1 -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -triple x86_64-pc-win32 -mllvm -x86-asm-syntax=intel -inline-asm=intel -O0 -S %s -o - -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 | FileCheck --check-prefix=INTEL %s + +// Test that intrinsics headers still work with -masm=intel. +#ifdef _MSC_VER +#include +#else +#include +#endif + +void f() { + // Intrinsic headers contain macros and inline functions. + // Inline assembly in both are checked only when they are + // referenced, so reference a few intrinsics here. + __SSC_MARK(4); + int a; + _hreset(a); + _pconfig_u32(0, (void*)0); + + _encls_u32(0, (void*)0); + _enclu_u32(0, (void*)0); + _enclv_u32(0, (void*)0); +#ifdef _MSC_VER + __movsb((void*)0, (void*)0, 0); + __movsd((void*)0, (void*)0, 0); + __movsw((void*)0, (void*)0, 0); + __stosb((void*)0, 0, 0); + __stosd((void*)0, 0, 0); + __stosw((void*)0, 0, 0); +#ifdef __x86_64__ + __movsq((void*)0, (void*)0, 0); + __stosq((void*)0, 0, 0); +#endif + __cpuid((void*)0, 0); + __cpuidex((void*)0, 0, 0); + __halt(); + __nop(); + __readmsr(0); + __readcr3(); + __writecr3(0); + + _InterlockedExchange_HLEAcquire((void*)0, 0); + _InterlockedExchange_HLERelease((void*)0, 0); + _InterlockedCompareExchange_HLEAcquire((void*)0, 0, 0); + _InterlockedCompareExchange_HLERelease((void*)0, 0, 0); +#ifdef __x86_64__ + _InterlockedExchange64_HLEAcquire((void*)0, 0); + _InterlockedExchange64_HLERelease((void*)0, 0); + _InterlockedCompareExchange64_HLEAcquire((void*)0, 0, 0); + _InterlockedCompareExchange64_HLERelease((void*)0, 0, 0); +#endif +#endif + + + __asm__("mov eax, ebx"); + // ATT: movl %ebx, %eax + // INTEL: mov eax, ebx + + // Explicitly overriding asm style per block works: + __asm__(".att_syntax\nmovl %ebx, %eax"); + // ATT: movl %ebx, %eax + // INTEL: mov eax, ebx + + // The .att_syntax was only scoped to the previous statement. + // (This is different from gcc, where `.att_syntax` is in + // effect from that point on, so portable code would want an + // explicit `.intel_syntax noprefix\n` at the start of this string). + __asm__("mov eax, ebx"); + // ATT: movl %ebx, %eax + // INTEL: mov eax, ebx +} + Index: clang/test/CodeGen/inline-asm-mixed-style.c =================================================================== --- clang/test/CodeGen/inline-asm-mixed-style.c +++ clang/test/CodeGen/inline-asm-mixed-style.c @@ -1,6 +1,9 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -O0 -emit-llvm -S %s -o - | FileCheck %s +// RUN: %clang_cc1 -ffreestanding -triple i386-unknown-unknown -fasm-blocks -O0 -emit-llvm -S %s -o - | FileCheck %s +// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -fasm-blocks -O0 -emit-llvm -S %s -o - | FileCheck %s // REQUIRES: x86-registered-target +#include + void f() { __asm mov eax, ebx __asm mov ebx, ecx Index: clang/test/CodeGen/ms-intrinsics-cpuid.c =================================================================== --- clang/test/CodeGen/ms-intrinsics-cpuid.c +++ clang/test/CodeGen/ms-intrinsics-cpuid.c @@ -18,6 +18,6 @@ // X86-SAME: (i32 %{{.*}}, i32 0) // X64-LABEL: define {{.*}} @test__cpuid(i32* %{{.*}}, i32 %{{.*}}) -// X64: call { i32, i32, i32, i32 } asm "xchgq %rbx{{.*}}cpuid{{.*}}xchgq %rbx{{.*}}", +// X64: call { i32, i32, i32, i32 } asm "xchg$(q$) $(%rbx{{.*}}$){{.*}}cpuid{{.*}}xchg$(q$) $(%rbx{{.*}}$)", // X64-SAME: "={ax},=r,={cx},={dx},0,2,~{dirflag},~{fpsr},~{flags}" // X64-SAME: (i32 %{{.*}}, i32 0) Index: clang/test/CodeGen/ms-intrinsics.c =================================================================== --- clang/test/CodeGen/ms-intrinsics.c +++ clang/test/CodeGen/ms-intrinsics.c @@ -36,7 +36,7 @@ return __movsb(Dest, Src, Count); } // CHECK-I386-LABEL: define{{.*}} void @test__movsb -// CHECK-I386: tail call { i8*, i8*, i32 } asm sideeffect "xchg %esi, $1\0Arep movsb\0Axchg %esi, $1", "={di},=r,={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i8* %Dest, i8* %Src, i32 %Count) +// CHECK-I386: tail call { i8*, i8*, i32 } asm sideeffect "xchg $(%esi, $1$|$1, esi$)\0Arep movsb\0Axchg $(%esi, $1$|$1, esi$)", "={di},=r,={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i8* %Dest, i8* %Src, i32 %Count) // CHECK-I386: ret void // CHECK-I386: } @@ -62,7 +62,7 @@ return __movsw(Dest, Src, Count); } // CHECK-I386-LABEL: define{{.*}} void @test__movsw -// CHECK-I386: tail call { i16*, i16*, i32 } asm sideeffect "xchg %esi, $1\0Arep movsw\0Axchg %esi, $1", "={di},=r,={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i16* %Dest, i16* %Src, i32 %Count) +// CHECK-I386: tail call { i16*, i16*, i32 } asm sideeffect "xchg $(%esi, $1$|$1, esi$)\0Arep movsw\0Axchg $(%esi, $1$|$1, esi$)", "={di},=r,={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i16* %Dest, i16* %Src, i32 %Count) // CHECK-I386: ret void // CHECK-I386: } @@ -75,12 +75,12 @@ return __stosd(Dest, Data, Count); } // CHECK-I386-LABEL: define{{.*}} void @test__stosd -// CHECK-I386: call { i32*, i32 } asm sideeffect "rep stosl", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 %Data, i32* %Dest, i32 %Count) +// CHECK-I386: call { i32*, i32 } asm sideeffect "rep stos$(l$|d$)", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 %Data, i32* %Dest, i32 %Count) // CHECK-I386: ret void // CHECK-I386: } // CHECK-X64-LABEL: define{{.*}} void @test__stosd -// CHECK-X64: call { i32*, i64 } asm sideeffect "rep stosl", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 %Data, i32* %Dest, i64 %Count) +// CHECK-X64: call { i32*, i64 } asm sideeffect "rep stos$(l$|d$)", "={di},={cx},{ax},0,1,~{memory},~{dirflag},~{fpsr},~{flags}"(i32 %Data, i32* %Dest, i64 %Count) // CHECK-X64: ret void // CHECK-X64: } @@ -88,12 +88,12 @@ return __movsd(Dest, Src, Count); } // CHECK-I386-LABEL: define{{.*}} void @test__movsd -// CHECK-I386: tail call { i32*, i32*, i32 } asm sideeffect "xchg %esi, $1\0Arep movsl\0Axchg %esi, $1", "={di},=r,={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Dest, i32* %Src, i32 %Count) +// CHECK-I386: tail call { i32*, i32*, i32 } asm sideeffect "xchg $(%esi, $1$|$1, esi$)\0Arep movs$(l$|d$)\0Axchg $(%esi, $1$|$1, esi$)", "={di},=r,={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Dest, i32* %Src, i32 %Count) // CHECK-I386: ret void // CHECK-I386: } // CHECK-X64-LABEL: define{{.*}} void @test__movsd -// CHECK-X64: call { i32*, i32*, i64 } asm sideeffect "rep movsl", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Dest, i32* %Src, i64 %Count) +// CHECK-X64: call { i32*, i32*, i64 } asm sideeffect "rep movs$(l$|d$)", "={di},={si},={cx},0,1,2,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Dest, i32* %Src, i64 %Count) // CHECK-X64: ret void // CHECK-X64: } @@ -626,48 +626,48 @@ #if defined(__i386__) || defined(__x86_64__) long test_InterlockedExchange_HLEAcquire(long volatile *Target, long Value) { // CHECK-INTEL: define{{.*}} i32 @test_InterlockedExchange_HLEAcquire(i32*{{[a-z_ ]*}}%Target, i32{{[a-z_ ]*}}%Value) -// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf2 ; lock ; xchg $0, $1", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Target, i32 %Value, i32* %Target) +// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf2 ; lock ; xchg $($0, $1$|$1, $0$)", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Target, i32 %Value, i32* %Target) return _InterlockedExchange_HLEAcquire(Target, Value); } long test_InterlockedExchange_HLERelease(long volatile *Target, long Value) { // CHECK-INTEL: define{{.*}} i32 @test_InterlockedExchange_HLERelease(i32*{{[a-z_ ]*}}%Target, i32{{[a-z_ ]*}}%Value) -// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf3 ; lock ; xchg $0, $1", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Target, i32 %Value, i32* %Target) +// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf3 ; lock ; xchg $($0, $1$|$1, $0$)", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Target, i32 %Value, i32* %Target) return _InterlockedExchange_HLERelease(Target, Value); } long test_InterlockedCompareExchange_HLEAcquire(long volatile *Destination, long Exchange, long Comparand) { // CHECK-INTEL: define{{.*}} i32 @test_InterlockedCompareExchange_HLEAcquire(i32*{{[a-z_ ]*}}%Destination, i32{{[a-z_ ]*}}%Exchange, i32{{[a-z_ ]*}}%Comparand) -// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf2 ; lock ; cmpxchg $2, $1", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Destination, i32 %Exchange, i32 %Comparand, i32* %Destination) +// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf2 ; lock ; cmpxchg $($2, $1$|$1, $2$)", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Destination, i32 %Exchange, i32 %Comparand, i32* %Destination) return _InterlockedCompareExchange_HLEAcquire(Destination, Exchange, Comparand); } long test_InterlockedCompareExchange_HLERelease(long volatile *Destination, long Exchange, long Comparand) { // CHECK-INTEL: define{{.*}} i32 @test_InterlockedCompareExchange_HLERelease(i32*{{[a-z_ ]*}}%Destination, i32{{[a-z_ ]*}}%Exchange, i32{{[a-z_ ]*}}%Comparand) -// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf3 ; lock ; cmpxchg $2, $1", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Destination, i32 %Exchange, i32 %Comparand, i32* %Destination) +// CHECK-INTEL: call i32 asm sideeffect ".byte 0xf3 ; lock ; cmpxchg $($2, $1$|$1, $2$)", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* %Destination, i32 %Exchange, i32 %Comparand, i32* %Destination) return _InterlockedCompareExchange_HLERelease(Destination, Exchange, Comparand); } #endif #if defined(__x86_64__) __int64 test_InterlockedExchange64_HLEAcquire(__int64 volatile *Target, __int64 Value) { // CHECK-X64: define{{.*}} i64 @test_InterlockedExchange64_HLEAcquire(i64*{{[a-z_ ]*}}%Target, i64{{[a-z_ ]*}}%Value) -// CHECK-X64: call i64 asm sideeffect ".byte 0xf2 ; lock ; xchg $0, $1", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Target, i64 %Value, i64* %Target) +// CHECK-X64: call i64 asm sideeffect ".byte 0xf2 ; lock ; xchg $($0, $1$|$1, $0$)", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Target, i64 %Value, i64* %Target) return _InterlockedExchange64_HLEAcquire(Target, Value); } __int64 test_InterlockedExchange64_HLERelease(__int64 volatile *Target, __int64 Value) { // CHECK-X64: define{{.*}} i64 @test_InterlockedExchange64_HLERelease(i64*{{[a-z_ ]*}}%Target, i64{{[a-z_ ]*}}%Value) -// CHECK-X64: call i64 asm sideeffect ".byte 0xf3 ; lock ; xchg $0, $1", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Target, i64 %Value, i64* %Target) +// CHECK-X64: call i64 asm sideeffect ".byte 0xf3 ; lock ; xchg $($0, $1$|$1, $0$)", "=r,=*m,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Target, i64 %Value, i64* %Target) return _InterlockedExchange64_HLERelease(Target, Value); } __int64 test_InterlockedCompareExchange64_HLEAcquire(__int64 volatile *Destination, __int64 Exchange, __int64 Comparand) { // CHECK-X64: define{{.*}} i64 @test_InterlockedCompareExchange64_HLEAcquire(i64*{{[a-z_ ]*}}%Destination, i64{{[a-z_ ]*}}%Exchange, i64{{[a-z_ ]*}}%Comparand) -// CHECK-X64: call i64 asm sideeffect ".byte 0xf2 ; lock ; cmpxchg $2, $1", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Destination, i64 %Exchange, i64 %Comparand, i64* %Destination) +// CHECK-X64: call i64 asm sideeffect ".byte 0xf2 ; lock ; cmpxchg $($2, $1$|$1, $2$)", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Destination, i64 %Exchange, i64 %Comparand, i64* %Destination) return _InterlockedCompareExchange64_HLEAcquire(Destination, Exchange, Comparand); } __int64 test_InterlockedCompareExchange64_HLERelease(__int64 volatile *Destination, __int64 Exchange, __int64 Comparand) { // CHECK-X64: define{{.*}} i64 @test_InterlockedCompareExchange64_HLERelease(i64*{{[a-z_ ]*}}%Destination, i64{{[a-z_ ]*}}%Exchange, i64{{[a-z_ ]*}}%Comparand) -// CHECK-X64: call i64 asm sideeffect ".byte 0xf3 ; lock ; cmpxchg $2, $1", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Destination, i64 %Exchange, i64 %Comparand, i64* %Destination) +// CHECK-X64: call i64 asm sideeffect ".byte 0xf3 ; lock ; cmpxchg $($2, $1$|$1, $2$)", "={ax},=*m,r,0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %Destination, i64 %Exchange, i64 %Comparand, i64* %Destination) return _InterlockedCompareExchange64_HLERelease(Destination, Exchange, Comparand); } #endif Index: clang/test/Driver/masm.c =================================================================== --- clang/test/Driver/masm.c +++ clang/test/Driver/masm.c @@ -6,9 +6,12 @@ int f() { // CHECK-INTEL: -x86-asm-syntax=intel +// CHECK-INTEL: -inline-asm=intel // CHECK-ATT: -x86-asm-syntax=att +// CHECK-ATT: -inline-asm=att // CHECK-SOMEREQUIRED: error: unsupported argument 'somerequired' to option 'masm=' // CHECK-ARM: warning: argument unused during compilation: '-masm=intel' // CHECK-CL: -x86-asm-syntax=intel +// CHECK-CL-NOT: -inline-asm=intel return 0; }