-
Notifications
You must be signed in to change notification settings - Fork 14.9k
MC: X86 intel syntax: Support data32 and data16 better #156287
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-backend-x86 Author: Danny Milosavljevic (daym) ChangesSee also #156286 Full diff: https://github.com/llvm/llvm-project/pull/156287.diff 4 Files Affected:
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index d7671ed19589b..211aa47e48fe3 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -3523,8 +3523,26 @@ bool X86AsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
PatchedName = Name;
// Hacks to handle 'data16' and 'data32'
- if (PatchedName == "data16" && is16BitMode()) {
- return Error(NameLoc, "redundant data16 prefix");
+ if (PatchedName == "data16") {
+ if (is16BitMode())
+ return Error(NameLoc, "redundant data16 prefix");
+ if (is64BitMode())
+ return Error(NameLoc, "'data16' is not supported in 64-bit mode");
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ StringRef Next = Parser.getTok().getString();
+ getLexer().Lex();
+ // data16 effectively changes the instruction suffix.
+ // TODO Generalize.
+ if (Next == "call")
+ Next = "callw";
+ if (Next == "ljmp")
+ Next = "ljmpw";
+
+ Name = Next;
+ PatchedName = Name;
+ ForcedDataPrefix = X86::Is16Bit;
+ IsPrefix = false;
+ }
}
if (PatchedName == "data32") {
if (is32BitMode())
@@ -4538,14 +4556,22 @@ bool X86AsmParser::matchAndEmitIntelInstruction(
if (X86Op->isImm()) {
// If it's not a constant fall through and let remainder take care of it.
const auto *CE = dyn_cast<MCConstantExpr>(X86Op->getImm());
- unsigned Size = getPointerWidth();
+ // Determine the size. Prioritize the ForcedDataPrefix flag if it was set
+ // by a 'data32' prefix. Otherwise, fall back to the pointer width of the
+ // current mode.
+ unsigned Size = (ForcedDataPrefix == X86::Is32Bit) ? 32
+ : (ForcedDataPrefix == X86::Is16Bit) ? 16
+ : getPointerWidth();
+ ForcedDataPrefix = 0;
if (CE &&
(isIntN(Size, CE->getValue()) || isUIntN(Size, CE->getValue()))) {
SmallString<16> Tmp;
Tmp += Base;
- Tmp += (is64BitMode())
- ? "q"
- : (is32BitMode()) ? "l" : (is16BitMode()) ? "w" : " ";
+ // Append the suffix corresponding to the determined size.
+ if (Size == 64) Tmp += "q";
+ else if (Size == 32) Tmp += "l";
+ else if (Size == 16) Tmp += "w";
+ else Tmp += " ";
Op.setTokenValue(Tmp);
// Do match in ATT mode to allow explicit suffix usage.
Match.push_back(MatchInstruction(Operands, Inst, ErrorInfo,
diff --git a/llvm/test/MC/X86/x86-16-intel.s b/llvm/test/MC/X86/x86-16-intel.s
new file mode 100644
index 0000000000000..77ae4ae217218
--- /dev/null
+++ b/llvm/test/MC/X86/x86-16-intel.s
@@ -0,0 +1,13 @@
+// RUN: llvm-mc -triple i386-unknown-unknown-code16 --x86-asm-syntax=intel --show-encoding %s | FileCheck %s
+
+// CHECK: pushl $8
+// CHECK: encoding: [0x66,0x6a,0x08]
+ data32 push 8
+
+// CHECK: pushw $8
+// CHECK: encoding: [0x6a,0x08]
+ push 8
+
+// CHECK: lretl
+// CHECK: encoding: [0x66,0xcb]
+ data32 retf
diff --git a/llvm/test/MC/X86/x86-16.s b/llvm/test/MC/X86/x86-16.s
index b0a4bda56fcbf..b4e116ab1a0fb 100644
--- a/llvm/test/MC/X86/x86-16.s
+++ b/llvm/test/MC/X86/x86-16.s
@@ -1060,3 +1060,15 @@ xresldtrk
// CHECK: encoding: [0x66,0x8b,0x1e,A,A]
// CHECK: fixup A - offset: 3, value: nearer, kind: FK_Data_2
movl nearer, %ebx
+
+// CHECK: pushl $8
+// CHECK: encoding: [0x66,0x6a,0x08]
+data32 push $8
+
+// CHECK: pushl $8
+// CHECK: encoding: [0x66,0x6a,0x08]
+pushl $8
+
+// CHECK: pushw $8
+// CHECK: encoding: [0x6a,0x08]
+push $8
diff --git a/llvm/test/MC/X86/x86-32-intel.s b/llvm/test/MC/X86/x86-32-intel.s
new file mode 100644
index 0000000000000..44fc5104653c2
--- /dev/null
+++ b/llvm/test/MC/X86/x86-32-intel.s
@@ -0,0 +1,28 @@
+// RUN: llvm-mc -triple i386-unknown-unknown --x86-asm-syntax=intel --show-encoding %s | FileCheck %s
+
+// CHECK: encoding: [0x66,0x6a,0x08]
+ data16 push 8
+
+// CHECK: encoding: [0x6a,0x08]
+ push 8
+
+// CxHECK: encoding: [0x66,0xcb]
+ // data16 retf
+
+// CHECK: encoding: [0xcb]
+ retf
+
+// CHECK: encoding: [0x66,0x9a,0xcd,0xab,0xce,0x7a]
+ data16 call 0x7ace, 0xabcd
+
+// CHECK: encoding: [0x9a,0xcd,0xab,0x00,0x00,0xce,0x7a]
+ call 0x7ace, 0xabcd
+
+// CHECK: encoding: [0xe8,A,A,A,A]
+ call a
+
+// CxHECK: encoding: [0x66,0xea,0xcd,0xab,0xce,0x7a]
+ // data16 ljmp 0x7ace, 0xabcd
+
+// CHECK: encoding: [0xea,0xcd,0xab,0x00,0x00,0xce,0x7a]
+ ljmp 0x7ace, 0xabcd
|
cc @MaskRay |
✅ With the latest revision this PR passed the C/C++ code formatter. |
Please update the PR title and summary to properly briefly describe your patch |
And format the changed code. |
4aa3936
to
7dcecbf
Compare
// RUN: llvm-mc -triple i386-unknown-unknown --x86-asm-syntax=intel --show-encoding %s | FileCheck %s | ||
|
||
// CHECK: encoding: [0x66,0x6a,0x08] | ||
data16 push 8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this intended?
GNU Assembler rejects data16 push 8
outside of .code16
region.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it?
$ cat boot.asm
.intel_syntax noprefix
test_section:
.code32
data16 push 8
$ as boot.asm
$ objdump -S a.out
a.out: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <test_section>:
0: 66 6a 08 pushw $0x8
$ as --version
GNU assembler (GNU Binutils) 2.44
Copyright (C) 2025 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `x86_64-unknown-linux-gnu'.
@@ -0,0 +1,28 @@ | |||
// RUN: llvm-mc -triple i386-unknown-unknown --x86-asm-syntax=intel --show-encoding %s | FileCheck %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this to intel-syntax-32.s instead. Possibly change the test to use --show-encoding
This PR fixes up
data16
anddata32
so they actually work in intel syntax mode.Previously, this happened:
The first one is obviously incorrect--and the second one is a weird workaround.
Happens only with intel syntax.
See also #156286