llvm-project/clang/test/CodeGen/inline-asm-intel.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

85 lines
3.6 KiB
C
Raw Normal View History

[clang] Make -masm=intel affect inline asm style With this, void f() { __asm__("mov eax, ebx"); } now compiles with clang with -masm=intel. This matches gcc. The flag is not accepted in clang-cl mode. It has no effect on MSVC-style `__asm {}` blocks, which are unconditionally in intel mode both before and after this change. One difference to gcc is that in clang, inline asm strings are "local" while they're "global" in gcc. Building the following with -masm=intel works with clang, but not with gcc where the ".att_syntax" from the 2nd __asm__() is in effect until file end (or until a ".intel_syntax" somewhere later in the file): __asm__("mov eax, ebx"); __asm__(".att_syntax\nmovl %ebx, %eax"); __asm__("mov eax, ebx"); This also updates clang's intrinsic headers to work both in -masm=att (the default) and -masm=intel modes. The official solution for this according to "Multiple assembler dialects in asm templates" in gcc docs->Extensions->Inline Assembly->Extended Asm is to write every inline asm snippet twice: bt{l %[Offset],%[Base] | %[Base],%[Offset]} This works in LLVM after D113932 and D113894, so use that. (Just putting `.att_syntax` at the start of the snippet works in some but not all cases: When LLVM interpolates in parameters like `%0`, it uses at&t or intel syntax according to the inline asm snippet's flavor, so the `.att_syntax` within the snippet happens to late: The interpolated-in parameter is already in intel style, and then won't parse in the switched `.att_syntax`.) It might be nice to invent a `#pragma clang asm_dialect push "att"` / `#pragma clang asm_dialect pop` to be able to force asm style per snippet, so that the inline asm string doesn't contain the same code in two variants, but let's leave that for a follow-up. Fixes PR21401 and PR20241. Differential Revision: https://reviews.llvm.org/D113707
2021-11-12 03:20:02 +08:00
// REQUIRES: x86-registered-target
/// Accept intel inline asm but write it out as att:
// RUN: %clang_cc1 -triple i386-unknown-linux -mllvm -x86-asm-syntax=att -inline-asm=intel -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -O0 -S %s -o - | FileCheck --check-prefix=ATT %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux -mllvm -x86-asm-syntax=att -inline-asm=intel -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -O0 -S %s -o - | FileCheck --check-prefix=ATT %s
[clang] Make -masm=intel affect inline asm style With this, void f() { __asm__("mov eax, ebx"); } now compiles with clang with -masm=intel. This matches gcc. The flag is not accepted in clang-cl mode. It has no effect on MSVC-style `__asm {}` blocks, which are unconditionally in intel mode both before and after this change. One difference to gcc is that in clang, inline asm strings are "local" while they're "global" in gcc. Building the following with -masm=intel works with clang, but not with gcc where the ".att_syntax" from the 2nd __asm__() is in effect until file end (or until a ".intel_syntax" somewhere later in the file): __asm__("mov eax, ebx"); __asm__(".att_syntax\nmovl %ebx, %eax"); __asm__("mov eax, ebx"); This also updates clang's intrinsic headers to work both in -masm=att (the default) and -masm=intel modes. The official solution for this according to "Multiple assembler dialects in asm templates" in gcc docs->Extensions->Inline Assembly->Extended Asm is to write every inline asm snippet twice: bt{l %[Offset],%[Base] | %[Base],%[Offset]} This works in LLVM after D113932 and D113894, so use that. (Just putting `.att_syntax` at the start of the snippet works in some but not all cases: When LLVM interpolates in parameters like `%0`, it uses at&t or intel syntax according to the inline asm snippet's flavor, so the `.att_syntax` within the snippet happens to late: The interpolated-in parameter is already in intel style, and then won't parse in the switched `.att_syntax`.) It might be nice to invent a `#pragma clang asm_dialect push "att"` / `#pragma clang asm_dialect pop` to be able to force asm style per snippet, so that the inline asm string doesn't contain the same code in two variants, but let's leave that for a follow-up. Fixes PR21401 and PR20241. Differential Revision: https://reviews.llvm.org/D113707
2021-11-12 03:20:02 +08:00
/// Accept intel inline asm and write it out as intel:
// RUN: %clang_cc1 -triple i386-unknown-linux -mllvm -x86-asm-syntax=intel -inline-asm=intel -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -O0 -S %s -o - | FileCheck --check-prefix=INTEL %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux -mllvm -x86-asm-syntax=intel -inline-asm=intel -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -O0 -S %s -o - | FileCheck --check-prefix=INTEL %s
[clang] Make -masm=intel affect inline asm style With this, void f() { __asm__("mov eax, ebx"); } now compiles with clang with -masm=intel. This matches gcc. The flag is not accepted in clang-cl mode. It has no effect on MSVC-style `__asm {}` blocks, which are unconditionally in intel mode both before and after this change. One difference to gcc is that in clang, inline asm strings are "local" while they're "global" in gcc. Building the following with -masm=intel works with clang, but not with gcc where the ".att_syntax" from the 2nd __asm__() is in effect until file end (or until a ".intel_syntax" somewhere later in the file): __asm__("mov eax, ebx"); __asm__(".att_syntax\nmovl %ebx, %eax"); __asm__("mov eax, ebx"); This also updates clang's intrinsic headers to work both in -masm=att (the default) and -masm=intel modes. The official solution for this according to "Multiple assembler dialects in asm templates" in gcc docs->Extensions->Inline Assembly->Extended Asm is to write every inline asm snippet twice: bt{l %[Offset],%[Base] | %[Base],%[Offset]} This works in LLVM after D113932 and D113894, so use that. (Just putting `.att_syntax` at the start of the snippet works in some but not all cases: When LLVM interpolates in parameters like `%0`, it uses at&t or intel syntax according to the inline asm snippet's flavor, so the `.att_syntax` within the snippet happens to late: The interpolated-in parameter is already in intel style, and then won't parse in the switched `.att_syntax`.) It might be nice to invent a `#pragma clang asm_dialect push "att"` / `#pragma clang asm_dialect pop` to be able to force asm style per snippet, so that the inline asm string doesn't contain the same code in two variants, but let's leave that for a follow-up. Fixes PR21401 and PR20241. Differential Revision: https://reviews.llvm.org/D113707
2021-11-12 03:20:02 +08:00
/// Check MS compat mode (_MSC_VER defined). The driver always picks intel
/// output in that mode, so test only that.
// RUN: %clang_cc1 -triple i386-pc-win32 -mllvm -x86-asm-syntax=intel -inline-asm=intel -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -O0 -S %s -o - -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 | FileCheck --check-prefix=INTEL %s
// RUN: %clang_cc1 -triple x86_64-pc-win32 -mllvm -x86-asm-syntax=intel -inline-asm=intel -Werror -target-feature +hreset -target-feature +pconfig -target-feature +sgx -ffreestanding -O0 -S %s -o - -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 | FileCheck --check-prefix=INTEL %s
[clang] Make -masm=intel affect inline asm style With this, void f() { __asm__("mov eax, ebx"); } now compiles with clang with -masm=intel. This matches gcc. The flag is not accepted in clang-cl mode. It has no effect on MSVC-style `__asm {}` blocks, which are unconditionally in intel mode both before and after this change. One difference to gcc is that in clang, inline asm strings are "local" while they're "global" in gcc. Building the following with -masm=intel works with clang, but not with gcc where the ".att_syntax" from the 2nd __asm__() is in effect until file end (or until a ".intel_syntax" somewhere later in the file): __asm__("mov eax, ebx"); __asm__(".att_syntax\nmovl %ebx, %eax"); __asm__("mov eax, ebx"); This also updates clang's intrinsic headers to work both in -masm=att (the default) and -masm=intel modes. The official solution for this according to "Multiple assembler dialects in asm templates" in gcc docs->Extensions->Inline Assembly->Extended Asm is to write every inline asm snippet twice: bt{l %[Offset],%[Base] | %[Base],%[Offset]} This works in LLVM after D113932 and D113894, so use that. (Just putting `.att_syntax` at the start of the snippet works in some but not all cases: When LLVM interpolates in parameters like `%0`, it uses at&t or intel syntax according to the inline asm snippet's flavor, so the `.att_syntax` within the snippet happens to late: The interpolated-in parameter is already in intel style, and then won't parse in the switched `.att_syntax`.) It might be nice to invent a `#pragma clang asm_dialect push "att"` / `#pragma clang asm_dialect pop` to be able to force asm style per snippet, so that the inline asm string doesn't contain the same code in two variants, but let's leave that for a follow-up. Fixes PR21401 and PR20241. Differential Revision: https://reviews.llvm.org/D113707
2021-11-12 03:20:02 +08:00
// Test that intrinsics headers still work with -masm=intel.
#ifdef _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
void f(void) {
[clang] Make -masm=intel affect inline asm style With this, void f() { __asm__("mov eax, ebx"); } now compiles with clang with -masm=intel. This matches gcc. The flag is not accepted in clang-cl mode. It has no effect on MSVC-style `__asm {}` blocks, which are unconditionally in intel mode both before and after this change. One difference to gcc is that in clang, inline asm strings are "local" while they're "global" in gcc. Building the following with -masm=intel works with clang, but not with gcc where the ".att_syntax" from the 2nd __asm__() is in effect until file end (or until a ".intel_syntax" somewhere later in the file): __asm__("mov eax, ebx"); __asm__(".att_syntax\nmovl %ebx, %eax"); __asm__("mov eax, ebx"); This also updates clang's intrinsic headers to work both in -masm=att (the default) and -masm=intel modes. The official solution for this according to "Multiple assembler dialects in asm templates" in gcc docs->Extensions->Inline Assembly->Extended Asm is to write every inline asm snippet twice: bt{l %[Offset],%[Base] | %[Base],%[Offset]} This works in LLVM after D113932 and D113894, so use that. (Just putting `.att_syntax` at the start of the snippet works in some but not all cases: When LLVM interpolates in parameters like `%0`, it uses at&t or intel syntax according to the inline asm snippet's flavor, so the `.att_syntax` within the snippet happens to late: The interpolated-in parameter is already in intel style, and then won't parse in the switched `.att_syntax`.) It might be nice to invent a `#pragma clang asm_dialect push "att"` / `#pragma clang asm_dialect pop` to be able to force asm style per snippet, so that the inline asm string doesn't contain the same code in two variants, but let's leave that for a follow-up. Fixes PR21401 and PR20241. Differential Revision: https://reviews.llvm.org/D113707
2021-11-12 03:20:02 +08:00
// 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
}