Skip to content

Commit 1c545f6

Browse files
committed
[ms] [X86] Use "P" modifier on all branch-target operands in inline X86 assembly.
Summary: Extend D71677 to apply to all branch-target operands, rather than special-casing call instructions. Also add a regression test for llvm.org/PR44272, since this finishes fixing it. Reviewers: thakis, rnk Reviewed By: thakis Subscribers: merge_guards_bot, hiraditya, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D72417
1 parent 3408940 commit 1c545f6

File tree

10 files changed

+101
-97
lines changed

10 files changed

+101
-97
lines changed

clang/test/CodeGen/ms-inline-asm-64.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,17 @@ int t4() {
5858
// CHECK-SAME: mov [ebx + $$4], ecx
5959
// CHECK-SAME: "*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(%struct.t3_type* %{{.*}})
6060
}
61+
62+
void bar() {}
63+
64+
void t5() {
65+
__asm {
66+
call bar
67+
jmp bar
68+
}
69+
// CHECK: t5
70+
// CHECK: call void asm sideeffect inteldialect
71+
// CHECK-SAME: call qword ptr ${0:P}
72+
// CHECK-SAME: jmp qword ptr ${1:P}
73+
// CHECK-SAME: "*m,*m,~{dirflag},~{fpsr},~{flags}"(void (...)* bitcast (void ()* @bar to void (...)*), void (...)* bitcast (void ()* @bar to void (...)*))
74+
}

