Skip to content

Commit e7aa4d5

Browse files
authored
Merge pull request #52 from Amanieu/rust-asm3
Inline assembly changes for RFC 2873
2 parents 94c0e0c + 66f695b commit e7aa4d5

File tree

15 files changed

+213
-25
lines changed

15 files changed

+213
-25
lines changed

Diff for: clang/lib/CodeGen/TargetInfo.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,10 @@ static void rewriteInputConstraintReferences(unsigned FirstIn,
11771177
if (NumDollars % 2 != 0 && Pos < AsmString.size()) {
11781178
// We have an operand reference.
11791179
size_t DigitStart = Pos;
1180+
if (AsmString[DigitStart] == '{') {
1181+
OS << '{';
1182+
++DigitStart;
1183+
}
11801184
size_t DigitEnd = AsmString.find_first_not_of("0123456789", DigitStart);
11811185
if (DigitEnd == std::string::npos)
11821186
DigitEnd = AsmString.size();

Diff for: clang/test/CodeGen/mozilla-ms-inline-asm.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ void invoke(void* that, unsigned methodIndex,
2727
// CHECK-SAME: sub esp,eax
2828
// CHECK-SAME: mov ecx,esp
2929
// CHECK-SAME: push $0
30-
// CHECK-SAME: call dword ptr $2
30+
// CHECK-SAME: call dword ptr ${2:P}
3131
// CHECK-SAME: {{.*}}__MSASMLABEL_.${:uid}__noparams:
3232
// CHECK-SAME: mov ecx,$3
3333
// CHECK-SAME: push ecx

Diff for: clang/test/CodeGen/ms-inline-asm.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ void t24_helper(void) {}
306306
void t24() {
307307
__asm call t24_helper
308308
// CHECK: t24
309-
// CHECK: call void asm sideeffect inteldialect "call dword ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(void ()* @t24_helper)
309+
// CHECK: call void asm sideeffect inteldialect "call dword ptr ${0:P}", "*m,~{dirflag},~{fpsr},~{flags}"(void ()* @t24_helper)
310310
}
311311

312312
void t25() {
@@ -681,7 +681,7 @@ void dot_operator(){
681681
void call_clobber() {
682682
__asm call t41
683683
// CHECK-LABEL: define void @call_clobber
684-
// CHECK: call void asm sideeffect inteldialect "call dword ptr $0", "*m,~{dirflag},~{fpsr},~{flags}"(void (i16)* @t41)
684+
// CHECK: call void asm sideeffect inteldialect "call dword ptr ${0:P}", "*m,~{dirflag},~{fpsr},~{flags}"(void (i16)* @t41)
685685
}
686686

687687
void xgetbv() {

Diff for: clang/test/CodeGen/ms-inline-asm.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ void test5() {
109109
__asm mov x, eax
110110
// CHECK: call void asm sideeffect inteldialect
111111
// CHECK-SAME: push $0
112-
// CHECK-SAME: call dword ptr $2
112+
// CHECK-SAME: call dword ptr ${2:P}
113113
// CHECK-SAME: mov $1, eax
114114
// CHECK-SAME: "=*m,=*m,*m,~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %y, i32* %x, i32 (float)* @_ZN2T5IiE6createIfEEiT_)
115115
}

Diff for: llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h

+4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ class MCParsedAsmOperand {
7171
/// variable/label? Only valid when parsing MS-style inline assembly.
7272
virtual bool needAddressOf() const { return false; }
7373

74+
/// isCallOperand - Is this an operand of an inline-assembly call instruction?
75+
/// Only valid when parsing MS-style inline assembly.
76+
virtual bool isCallOperand() const { return false; }
77+
7478
/// isOffsetOf - Do we need to emit code to get the offset of the variable,
7579
/// rather then the value of the variable? Only valid when parsing MS-style
7680
/// inline assembly.

Diff for: llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ enum AsmRewriteKind {
3535
AOK_Align, // Rewrite align as .align.
3636
AOK_EVEN, // Rewrite even as .even.
3737
AOK_Emit, // Rewrite _emit as .byte.
38+
AOK_CallInput, // Rewrite in terms of ${N:P}.
3839
AOK_Input, // Rewrite in terms of $N.
3940
AOK_Output, // Rewrite in terms of $N.
4041
AOK_SizeDirective, // Add a sizing directive (e.g., dword ptr).
@@ -49,6 +50,7 @@ const char AsmRewritePrecedence [] = {
4950
2, // AOK_EVEN
5051
2, // AOK_Emit
5152
3, // AOK_Input
53+
3, // AOK_CallInput
5254
3, // AOK_Output
5355
5, // AOK_SizeDirective
5456
1, // AOK_Label

Diff for: llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp

+33-4
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,17 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
207207
}
208208
if (Done) break;
209209

210+
bool HasCurlyBraces = false;
211+
if (*LastEmitted == '{') { // ${variable}
212+
++LastEmitted; // Consume '{' character.
213+
HasCurlyBraces = true;
214+
}
215+
210216
// If we have ${:foo}, then this is not a real operand reference, it is a
211217
// "magic" string reference, just like in .td files. Arrange to call
212218
// PrintSpecial.
213-
if (LastEmitted[0] == '{' && LastEmitted[1] == ':') {
214-
LastEmitted += 2;
219+
if (HasCurlyBraces && LastEmitted[0] == ':') {
220+
++LastEmitted;
215221
const char *StrStart = LastEmitted;
216222
const char *StrEnd = strchr(StrStart, '}');
217223
if (!StrEnd)
@@ -238,6 +244,27 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
238244
report_fatal_error("Invalid $ operand number in inline asm string: '" +
239245
Twine(AsmStr) + "'");
240246

247+
char Modifier[2] = { 0, 0 };
248+
249+
if (HasCurlyBraces) {
250+
// If we have curly braces, check for a modifier character. This
251+
// supports syntax like ${0:u}, which correspond to "%u0" in GCC asm.
252+
if (*LastEmitted == ':') {
253+
++LastEmitted; // Consume ':' character.
254+
if (*LastEmitted == 0)
255+
report_fatal_error("Bad ${:} expression in inline asm string: '" +
256+
Twine(AsmStr) + "'");
257+
258+
Modifier[0] = *LastEmitted;
259+
++LastEmitted; // Consume modifier character.
260+
}
261+
262+
if (*LastEmitted != '}')
263+
report_fatal_error("Bad ${} expression in inline asm string: '" +
264+
Twine(AsmStr) + "'");
265+
++LastEmitted; // Consume '}' character.
266+
}
267+
241268
// Okay, we finally have a value number. Ask the target to print this
242269
// operand!
243270
unsigned OpNo = InlineAsm::MIOp_FirstOperand;
@@ -262,9 +289,11 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
262289
++OpNo; // Skip over the ID number.
263290

264291
if (InlineAsm::isMemKind(OpFlags)) {
265-
Error = AP->PrintAsmMemoryOperand(MI, OpNo, /*Modifier*/ nullptr, OS);
292+
Error = AP->PrintAsmMemoryOperand(
293+
MI, OpNo, Modifier[0] ? Modifier : nullptr, OS);
266294
} else {
267-
Error = AP->PrintAsmOperand(MI, OpNo, /*Modifier*/ nullptr, OS);
295+
Error = AP->PrintAsmOperand(MI, OpNo,
296+
Modifier[0] ? Modifier : nullptr, OS);
268297
}
269298
}
270299
if (Error) {

Diff for: llvm/lib/MC/MCParser/AsmParser.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -5728,7 +5728,10 @@ bool AsmParser::parseMSInlineAsm(
57285728
InputDecls.push_back(OpDecl);
57295729
InputDeclsAddressOf.push_back(Operand.needAddressOf());
57305730
InputConstraints.push_back(Operand.getConstraint().str());
5731-
AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
5731+
if (Operand.isCallOperand())
5732+
AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
5733+
else
5734+
AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());
57325735
}
57335736
}
57345737

@@ -5818,6 +5821,9 @@ bool AsmParser::parseMSInlineAsm(
58185821
case AOK_Input:
58195822
OS << '$' << InputIdx++;
58205823
break;
5824+
case AOK_CallInput:
5825+
OS << "${" << InputIdx++ << ":P}";
5826+
break;
58215827
case AOK_Output:
58225828
OS << '$' << OutputIdx++;
58235829
break;

Diff for: llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -2855,6 +2855,15 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
28552855
}
28562856
}
28572857

2858+
// Mark the operands of a call instruction. These need to be handled
2859+
// differently when referenced in MS-style inline assembly.
2860+
if (Name.startswith("call") || Name.startswith("lcall")) {
2861+
for (size_t i = 1; i < Operands.size(); ++i) {
2862+
X86Operand &Op = static_cast<X86Operand &>(*Operands[i]);
2863+
Op.setCallOperand(true);
2864+
}
2865+
}
2866+
28582867
if (Flags)
28592868
Operands.push_back(X86Operand::CreatePrefix(Flags, NameLoc, NameLoc));
28602869
return false;

Diff for: llvm/lib/Target/X86/AsmParser/X86Operand.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct X86Operand final : public MCParsedAsmOperand {
3636
StringRef SymName;
3737
void *OpDecl;
3838
bool AddressOf;
39+
bool CallOperand;
3940

4041
struct TokOp {
4142
const char *Data;
@@ -77,7 +78,7 @@ struct X86Operand final : public MCParsedAsmOperand {
7778
};
7879

7980
X86Operand(KindTy K, SMLoc Start, SMLoc End)
80-
: Kind(K), StartLoc(Start), EndLoc(End) {}
81+
: Kind(K), StartLoc(Start), EndLoc(End), CallOperand(false) {}
8182

8283
StringRef getSymName() override { return SymName; }
8384
void *getOpDecl() override { return OpDecl; }
@@ -277,6 +278,9 @@ struct X86Operand final : public MCParsedAsmOperand {
277278
return AddressOf;
278279
}
279280

281+
bool isCallOperand() const override { return CallOperand; }
282+
void setCallOperand(bool IsCallOperand) { CallOperand = IsCallOperand; }
283+
280284
bool isMem() const override { return Kind == Memory; }
281285
bool isMemUnsized() const {
282286
return Kind == Memory && Mem.Size == 0;

Diff for: llvm/lib/Target/X86/X86AsmPrinter.cpp

+71-12
Original file line numberDiff line numberDiff line change
@@ -336,14 +336,22 @@ void X86AsmPrinter::PrintMemReference(const MachineInstr *MI, unsigned OpNo,
336336
PrintLeaMemReference(MI, OpNo, O, Modifier);
337337
}
338338

339+
339340
void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI,
340-
unsigned OpNo, raw_ostream &O) {
341+
unsigned OpNo, raw_ostream &O,
342+
const char *Modifier) {
341343
const MachineOperand &BaseReg = MI->getOperand(OpNo + X86::AddrBaseReg);
342344
unsigned ScaleVal = MI->getOperand(OpNo + X86::AddrScaleAmt).getImm();
343345
const MachineOperand &IndexReg = MI->getOperand(OpNo + X86::AddrIndexReg);
344346
const MachineOperand &DispSpec = MI->getOperand(OpNo + X86::AddrDisp);
345347
const MachineOperand &SegReg = MI->getOperand(OpNo + X86::AddrSegmentReg);
346348

349+
// If we really don't want to print out (rip), don't.
350+
bool HasBaseReg = BaseReg.getReg() != 0;
351+
if (HasBaseReg && Modifier && !strcmp(Modifier, "no-rip") &&
352+
BaseReg.getReg() == X86::RIP)
353+
HasBaseReg = false;
354+
347355
// If this has a segment register, print it.
348356
if (SegReg.getReg()) {
349357
PrintOperand(MI, OpNo + X86::AddrSegmentReg, O);
@@ -353,7 +361,7 @@ void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI,
353361
O << '[';
354362

355363
bool NeedPlus = false;
356-
if (BaseReg.getReg()) {
364+
if (HasBaseReg) {
357365
PrintOperand(MI, OpNo + X86::AddrBaseReg, O);
358366
NeedPlus = true;
359367
}
@@ -371,7 +379,7 @@ void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI,
371379
PrintOperand(MI, OpNo + X86::AddrDisp, O);
372380
} else {
373381
int64_t DispVal = DispSpec.getImm();
374-
if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) {
382+
if (DispVal || (!IndexReg.getReg() && !HasBaseReg)) {
375383
if (NeedPlus) {
376384
if (DispVal > 0)
377385
O << " + ";
@@ -389,7 +397,7 @@ void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI,
389397
static bool printAsmMRegister(X86AsmPrinter &P, const MachineOperand &MO,
390398
char Mode, raw_ostream &O) {
391399
unsigned Reg = MO.getReg();
392-
bool EmitPercent = true;
400+
bool EmitPercent = MO.getParent()->getInlineAsmDialect() == InlineAsm::AD_ATT;
393401

394402
if (!X86::GR8RegClass.contains(Reg) &&
395403
!X86::GR16RegClass.contains(Reg) &&
@@ -428,6 +436,42 @@ static bool printAsmMRegister(X86AsmPrinter &P, const MachineOperand &MO,
428436
return false;
429437
}
430438

439+
static bool printAsmVRegister(X86AsmPrinter &P, const MachineOperand &MO,
440+
char Mode, raw_ostream &O) {
441+
unsigned Reg = MO.getReg();
442+
bool EmitPercent = MO.getParent()->getInlineAsmDialect() == InlineAsm::AD_ATT;
443+
444+
unsigned Index;
445+
if (X86::VR128XRegClass.contains(Reg))
446+
Index = Reg - X86::XMM0;
447+
else if (X86::VR256XRegClass.contains(Reg))
448+
Index = Reg - X86::YMM0;
449+
else if (X86::VR512RegClass.contains(Reg))
450+
Index = Reg - X86::ZMM0;
451+
else
452+
return true;
453+
454+
switch (Mode) {
455+
default: // Unknown mode.
456+
return true;
457+
case 'x': // Print V4SFmode register
458+
Reg = X86::XMM0 + Index;
459+
break;
460+
case 't': // Print V8SFmode register
461+
Reg = X86::YMM0 + Index;
462+
break;
463+
case 'g': // Print V16SFmode register
464+
Reg = X86::ZMM0 + Index;
465+
break;
466+
}
467+
468+
if (EmitPercent)
469+
O << '%';
470+
471+
O << X86ATTInstPrinter::getRegisterName(Reg);
472+
return false;
473+
}
474+
431475
/// PrintAsmOperand - Print out an operand for an inline asm expression.
432476
///
433477
bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
@@ -502,6 +546,14 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
502546
PrintOperand(MI, OpNo, O);
503547
return false;
504548

549+
case 'x': // Print V4SFmode register
550+
case 't': // Print V8SFmode register
551+
case 'g': // Print V16SFmode register
552+
if (MO.isReg())
553+
return printAsmVRegister(*this, MO, ExtraCode[0], O);
554+
PrintOperand(MI, OpNo, O);
555+
return false;
556+
505557
case 'P': // This is the operand of a call, treat specially.
506558
PrintPCRelImm(MI, OpNo, O);
507559
return false;
@@ -524,11 +576,6 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
524576
bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
525577
const char *ExtraCode,
526578
raw_ostream &O) {
527-
if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) {
528-
PrintIntelMemReference(MI, OpNo, O);
529-
return false;
530-
}
531-
532579
if (ExtraCode && ExtraCode[0]) {
533580
if (ExtraCode[1] != 0) return true; // Unknown modifier.
534581

@@ -542,14 +589,26 @@ bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
542589
// These only apply to registers, ignore on mem.
543590
break;
544591
case 'H':
545-
PrintMemReference(MI, OpNo, O, "H");
592+
if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) {
593+
return true; // Unsupported modifier in Intel inline assembly.
594+
} else {
595+
PrintMemReference(MI, OpNo, O, "H");
596+
}
546597
return false;
547598
case 'P': // Don't print @PLT, but do print as memory.
548-
PrintMemReference(MI, OpNo, O, "no-rip");
599+
if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) {
600+
PrintIntelMemReference(MI, OpNo, O, "no-rip");
601+
} else {
602+
PrintMemReference(MI, OpNo, O, "no-rip");
603+
}
549604
return false;
550605
}
551606
}
552-
PrintMemReference(MI, OpNo, O, nullptr);
607+
if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) {
608+
PrintIntelMemReference(MI, OpNo, O, nullptr);
609+
} else {
610+
PrintMemReference(MI, OpNo, O, nullptr);
611+
}
553612
return false;
554613
}
555614

Diff for: llvm/lib/Target/X86/X86AsmPrinter.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
112112
void PrintMemReference(const MachineInstr *MI, unsigned OpNo, raw_ostream &O,
113113
const char *Modifier);
114114
void PrintIntelMemReference(const MachineInstr *MI, unsigned OpNo,
115-
raw_ostream &O);
115+
raw_ostream &O, const char *Modifier);
116116

117117
public:
118118
X86AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);

0 commit comments

Comments
 (0)