Skip to content

Commit 1d57587

Browse files
authored
X86: Support dollar symbol for AT&T syntax and add output-asm-variant to llc
'$' indicates immediate values in AT&T syntax, so symbol names starting with '$' need to be quoted or wrapped in parentheses. Parentheses are preferred to support expressions with relocation specifiers without modifying MCExpr internals, aligning with GCC (https://gcc.gnu.org/PR91298). Add `-output-asm-variant` to llc for testing Intel syntax, avoiding `-x86-asm-syntax` which affects MCAsmInfo used by input assembly (-x86-asm-syntax=intel doesn't work with AT&T module asm) Note: In these positions the symbol name cannot be quoted: `$var:` `.globl $var` `.type $var, @object` Close #147587 Pull Request: #147876
1 parent af6500d commit 1d57587

File tree

7 files changed

+106
-15
lines changed

7 files changed

+106
-15
lines changed

llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "X86ATTInstPrinter.h"
1515
#include "X86BaseInfo.h"
1616
#include "X86InstComments.h"
17+
#include "llvm/ADT/SmallString.h"
1718
#include "llvm/MC/MCAsmInfo.h"
1819
#include "llvm/MC/MCExpr.h"
1920
#include "llvm/MC/MCInst.h"
@@ -35,6 +36,21 @@ using namespace llvm;
3536
#define PRINT_ALIAS_INSTR
3637
#include "X86GenAsmWriter.inc"
3738

39+
// Print an MCExpr as an operand. Similar to GCC, wrap the output in parentheses
40+
// if it begins with '$', as '$' in an operand position indicates an immediate
41+
// value in the AT&T syntax.
42+
void X86ATTInstPrinter::printExprOperand(raw_ostream &OS, const MCExpr &E) {
43+
SmallString<128> S;
44+
{
45+
raw_svector_ostream SOS(S);
46+
MAI.printExpr(SOS, E);
47+
}
48+
if (S.starts_with("$"))
49+
OS << '(' << S << ')';
50+
else
51+
OS << S;
52+
}
53+
3854
void X86ATTInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
3955
markup(OS, Markup::Register) << '%' << getRegisterName(Reg);
4056
}
@@ -446,7 +462,7 @@ void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op,
446462
O << formatImm(DispVal);
447463
} else {
448464
assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
449-
MAI.printExpr(O, *DispSpec.getExpr());
465+
printExprOperand(O, *DispSpec.getExpr());
450466
}
451467

452468
if (IndexReg.getReg() || BaseReg.getReg()) {
@@ -501,7 +517,7 @@ void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
501517
O << formatImm(DispSpec.getImm());
502518
} else {
503519
assert(DispSpec.isExpr() && "non-immediate displacement?");
504-
MAI.printExpr(O, *DispSpec.getExpr());
520+
printExprOperand(O, *DispSpec.getExpr());
505521
}
506522
}
507523

llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class X86ATTInstPrinter final : public X86InstPrinterCommon {
2323
const MCRegisterInfo &MRI)
2424
: X86InstPrinterCommon(MAI, MII, MRI), HasCustomInstComment(false) {}
2525

26+
void printExprOperand(raw_ostream &OS, const MCExpr &E) override;
2627
void printRegName(raw_ostream &OS, MCRegister Reg) override;
2728
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
2829
const MCSubtargetInfo &STI, raw_ostream &OS) override;

llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626

2727
using namespace llvm;
2828

29+
void X86InstPrinterCommon::printExprOperand(raw_ostream &OS, const MCExpr &E) {
30+
MAI.printExpr(OS, E);
31+
}
32+
2933
void X86InstPrinterCommon::printCondCode(const MCInst *MI, unsigned Op,
3034
raw_ostream &O) {
3135
int64_t Imm = MI->getOperand(Op).getImm();
@@ -374,7 +378,7 @@ void X86InstPrinterCommon::printPCRelImm(const MCInst *MI, uint64_t Address,
374378
markup(O, Markup::Immediate) << formatHex((uint64_t)Address);
375379
} else {
376380
// Otherwise, just print the expression.
377-
MAI.printExpr(O, *Op.getExpr());
381+
printExprOperand(O, *Op.getExpr());
378382
}
379383
}
380384
}

llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
#include "llvm/MC/MCInstPrinter.h"
1818

1919
namespace llvm {
20+
class MCExpr;
2021

2122
class X86InstPrinterCommon : public MCInstPrinter {
2223
public:
2324
using MCInstPrinter::MCInstPrinter;
2425

26+
virtual void printExprOperand(raw_ostream &OS, const MCExpr &E);
2527
virtual void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) = 0;
2628
void printCondCode(const MCInst *MI, unsigned Op, raw_ostream &OS);
2729
void printCondFlags(const MCInst *MI, unsigned Op, raw_ostream &OS);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
; RUN: llc < %s -mtriple=x86_64 | FileCheck %s --check-prefix=ATT
2+
; RUN: llc < %s -mtriple=x86_64 -output-asm-variant=1 | FileCheck %s --check-prefix=INTEL
3+
4+
module asm "mov ($foo), %eax"
5+
6+
; ATT: movl ($foo), %eax
7+
; INTEL: mov eax, dword ptr [$foo]

llvm/test/CodeGen/X86/dollar-name.ll

Lines changed: 67 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,73 @@
1-
; RUN: llc < %s -mtriple=i386-linux | FileCheck %s
2-
; PR1339
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
;; See also dollar-name-asm.ll for module asm tests, which update_llc_test_checks.py doesn't support.
3+
; RUN: llc < %s -mtriple=i686 -relocation-model=static | FileCheck %s --check-prefix=STATIC
4+
; RUN: llc < %s -mtriple=x86_64 -relocation-model=pic | FileCheck %s --check-prefix=PIC
5+
; RUN: llc < %s -mtriple=x86_64 -relocation-model=pic -output-asm-variant=1 | FileCheck %s --check-prefix=INTEL-PIC
36

4-
@"$bar" = global i32 zeroinitializer
5-
@"$qux" = external dso_local global i32
7+
@"$arr" = global [2 x i32] zeroinitializer
8+
@"$arr_h" = hidden global [2 x i32] zeroinitializer
9+
@"$tls" = hidden thread_local global i32 0
610

711
define i32 @"$foo"() nounwind {
8-
; CHECK: movl $bar,
9-
; CHECK: addl $qux,
10-
; CHECK: calll $hen
11-
%m = load i32, ptr @"$bar"
12-
%n = load i32, ptr @"$qux"
13-
%t = add i32 %m, %n
14-
%u = call i32 @"$hen"(i32 %t)
12+
; STATIC-LABEL: $foo:
13+
; STATIC: # %bb.0:
14+
; STATIC-NEXT: movl ($arr), %eax
15+
; STATIC-NEXT: movl %gs:0, %ecx
16+
; STATIC-NEXT: addl ($arr+4), %eax
17+
; STATIC-NEXT: addl ($tls@NTPOFF)(%ecx), %eax
18+
; STATIC-NEXT: pushl ($arr_h)
19+
; STATIC-NEXT: pushl %eax
20+
; STATIC-NEXT: calll ($hen@PLT)
21+
; STATIC-NEXT: addl $8, %esp
22+
; STATIC-NEXT: retl
23+
;
24+
; PIC-LABEL: $foo:
25+
; PIC: # %bb.0:
26+
; PIC-NEXT: pushq %rbp
27+
; PIC-NEXT: pushq %r14
28+
; PIC-NEXT: pushq %rbx
29+
; PIC-NEXT: movq ($arr@GOTPCREL)(%rip), %r14
30+
; PIC-NEXT: movl (%r14), %ebx
31+
; PIC-NEXT: movl ($arr_h)(%rip), %ebp
32+
; PIC-NEXT: leaq ($tls@TLSLD)(%rip), %rdi
33+
; PIC-NEXT: callq __tls_get_addr@PLT
34+
; PIC-NEXT: addl 4(%r14), %ebx
35+
; PIC-NEXT: addl ($tls@DTPOFF)(%rax), %ebx
36+
; PIC-NEXT: movl %ebx, %edi
37+
; PIC-NEXT: movl %ebp, %esi
38+
; PIC-NEXT: callq ($hen@PLT)
39+
; PIC-NEXT: popq %rbx
40+
; PIC-NEXT: popq %r14
41+
; PIC-NEXT: popq %rbp
42+
; PIC-NEXT: retq
43+
;
44+
; INTEL-PIC-LABEL: $foo:
45+
; INTEL-PIC: # %bb.0:
46+
; INTEL-PIC-NEXT: push rbp
47+
; INTEL-PIC-NEXT: push r14
48+
; INTEL-PIC-NEXT: push rbx
49+
; INTEL-PIC-NEXT: mov r14, qword ptr [rip + $arr@GOTPCREL]
50+
; INTEL-PIC-NEXT: mov ebx, dword ptr [r14]
51+
; INTEL-PIC-NEXT: mov ebp, dword ptr [rip + $arr_h]
52+
; INTEL-PIC-NEXT: lea rdi, [rip + $tls@TLSLD]
53+
; INTEL-PIC-NEXT: call __tls_get_addr@PLT
54+
; INTEL-PIC-NEXT: add ebx, dword ptr [r14 + 4]
55+
; INTEL-PIC-NEXT: add ebx, dword ptr [rax + $tls@DTPOFF]
56+
; INTEL-PIC-NEXT: mov edi, ebx
57+
; INTEL-PIC-NEXT: mov esi, ebp
58+
; INTEL-PIC-NEXT: call $hen@PLT
59+
; INTEL-PIC-NEXT: pop rbx
60+
; INTEL-PIC-NEXT: pop r14
61+
; INTEL-PIC-NEXT: pop rbp
62+
; INTEL-PIC-NEXT: ret
63+
%m = load i32, ptr @"$arr"
64+
%m1 = load i32, ptr getelementptr inbounds nuw (i32, ptr @"$arr", i23 1)
65+
%m2 = load i32, ptr @"$arr_h"
66+
%tls_v = load i32, ptr @"$tls"
67+
%t0 = add i32 %m, %m1
68+
%t1 = add i32 %t0, %tls_v
69+
%u = call i32 @"$hen"(i32 %t1, i32 %m2)
1570
ret i32 %u
1671
}
1772

18-
declare i32 @"$hen"(i32 %a)
73+
declare i32 @"$hen"(i32 %a, i32 %b)

llvm/tools/llc/llc.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ static cl::opt<bool>
143143
static cl::opt<bool> ShowMCEncoding("show-mc-encoding", cl::Hidden,
144144
cl::desc("Show encoding in .s output"));
145145

146+
static cl::opt<unsigned>
147+
OutputAsmVariant("output-asm-variant",
148+
cl::desc("Syntax variant to use for output printing"));
149+
146150
static cl::opt<bool>
147151
DwarfDirectory("dwarf-directory", cl::Hidden,
148152
cl::desc("Use .file directives with an explicit directory"),
@@ -500,6 +504,8 @@ static int compileModule(char **argv, LLVMContext &Context) {
500504
Options.MCOptions.ShowMCEncoding = ShowMCEncoding;
501505
Options.MCOptions.AsmVerbose = AsmVerbose;
502506
Options.MCOptions.PreserveAsmComments = PreserveComments;
507+
if (OutputAsmVariant.getNumOccurrences())
508+
Options.MCOptions.OutputAsmVariant = OutputAsmVariant;
503509
Options.MCOptions.IASSearchPaths = IncludeDirs;
504510
Options.MCOptions.InstPrinterOptions = InstPrinterOptions;
505511
Options.MCOptions.SplitDwarfFile = SplitDwarfFile;

0 commit comments

Comments
 (0)