llvm/include/llvm/MC/MCInstrDesc.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ enum OperandConstraint {
3737
/// These are flags set on operands, but should be considered
3838
/// private, all access should go through the MCOperandInfo accessors.
3939
/// See the accessors for a description of what these are.
40-
enum OperandFlags { LookupPtrRegClass = 0, Predicate, OptionalDef };
40+
enum OperandFlags {
41+
LookupPtrRegClass = 0,
42+
Predicate,
43+
OptionalDef,
44+
BranchTarget
45+
};
4146

4247
/// Operands are tagged with one of the values of this enum.
4348
enum OperandType {
@@ -98,6 +103,9 @@ class MCOperandInfo {
98103
/// Set if this operand is a optional def.
99104
bool isOptionalDef() const { return Flags & (1 << MCOI::OptionalDef); }
100105

106+
/// Set if this operand is a branch target.
107+
bool isBranchTarget() const { return Flags & (1 << MCOI::BranchTarget); }
108+
101109
bool isGenericType() const {
102110
return OperandType >= MCOI::OPERAND_FIRST_GENERIC &&
103111
OperandType <= MCOI::OPERAND_LAST_GENERIC;

llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,6 @@ 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-
7874
/// isOffsetOfLocal - Do we need to emit code to get the offset of the local
7975
/// variable, rather than its value? Only valid when parsing MS-style inline
8076
/// assembly.

llvm/lib/MC/MCParser/AsmParser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5845,7 +5845,7 @@ bool AsmParser::parseMSInlineAsm(
58455845
InputDecls.push_back(OpDecl);
58465846
InputDeclsAddressOf.push_back(Operand.needAddressOf());
58475847
InputConstraints.push_back(Constraint.str());
5848-
if (Operand.isCallOperand())
5848+
if (Desc.OpInfo[i - 1].isBranchTarget())
58495849
AsmStrRewrites.emplace_back(AOK_CallInput, Start, SymName.size());
58505850
else
58515851
AsmStrRewrites.emplace_back(AOK_Input, Start, SymName.size());

llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2924,15 +2924,6 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
29242924
}
29252925
}
29262926

2927-
// Mark the operands of a call instruction. These need to be handled
2928-
// differently when referenced in MS-style inline assembly.
2929-
if (Name.startswith("call") || Name.startswith("lcall")) {
2930-
for (size_t i = 1; i < Operands.size(); ++i) {
2931-
X86Operand &Op = static_cast<X86Operand &>(*Operands[i]);
2932-
Op.setCallOperand(true);
2933-
}
2934-
}
2935-
29362927
if (Flags)
29372928
Operands.push_back(X86Operand::CreatePrefix(Flags, NameLoc, NameLoc));
29382929
return false;

llvm/lib/Target/X86/AsmParser/X86Operand.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,9 +284,6 @@ struct X86Operand final : public MCParsedAsmOperand {
284284

285285
bool needAddressOf() const override { return AddressOf; }
286286

287-
bool isCallOperand() const override { return CallOperand; }
288-
void setCallOperand(bool IsCallOperand) { CallOperand = IsCallOperand; }
289-
290287
bool isMem() const override { return Kind == Memory; }
291288
bool isMemUnsized() const {
292289
return Kind == Memory && Mem.Size == 0;

llvm/lib/Target/X86/X86InstrControl.td

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,12 @@ let isCall = 1 in
220220
// registers are added manually.
221221
let Uses = [ESP, SSP] in {
222222
def CALLpcrel32 : Ii32PCRel<0xE8, RawFrm,
223-
(outs), (ins i32imm_pcrel:$dst),
223+
(outs), (ins i32imm_brtarget:$dst),
224224
"call{l}\t$dst", []>, OpSize32,
225225
Requires<[Not64BitMode]>, Sched<[WriteJump]>;
226226
let hasSideEffects = 0 in
227227
def CALLpcrel16 : Ii16PCRel<0xE8, RawFrm,
228-
(outs), (ins i16imm_pcrel:$dst),
228+
(outs), (ins i16imm_brtarget:$dst),
229229
"call{w}\t$dst", []>, OpSize16,
230230
Sched<[WriteJump]>;
231231
def CALL16r : I<0xFF, MRM2r, (outs), (ins GR16:$dst),
@@ -285,15 +285,15 @@ let isCall = 1 in
285285
// Tail call stuff.
286286
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
287287
isCodeGenOnly = 1, Uses = [ESP, SSP] in {
288-
def TCRETURNdi : PseudoI<(outs), (ins i32imm_pcrel:$dst, i32imm:$offset),
288+
def TCRETURNdi : PseudoI<(outs), (ins i32imm_brtarget:$dst, i32imm:$offset),
289289
[]>, Sched<[WriteJump]>, NotMemoryFoldable;
290290
def TCRETURNri : PseudoI<(outs), (ins ptr_rc_tailcall:$dst, i32imm:$offset),
291291
[]>, Sched<[WriteJump]>, NotMemoryFoldable;
292292
let mayLoad = 1 in
293293
def TCRETURNmi : PseudoI<(outs), (ins i32mem_TC:$dst, i32imm:$offset),
294294
[]>, Sched<[WriteJumpLd]>;
295295

296-
def TAILJMPd : PseudoI<(outs), (ins i32imm_pcrel:$dst),
296+
def TAILJMPd : PseudoI<(outs), (ins i32imm_brtarget:$dst),
297297
[]>, Sched<[WriteJump]>;
298298

299299
def TAILJMPr : PseudoI<(outs), (ins ptr_rc_tailcall:$dst),
@@ -309,10 +309,11 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1,
309309
isCodeGenOnly = 1, SchedRW = [WriteJump] in
310310
let Uses = [ESP, EFLAGS, SSP] in {
311311
def TCRETURNdicc : PseudoI<(outs),
312-
(ins i32imm_pcrel:$dst, i32imm:$offset, i32imm:$cond), []>;
312+
(ins i32imm_brtarget:$dst, i32imm:$offset, i32imm:$cond),
313+
[]>;
313314

314315
// This gets substituted to a conditional jump instruction in MC lowering.
315-
def TAILJMPd_CC : PseudoI<(outs), (ins i32imm_pcrel:$dst, i32imm:$cond), []>;
316+
def TAILJMPd_CC : PseudoI<(outs), (ins i32imm_brtarget:$dst, i32imm:$cond), []>;
316317
}
317318

318319

@@ -328,7 +329,7 @@ let isCall = 1, Uses = [RSP, SSP], SchedRW = [WriteJump] in {
328329
// that the offset between an arbitrary immediate and the call will fit in
329330
// the 32-bit pcrel field that we have.
330331
def CALL64pcrel32 : Ii32PCRel<0xE8, RawFrm,
331-
(outs), (ins i64i32imm_pcrel:$dst),
332+
(outs), (ins i64i32imm_brtarget:$dst),
332333
"call{q}\t$dst", []>, OpSize32,
333334
Requires<[In64BitMode]>;
334335
def CALL64r : I<0xFF, MRM2r, (outs), (ins GR64:$dst),
@@ -357,7 +358,7 @@ let isCall = 1, Uses = [RSP, SSP], SchedRW = [WriteJump] in {
357358
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
358359
isCodeGenOnly = 1, Uses = [RSP, SSP] in {
359360
def TCRETURNdi64 : PseudoI<(outs),
360-
(ins i64i32imm_pcrel:$dst, i32imm:$offset),
361+
(ins i64i32imm_brtarget:$dst, i32imm:$offset),
361362
[]>, Sched<[WriteJump]>;
362363
def TCRETURNri64 : PseudoI<(outs),
363364
(ins ptr_rc_tailcall:$dst, i32imm:$offset),
@@ -367,7 +368,7 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
367368
(ins i64mem_TC:$dst, i32imm:$offset),
368369
[]>, Sched<[WriteJumpLd]>, NotMemoryFoldable;
369370

370-
def TAILJMPd64 : PseudoI<(outs), (ins i64i32imm_pcrel:$dst),
371+
def TAILJMPd64 : PseudoI<(outs), (ins i64i32imm_brtarget:$dst),
371372
[]>, Sched<[WriteJump]>;
372373

373374
def TAILJMPr64 : PseudoI<(outs), (ins ptr_rc_tailcall:$dst),
@@ -415,10 +416,10 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1,
415416
isCodeGenOnly = 1, SchedRW = [WriteJump] in
416417
let Uses = [RSP, EFLAGS, SSP] in {
417418
def TCRETURNdi64cc : PseudoI<(outs),
418-
(ins i64i32imm_pcrel:$dst, i32imm:$offset,
419+
(ins i64i32imm_brtarget:$dst, i32imm:$offset,
419420
i32imm:$cond), []>;
420421

421422
// This gets substituted to a conditional jump instruction in MC lowering.
422423
def TAILJMPd64_CC : PseudoI<(outs),
423-
(ins i64i32imm_pcrel:$dst, i32imm:$cond), []>;
424+
(ins i64i32imm_brtarget:$dst, i32imm:$cond), []>;
424425
}

llvm/lib/Target/X86/X86InstrInfo.td

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -454,33 +454,33 @@ def i64mem_TC : Operand<i64> {
454454
let OperandType = "OPERAND_MEMORY";
455455
}
456456

457-
let OperandType = "OPERAND_PCREL",
458-
ParserMatchClass = X86AbsMemAsmOperand,
459-
PrintMethod = "printPCRelImm" in {
460-
def i32imm_pcrel : Operand<i32>;
461-
def i16imm_pcrel : Operand<i16>;
462-
463-
// Branch targets have OtherVT type and print as pc-relative values.
464-
def brtarget : Operand<OtherVT>;
465-
def brtarget8 : Operand<OtherVT>;
466-
467-
}
468-
469457
// Special parser to detect 16-bit mode to select 16-bit displacement.
470458
def X86AbsMem16AsmOperand : AsmOperandClass {
471459
let Name = "AbsMem16";
472460
let RenderMethod = "addAbsMemOperands";
473461
let SuperClasses = [X86AbsMemAsmOperand];
474462
}
475463

476-
// Branch targets have OtherVT type and print as pc-relative values.
477-
let OperandType = "OPERAND_PCREL",
478-
PrintMethod = "printPCRelImm" in {
479-
let ParserMatchClass = X86AbsMem16AsmOperand in
480-
def brtarget16 : Operand<OtherVT>;
481-
let ParserMatchClass = X86AbsMemAsmOperand in
482-
def brtarget32 : Operand<OtherVT>;
464+
// Branch targets print as pc-relative values.
465+
class BranchTargetOperand<ValueType ty> : Operand<ty> {
466+
let OperandType = "OPERAND_PCREL";
467+
let PrintMethod = "printPCRelImm";
468+
let ParserMatchClass = X86AbsMemAsmOperand;
469+
}
470+
471+
def i32imm_brtarget : BranchTargetOperand<i32>;
472+
def i16imm_brtarget : BranchTargetOperand<i16>;
473+
474+
// 64-bits but only 32 bits are significant, and those bits are treated as being
475+
// pc relative.
476+
def i64i32imm_brtarget : BranchTargetOperand<i64>;
477+
478+
def brtarget : BranchTargetOperand<OtherVT>;
479+
def brtarget8 : BranchTargetOperand<OtherVT>;
480+
def brtarget16 : BranchTargetOperand<OtherVT> {
481+
let ParserMatchClass = X86AbsMem16AsmOperand;
483482
}
483+
def brtarget32 : BranchTargetOperand<OtherVT>;
484484

485485
let RenderMethod = "addSrcIdxOperands" in {
486486
def X86SrcIdx8Operand : AsmOperandClass {
@@ -756,14 +756,6 @@ def i64u8imm : Operand<i64> {
756756
let OperandType = "OPERAND_IMMEDIATE";
757757
}
758758

759-
// 64-bits but only 32 bits are significant, and those bits are treated as being
760-
// pc relative.
761-
def i64i32imm_pcrel : Operand<i64> {
762-
let PrintMethod = "printPCRelImm";
763-
let ParserMatchClass = X86AbsMemAsmOperand;
764-
let OperandType = "OPERAND_PCREL";
765-
}
766-
767759
def lea64_32mem : Operand<i32> {
768760
let PrintMethod = "printanymem";
769761
let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm, SEGMENT_REG);

llvm/utils/TableGen/InstrInfoEmitter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
164164
if (Op.Rec->isSubClassOf("OptionalDefOperand"))
165165
Res += "|(1<<MCOI::OptionalDef)";
166166

167+
// Branch target operands. Check to see if the original unexpanded
168+
// operand was of type BranchTargetOperand.
169+
if (Op.Rec->isSubClassOf("BranchTargetOperand"))
170+
Res += "|(1<<MCOI::BranchTarget)";
171+
167172
// Fill in operand type.
168173
Res += ", ";
169174
assert(!Op.OperandType.empty() && "Invalid operand type.");

llvm/utils/TableGen/X86RecognizableInstr.cpp

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -879,9 +879,9 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
879879
TYPE("i128mem", TYPE_M)
880880
TYPE("i256mem", TYPE_M)
881881
TYPE("i512mem", TYPE_M)
882-
TYPE("i64i32imm_pcrel", TYPE_REL)
883-
TYPE("i16imm_pcrel", TYPE_REL)
884-
TYPE("i32imm_pcrel", TYPE_REL)
882+
TYPE("i64i32imm_brtarget", TYPE_REL)
883+
TYPE("i16imm_brtarget", TYPE_REL)
884+
TYPE("i32imm_brtarget", TYPE_REL)
885885
TYPE("ccode", TYPE_IMM)
886886
TYPE("AVX512RC", TYPE_IMM)
887887
TYPE("brtarget32", TYPE_REL)
@@ -1169,45 +1169,45 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s,
11691169
if(OpSize != X86Local::OpSize16) {
11701170
// For instructions without an OpSize prefix, a declared 16-bit register or
11711171
// immediate encoding is special.
1172-
ENCODING("i16imm", ENCODING_IW)
1172+
ENCODING("i16imm", ENCODING_IW)
11731173
}
1174-
ENCODING("i16imm", ENCODING_Iv)
1175-
ENCODING("i16i8imm", ENCODING_IB)
1176-
ENCODING("i32imm", ENCODING_Iv)
1177-
ENCODING("i32i8imm", ENCODING_IB)
1178-
ENCODING("i64i32imm", ENCODING_ID)
1179-
ENCODING("i64i8imm", ENCODING_IB)
1180-
ENCODING("i8imm", ENCODING_IB)
1181-
ENCODING("u8imm", ENCODING_IB)
1182-
ENCODING("i16u8imm", ENCODING_IB)
1183-
ENCODING("i32u8imm", ENCODING_IB)
1184-
ENCODING("i64u8imm", ENCODING_IB)
1185-
ENCODING("i64i32imm_pcrel", ENCODING_ID)
1186-
ENCODING("i16imm_pcrel", ENCODING_IW)
1187-
ENCODING("i32imm_pcrel", ENCODING_ID)
1188-
ENCODING("brtarget32", ENCODING_ID)
1189-
ENCODING("brtarget16", ENCODING_IW)
1190-
ENCODING("brtarget8", ENCODING_IB)
1191-
ENCODING("i64imm", ENCODING_IO)
1192-
ENCODING("offset16_8", ENCODING_Ia)
1193-
ENCODING("offset16_16", ENCODING_Ia)
1194-
ENCODING("offset16_32", ENCODING_Ia)
1195-
ENCODING("offset32_8", ENCODING_Ia)
1196-
ENCODING("offset32_16", ENCODING_Ia)
1197-
ENCODING("offset32_32", ENCODING_Ia)
1198-
ENCODING("offset32_64", ENCODING_Ia)
1199-
ENCODING("offset64_8", ENCODING_Ia)
1200-
ENCODING("offset64_16", ENCODING_Ia)
1201-
ENCODING("offset64_32", ENCODING_Ia)
1202-
ENCODING("offset64_64", ENCODING_Ia)
1203-
ENCODING("srcidx8", ENCODING_SI)
1204-
ENCODING("srcidx16", ENCODING_SI)
1205-
ENCODING("srcidx32", ENCODING_SI)
1206-
ENCODING("srcidx64", ENCODING_SI)
1207-
ENCODING("dstidx8", ENCODING_DI)
1208-
ENCODING("dstidx16", ENCODING_DI)
1209-
ENCODING("dstidx32", ENCODING_DI)
1210-
ENCODING("dstidx64", ENCODING_DI)
1174+
ENCODING("i16imm", ENCODING_Iv)
1175+
ENCODING("i16i8imm", ENCODING_IB)
1176+
ENCODING("i32imm", ENCODING_Iv)
1177+
ENCODING("i32i8imm", ENCODING_IB)
1178+
ENCODING("i64i32imm", ENCODING_ID)
1179+
ENCODING("i64i8imm", ENCODING_IB)
1180+
ENCODING("i8imm", ENCODING_IB)
1181+
ENCODING("u8imm", ENCODING_IB)
1182+
ENCODING("i16u8imm", ENCODING_IB)
1183+
ENCODING("i32u8imm", ENCODING_IB)
1184+
ENCODING("i64u8imm", ENCODING_IB)
1185+
ENCODING("i64i32imm_brtarget", ENCODING_ID)
1186+
ENCODING("i16imm_brtarget", ENCODING_IW)
1187+
ENCODING("i32imm_brtarget", ENCODING_ID)
1188+
ENCODING("brtarget32", ENCODING_ID)
1189+
ENCODING("brtarget16", ENCODING_IW)
1190+
ENCODING("brtarget8", ENCODING_IB)
1191+
ENCODING("i64imm", ENCODING_IO)
1192+
ENCODING("offset16_8", ENCODING_Ia)
1193+
ENCODING("offset16_16", ENCODING_Ia)
1194+
ENCODING("offset16_32", ENCODING_Ia)
1195+
ENCODING("offset32_8", ENCODING_Ia)
1196+
ENCODING("offset32_16", ENCODING_Ia)
1197+
ENCODING("offset32_32", ENCODING_Ia)
1198+
ENCODING("offset32_64", ENCODING_Ia)
1199+
ENCODING("offset64_8", ENCODING_Ia)
1200+
ENCODING("offset64_16", ENCODING_Ia)
1201+
ENCODING("offset64_32", ENCODING_Ia)
1202+
ENCODING("offset64_64", ENCODING_Ia)
1203+
ENCODING("srcidx8", ENCODING_SI)
1204+
ENCODING("srcidx16", ENCODING_SI)
1205+
ENCODING("srcidx32", ENCODING_SI)
1206+
ENCODING("srcidx64", ENCODING_SI)
1207+
ENCODING("dstidx8", ENCODING_DI)
1208+
ENCODING("dstidx16", ENCODING_DI)
1209+
ENCODING("dstidx32", ENCODING_DI)
1210+
ENCODING("dstidx64", ENCODING_DI)
12111211
errs() << "Unhandled relocation encoding " << s << "\n";
12121212
llvm_unreachable("Unhandled relocation encoding");
12131213
}

0 commit comments

Comments
 (0)