thakis updated this revision to Diff 387381.
thakis added a comment.
- rebase on top of recent (partially still pending) llvm patches
- use `{...|...}` in intrinsic headers
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D113707/new/
https://reviews.llvm.org/D113707
Files:
clang/include/clang/Basic/CodeGenOptions.def
clang/include/clang/Basic/CodeGenOptions.h
clang/include/clang/Driver/Options.td
clang/lib/CodeGen/CGStmt.cpp
clang/lib/Driver/ToolChains/Clang.cpp
clang/lib/Frontend/CompilerInvocation.cpp
clang/lib/Headers/immintrin.h
clang/lib/Headers/intrin.h
clang/lib/Headers/x86gprintrin.h
clang/test/CodeGen/inline-asm-intel.c
clang/test/CodeGen/inline-asm-mixed-style.c
clang/test/Driver/masm.c
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;
}
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 -triple x86_64-unknown-unknown -fasm-blocks -O0 -emit-llvm -S %s -o - | FileCheck %s
// REQUIRES: x86-registered-target
+#include <immintrin.h>
+
void f() {
__asm mov eax, ebx
__asm mov ebx, ecx
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 <intrin.h>
+#else
+#include <x86intrin.h>
+#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/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/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/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/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/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/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<MSAsmStmt>(&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/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<mwatchos_simulator_version_min_EQ>;
def march_EQ : Joined<["-"], "march=">, Group<m_Group>, Flags<[CoreOption]>;
def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Flags<[NoXarchOption]>;
+def inline_asm_EQ : Joined<["-"], "inline-asm=">, Group<m_Group>, Flags<[CC1Option]>;
def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>, Flags<[CC1Option]>,
MarshallingInfoString<TargetOpts<"CodeModel">, [{"default"}]>;
def mtls_size_EQ : Joined<["-"], "mtls-size=">, Group<m_Group>, Flags<[NoXarchOption, CC1Option]>,
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=<file>", "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.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits