[llvm] 9566405 - [Inline asm] Fix mangle problem when variable used in inline asm.
Xiang1 Zhang via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 23 18:41:48 PDT 2022
Author: Xiang1 Zhang
Date: 2022-03-24T09:41:23+08:00
New Revision: 95664050201dbe595d5749bf0212f3847e1d9403
URL: https://github.com/llvm/llvm-project/commit/95664050201dbe595d5749bf0212f3847e1d9403
DIFF: https://github.com/llvm/llvm-project/commit/95664050201dbe595d5749bf0212f3847e1d9403.diff
LOG: [Inline asm] Fix mangle problem when variable used in inline asm.
(Correct 'Mem symbol + IntelExpr' output in PIC model)
Reviewed By: skan
Differential Revision: https://reviews.llvm.org/D121785
Added:
llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-1-reg.ll
llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-2-regs.ll
llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-nopic.ll
llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-1-reg.ll
llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-2-regs.ll
Modified:
llvm/docs/LangRef.rst
llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
llvm/lib/Target/X86/X86AsmPrinter.cpp
Removed:
################################################################################
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index f76718c077129..7e21904f16997 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -5078,8 +5078,10 @@ X86:
the operand. (The behavior for relocatable symbol expressions is a
target-specific behavior for this typically target-independent modifier)
- ``H``: Print a memory reference with additional offset +8.
-- ``P``: Print a memory reference or operand for use as the argument of a call
- instruction. (E.g. omit ``(rip)``, even though it's PC-relative.)
+- ``P``: Print a memory reference used as the argument of a call instruction or
+ used with explicit base reg and index reg as its offset. So it can not use
+ additional regs to present the memory reference. (E.g. omit ``(rip)``, even
+ though it's PC-relative.)
XCore:
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 4d7bc65bade56..8008b53040129 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -432,6 +432,8 @@ class X86AsmParser : public MCTargetAsmParser {
short BracCount;
bool MemExpr;
bool OffsetOperator;
+ bool AttachToOperandIdx;
+ bool IsPIC;
SMLoc OffsetOperatorLoc;
AsmTypeInfo CurType;
@@ -449,7 +451,8 @@ class X86AsmParser : public MCTargetAsmParser {
IntelExprStateMachine()
: State(IES_INIT), PrevState(IES_ERROR), BaseReg(0), IndexReg(0),
TmpReg(0), Scale(0), Imm(0), Sym(nullptr), BracCount(0),
- MemExpr(false), OffsetOperator(false) {}
+ MemExpr(false), OffsetOperator(false), AttachToOperandIdx(false),
+ IsPIC(false) {}
void addImm(int64_t imm) { Imm += imm; }
short getBracCount() const { return BracCount; }
@@ -469,9 +472,29 @@ class X86AsmParser : public MCTargetAsmParser {
bool isValidEndState() const {
return State == IES_RBRAC || State == IES_INTEGER;
}
+
+ // Is the intel expression appended after an operand index.
+ // [OperandIdx][Intel Expression]
+ // This is neccessary for checking if it is an independent
+ // intel expression at back end when parse inline asm.
+ void setAppendAfterOperand() { AttachToOperandIdx = true; }
+
+ bool isPIC() const { return IsPIC; }
+ void setPIC() { IsPIC = true; }
+
bool hadError() const { return State == IES_ERROR; }
const InlineAsmIdentifierInfo &getIdentifierInfo() const { return Info; }
+ bool regsUseUpError(StringRef &ErrMsg) {
+ // This case mostly happen in inline asm, e.g. Arr[BaseReg + IndexReg]
+ // can not intruduce additional register in inline asm in PIC model.
+ if (IsPIC && AttachToOperandIdx)
+ ErrMsg = "Don't use 2 or more regs for mem offset in PIC model!";
+ else
+ ErrMsg = "BaseReg/IndexReg already set!";
+ return true;
+ }
+
void onOr() {
IntelExprState CurrState = State;
switch (State) {
@@ -655,10 +678,8 @@ class X86AsmParser : public MCTargetAsmParser {
if (!BaseReg) {
BaseReg = TmpReg;
} else {
- if (IndexReg) {
- ErrMsg = "BaseReg/IndexReg already set!";
- return true;
- }
+ if (IndexReg)
+ return regsUseUpError(ErrMsg);
IndexReg = TmpReg;
Scale = 0;
}
@@ -716,10 +737,8 @@ class X86AsmParser : public MCTargetAsmParser {
if (!BaseReg) {
BaseReg = TmpReg;
} else {
- if (IndexReg) {
- ErrMsg = "BaseReg/IndexReg already set!";
- return true;
- }
+ if (IndexReg)
+ return regsUseUpError(ErrMsg);
IndexReg = TmpReg;
Scale = 0;
}
@@ -777,10 +796,8 @@ class X86AsmParser : public MCTargetAsmParser {
case IES_MULTIPLY:
// Index Register - Scale * Register
if (PrevState == IES_INTEGER) {
- if (IndexReg) {
- ErrMsg = "BaseReg/IndexReg already set!";
- return true;
- }
+ if (IndexReg)
+ return regsUseUpError(ErrMsg);
State = IES_REGISTER;
IndexReg = Reg;
// Get the scale and replace the 'Scale * Register' with '0'.
@@ -861,10 +878,8 @@ class X86AsmParser : public MCTargetAsmParser {
State = IES_INTEGER;
if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
// Index Register - Register * Scale
- if (IndexReg) {
- ErrMsg = "BaseReg/IndexReg already set!";
- return true;
- }
+ if (IndexReg)
+ return regsUseUpError(ErrMsg);
IndexReg = TmpReg;
Scale = TmpInt;
if (checkScale(Scale, ErrMsg))
@@ -945,7 +960,7 @@ class X86AsmParser : public MCTargetAsmParser {
BracCount++;
return false;
}
- bool onRBrac() {
+ bool onRBrac(StringRef &ErrMsg) {
IntelExprState CurrState = State;
switch (State) {
default:
@@ -955,8 +970,10 @@ class X86AsmParser : public MCTargetAsmParser {
case IES_OFFSET:
case IES_REGISTER:
case IES_RPAREN:
- if (BracCount-- != 1)
+ if (BracCount-- != 1) {
+ ErrMsg = "unexpected bracket encountered";
return true;
+ }
State = IES_RBRAC;
if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
// If we already have a BaseReg, then assume this is the IndexReg with
@@ -964,7 +981,8 @@ class X86AsmParser : public MCTargetAsmParser {
if (!BaseReg) {
BaseReg = TmpReg;
} else {
- assert (!IndexReg && "BaseReg/IndexReg already set!");
+ if (IndexReg)
+ return regsUseUpError(ErrMsg);
IndexReg = TmpReg;
Scale = 0;
}
@@ -1111,6 +1129,8 @@ class X86AsmParser : public MCTargetAsmParser {
InlineAsmIdentifierInfo &Info,
bool IsUnevaluatedOperand, SMLoc &End,
bool IsParsingOffsetOperator = false);
+ void tryParseOperandIdx(AsmToken::TokenKind PrevTK,
+ IntelExprStateMachine &SM);
bool ParseMemOperand(unsigned SegReg, const MCExpr *Disp, SMLoc StartLoc,
SMLoc EndLoc, OperandVector &Operands);
@@ -1841,11 +1861,25 @@ bool X86AsmParser::ParseMasmNamedOperator(StringRef Name,
return true;
}
+// Check if current intel expression append after an operand.
+// Like: [Operand][Intel Expression]
+void X86AsmParser::tryParseOperandIdx(AsmToken::TokenKind PrevTK,
+ IntelExprStateMachine &SM) {
+ if (PrevTK != AsmToken::RBrac)
+ return;
+
+ SM.setAppendAfterOperand();
+}
+
bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
MCAsmParser &Parser = getParser();
StringRef ErrMsg;
AsmToken::TokenKind PrevTK = AsmToken::Error;
+
+ if (getContext().getObjectFileInfo()->isPositionIndependent())
+ SM.setPIC();
+
bool Done = false;
while (!Done) {
// Get a fresh reference on each loop iteration in case the previous
@@ -2123,10 +2157,12 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
case AsmToken::LBrac:
if (SM.onLBrac())
return Error(Tok.getLoc(), "unexpected bracket encountered");
+ tryParseOperandIdx(PrevTK, SM);
break;
case AsmToken::RBrac:
- if (SM.onRBrac())
- return Error(Tok.getLoc(), "unexpected bracket encountered");
+ if (SM.onRBrac(ErrMsg)) {
+ return Error(Tok.getLoc(), ErrMsg);
+ }
break;
case AsmToken::LParen: SM.onLParen(); break;
case AsmToken::RParen: SM.onRParen(); break;
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index b7ae87348107f..0693d807b94f7 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -362,6 +362,14 @@ void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI,
BaseReg.getReg() == X86::RIP)
HasBaseReg = false;
+ // If we really just want to print out displacement.
+ bool HasIndexReg = IndexReg.getReg() != 0;
+ if (Modifier && (DispSpec.isGlobal() || DispSpec.isSymbol()) &&
+ !strcmp(Modifier, "disp-only")) {
+ HasBaseReg = false;
+ HasIndexReg = false;
+ }
+
// If this has a segment register, print it.
if (SegReg.getReg()) {
PrintOperand(MI, OpNo + X86::AddrSegmentReg, O);
@@ -605,11 +613,14 @@ bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
PrintMemReference(MI, OpNo, O, "H");
}
return false;
- case 'P': // Don't print @PLT, but do print as memory.
+ // Print memory only with displacement. The Modifer 'P' is used in inline
+ // asm to present a call symbol or a global symbol which can not use base
+ // reg or index reg.
+ case 'P':
if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) {
- PrintIntelMemReference(MI, OpNo, O, "no-rip");
+ PrintIntelMemReference(MI, OpNo, O, "disp-only");
} else {
- PrintMemReference(MI, OpNo, O, "no-rip");
+ PrintMemReference(MI, OpNo, O, "disp-only");
}
return false;
}
diff --git a/llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-1-reg.ll b/llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-1-reg.ll
new file mode 100644
index 0000000000000..eaccf203eaa6a
--- /dev/null
+++ b/llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-1-reg.ll
@@ -0,0 +1,95 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64-unknown-unknown -relocation-model=pic %s -o - | FileCheck %s
+
+; Tests come from "clang/test/CodeGen/ms-inline-asm-variables.c"
+; int gVar;
+; void t1() {
+; __asm add eax, dword ptr gVar[rax]
+; __asm add dword ptr [rax+gVar], eax
+; __asm add ebx, dword ptr gVar[271 - 82 + 81 + rbx]
+; __asm add dword ptr [rbx + gVar + 828], ebx
+; gVar = 3;
+; }
+;
+; void t2(void) {
+; int lVar;
+; __asm mov eax, dword ptr lVar[rax]
+; __asm mov dword ptr [rax+lVar], eax
+; __asm mov ebx, dword ptr lVar[271 - 82 + 81 + rbx]
+; __asm mov dword ptr [rbx + lVar + 828], ebx
+; __asm mov 5 + 8 + 13 + 21[lVar + rbx], eax
+; lVar = 2;
+; }
+
+ at gVar = global i32 0, align 4
+
+; Function Attrs: noinline nounwind optnone uwtable
+define void @t1() #0 {
+; CHECK-LABEL: t1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: .cfi_offset %rbp, -16
+; CHECK-NEXT: movq %rsp, %rbp
+; CHECK-NEXT: .cfi_def_cfa_register %rbp
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_offset %rbx, -24
+; CHECK-NEXT: movq gVar at GOTPCREL(%rip), %rcx
+; CHECK-NEXT: #APP
+; CHECK-EMPTY:
+; CHECK-NEXT: addl (%rcx,%rax), %eax
+; CHECK-NEXT: addl %eax, (%rcx,%rax)
+; CHECK-NEXT: addl 270(%rcx,%rbx), %ebx
+; CHECK-NEXT: addl %ebx, 828(%rcx,%rbx)
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: movq gVar at GOTPCREL(%rip), %rax
+; CHECK-NEXT: movl $3, (%rax)
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa %rsp, 8
+; CHECK-NEXT: retq
+entry:
+ call void asm sideeffect inteldialect "add eax, dword ptr $2[rax]\0A\09add dword ptr $0[rax], eax\0A\09add ebx, dword ptr $3[rbx + $$270]\0A\09add dword ptr $1[rbx + $$828], ebx", "=*m,=*m,*m,*m,~{eax},~{ebx},~{flags},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar) #1
+ store i32 3, i32* @gVar, align 4
+ ret void
+}
+
+; Function Attrs: noinline nounwind optnone uwtable
+define void @t2() #0 {
+; CHECK-LABEL: t2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: .cfi_offset %rbp, -16
+; CHECK-NEXT: movq %rsp, %rbp
+; CHECK-NEXT: .cfi_def_cfa_register %rbp
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_offset %rbx, -24
+; CHECK-NEXT: #APP
+; CHECK-EMPTY:
+; CHECK-NEXT: movl -12(%rbp,%rax), %eax
+; CHECK-NEXT: movl %eax, -12(%rbp,%rax)
+; CHECK-NEXT: movl 258(%rbp,%rbx), %ebx
+; CHECK-NEXT: movl %ebx, 816(%rbp,%rbx)
+; CHECK-NEXT: movl %eax, 35(%rbp,%rbx)
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: movl $2, -12(%rbp)
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa %rsp, 8
+; CHECK-NEXT: retq
+entry:
+ %lVar = alloca i32, align 4
+ call void asm sideeffect inteldialect "mov eax, dword ptr $3[rax]\0A\09mov dword ptr $0[rax], eax\0A\09mov ebx, dword ptr $4[rbx + $$270]\0A\09mov dword ptr $1[rbx + $$828], ebx\0A\09mov $2[rbx + $$47], eax", "=*m,=*m,=*m,*m,*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar) #1
+ store i32 2, i32* %lVar, align 4
+ ret void
+}
+
+attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { nounwind }
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
diff --git a/llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-2-regs.ll b/llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-2-regs.ll
new file mode 100644
index 0000000000000..bf6f2e18330fb
--- /dev/null
+++ b/llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-2-regs.ll
@@ -0,0 +1,31 @@
+; RUN: not llc -mtriple=x86_64-unknown-unknown -relocation-model=pic %s -o /dev/null 2>&1 | FileCheck %s
+
+; Tests come from "clang/test/CodeGen/ms-inline-asm-variables.c"
+;
+; int gVar;
+; void t1() {
+; __asm add ecx, dword ptr gVar[4590 + rax + rcx*4]
+; __asm add dword ptr [gVar + rax + 45 + 23 - 53 + 60 - 2 + rcx*8], ecx
+; __asm add 1 + 1 + 2 + 3[gVar + rcx + rbx], eax
+; gVar = 3;
+; }
+
+ at gVar = global i32 0, align 4
+
+; Function Attrs: noinline nounwind optnone uwtable
+define void @t1() #0 {
+; CHECK: error: Don't use 2 or more regs for mem offset in PIC model
+; CHECK: error: Don't use 2 or more regs for mem offset in PIC model
+; CHECK: error: Don't use 2 or more regs for mem offset in PIC model
+entry:
+ call void asm sideeffect inteldialect "add ecx, dword ptr ${2:P}[rax + rcx * $$4 + $$4590]\0A\09add dword ptr ${0:P}[rcx + rcx * $$8 + $$73], ecx\0A\09add ${1:P}[rcx + rbx + $$7], eax", "=*m,=*m,*m,~{ecx},~{flags},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar)
+ store i32 3, i32* @gVar, align 4
+ ret void
+}
+
+attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { nounwind }
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
diff --git a/llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-nopic.ll b/llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-nopic.ll
new file mode 100644
index 0000000000000..722245ee195e4
--- /dev/null
+++ b/llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-nopic.ll
@@ -0,0 +1,104 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64-unknown-unknown %s -o - | FileCheck %s
+
+; Tests similar with "clang/test/CodeGen/ms-inline-asm-variables.c"
+; // clang -fasm-blocks -target x86_64-unknown-unknown -S
+
+; int gVar;
+; void t1() {
+; __asm add eax, dword ptr gVar[rax]
+; __asm add dword ptr [rax+gVar], eax
+; __asm add ebx, dword ptr gVar[271 - 82 + 81 + rbx]
+; __asm add dword ptr [rbx + gVar + 828], ebx
+; __asm add ecx, dword ptr gVar[4590 + rcx + rcx*4]
+; __asm add dword ptr [gVar + rcx + 45 + 23 - 53 + 60 - 2 + rcx*8], ecx
+; __asm add 1 + 1 + 2 + 3[gVar + rcx + rbx], eax
+;
+; gVar += 2;
+; }
+;
+; void t2(void) {
+; int lVar;
+; __asm mov eax, dword ptr lVar[rax]
+; __asm mov dword ptr [rax+lVar], eax
+; __asm mov ebx, dword ptr lVar[271 - 82 + 81 + rbx]
+; __asm mov dword ptr [rbx + lVar + 828], ebx
+; __asm mov 5 + 8 + 13 + 21[lVar + rbx], eax
+; }
+
+ at gVar = dso_local global i32 0, align 4
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local void @t1() #0 {
+; CHECK-LABEL: t1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: .cfi_offset %rbp, -16
+; CHECK-NEXT: movq %rsp, %rbp
+; CHECK-NEXT: .cfi_def_cfa_register %rbp
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_offset %rbx, -24
+; CHECK-NEXT: #APP
+; CHECK-EMPTY:
+; CHECK-NEXT: addl gVar(,%rax), %eax
+; CHECK-NEXT: addl %eax, gVar(,%rax)
+; CHECK-NEXT: addl gVar+270(,%rbx), %ebx
+; CHECK-NEXT: addl %ebx, gVar+828(,%rbx)
+; CHECK-NEXT: addl gVar+4590(%rcx,%rcx,4), %ecx
+; CHECK-NEXT: addl %ecx, gVar+73(%rcx,%rcx,8)
+; CHECK-NEXT: addl %eax, gVar+7(%rcx,%rbx)
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: movl gVar, %eax
+; CHECK-NEXT: addl $2, %eax
+; CHECK-NEXT: movl %eax, gVar
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa %rsp, 8
+; CHECK-NEXT: retq
+entry:
+ call void asm sideeffect inteldialect "add eax, dword ptr $4[rax]\0A\09add dword ptr $0[rax], eax\0A\09add ebx, dword ptr $5[rbx + $$270]\0A\09add dword ptr $1[rbx + $$828], ebx\0A\09add ecx, dword ptr ${6:P}[rcx + rcx * $$4 + $$4590]\0A\09add dword ptr ${2:P}[rcx + rcx * $$8 + $$73], ecx\0A\09add ${3:P}[rcx + rbx + $$7], eax", "=*m,=*m,=*m,=*m,*m,*m,*m,~{eax},~{ebx},~{ecx},~{flags},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar) #1
+ %0 = load i32, i32* @gVar, align 4
+ %add = add nsw i32 %0, 2
+ store i32 %add, i32* @gVar, align 4
+ ret void
+}
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local void @t2() #0 {
+; CHECK-LABEL: t2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: .cfi_offset %rbp, -16
+; CHECK-NEXT: movq %rsp, %rbp
+; CHECK-NEXT: .cfi_def_cfa_register %rbp
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_offset %rbx, -24
+; CHECK-NEXT: #APP
+; CHECK-EMPTY:
+; CHECK-NEXT: movl -12(%rbp,%rax), %eax
+; CHECK-NEXT: movl %eax, -12(%rbp,%rax)
+; CHECK-NEXT: movl 258(%rbp,%rbx), %ebx
+; CHECK-NEXT: movl %ebx, 816(%rbp,%rbx)
+; CHECK-NEXT: movl %eax, 35(%rbp,%rbx)
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa %rsp, 8
+; CHECK-NEXT: retq
+entry:
+ %lVar = alloca i32, align 4
+ call void asm sideeffect inteldialect "mov eax, dword ptr $3[rax]\0A\09mov dword ptr $0[rax], eax\0A\09mov ebx, dword ptr $4[rbx + $$270]\0A\09mov dword ptr $1[rbx + $$828], ebx\0A\09mov $2[rbx + $$47], eax", "=*m,=*m,=*m,*m,*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar) #1
+ ret void
+}
+
+attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"uwtable", i32 2}
diff --git a/llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-1-reg.ll b/llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-1-reg.ll
new file mode 100644
index 0000000000000..a39e9fc71a9c9
--- /dev/null
+++ b/llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-1-reg.ll
@@ -0,0 +1,153 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=i386-unknown-unknown %s -o - | FileCheck --check-prefix=X86 %s
+; RUN: llc -mtriple=i386-unknown-unknown -relocation-model=pic %s -o -| FileCheck --check-prefix=X86PIC %s
+
+; Tests come from clang/test/CodeGen/ms-inline-asm-variables.c
+;
+; int gVar;
+; void t1() {
+; __asm add eax, dword ptr gVar[eax]
+; __asm add dword ptr [eax+gVar], eax
+; __asm add ebx, dword ptr gVar[271 - 82 + 81 + ebx]
+; __asm add dword ptr [ebx + gVar + 828], ebx
+; gVar = 3;
+; }
+;
+; void t2(void) {
+; int lVar;
+; __asm mov eax, dword ptr lVar[eax]
+; __asm mov dword ptr [eax+lVar], eax
+; __asm mov ebx, dword ptr lVar[271 - 82 + 81 + ebx]
+; __asm mov dword ptr [ebx + lVar + 828], ebx
+; __asm mov 5 + 8 + 13 + 21[lVar + ebx], eax
+; lVar = 2;
+; }
+
+ at gVar = global i32 0, align 4
+
+; Function Attrs: noinline nounwind optnone uwtable
+define void @t1() #0 {
+; X86-LABEL: t1:
+; X86: # %bb.0: # %entry
+; X86-NEXT: pushl %ebp
+; X86-NEXT: .cfi_def_cfa_offset 8
+; X86-NEXT: .cfi_offset %ebp, -8
+; X86-NEXT: movl %esp, %ebp
+; X86-NEXT: .cfi_def_cfa_register %ebp
+; X86-NEXT: pushl %ebx
+; X86-NEXT: .cfi_offset %ebx, -12
+; X86-NEXT: #APP
+; X86-EMPTY:
+; X86-NEXT: addl gVar(%eax), %eax
+; X86-NEXT: addl %eax, gVar(%eax)
+; X86-NEXT: addl gVar+270(%ebx), %ebx
+; X86-NEXT: addl %ebx, gVar+828(%ebx)
+; X86-EMPTY:
+; X86-NEXT: #NO_APP
+; X86-NEXT: movl $3, gVar
+; X86-NEXT: popl %ebx
+; X86-NEXT: popl %ebp
+; X86-NEXT: .cfi_def_cfa %esp, 4
+; X86-NEXT: retl
+;
+; X86PIC-LABEL: t1:
+; X86PIC: # %bb.0: # %entry
+; X86PIC-NEXT: pushl %ebp
+; X86PIC-NEXT: .cfi_def_cfa_offset 8
+; X86PIC-NEXT: .cfi_offset %ebp, -8
+; X86PIC-NEXT: movl %esp, %ebp
+; X86PIC-NEXT: .cfi_def_cfa_register %ebp
+; X86PIC-NEXT: pushl %ebx
+; X86PIC-NEXT: .cfi_offset %ebx, -12
+; X86PIC-NEXT: calll .L0$pb
+; X86PIC-NEXT: .L0$pb:
+; X86PIC-NEXT: popl %ecx
+; X86PIC-NEXT: .Ltmp0:
+; X86PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp0-.L0$pb), %ecx
+; X86PIC-NEXT: movl gVar at GOT(%ecx), %edx
+; X86PIC-NEXT: #APP
+; X86PIC-EMPTY:
+; X86PIC-NEXT: addl (%edx,%eax), %eax
+; X86PIC-NEXT: addl %eax, (%edx,%eax)
+; X86PIC-NEXT: addl 270(%edx,%ebx), %ebx
+; X86PIC-NEXT: addl %ebx, 828(%edx,%ebx)
+; X86PIC-EMPTY:
+; X86PIC-NEXT: #NO_APP
+; X86PIC-NEXT: movl gVar at GOT(%ecx), %eax
+; X86PIC-NEXT: movl $3, (%eax)
+; X86PIC-NEXT: popl %ebx
+; X86PIC-NEXT: popl %ebp
+; X86PIC-NEXT: .cfi_def_cfa %esp, 4
+; X86PIC-NEXT: retl
+entry:
+ call void asm sideeffect inteldialect "add eax, dword ptr $2[eax]\0A\09add dword ptr $0[eax], eax\0A\09add ebx, dword ptr $3[ebx + $$270]\0A\09add dword ptr $1[ebx + $$828], ebx", "=*m,=*m,*m,*m,~{eax},~{ebx},~{flags},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar)
+ store i32 3, i32* @gVar, align 4
+ ret void
+}
+
+; Function Attrs: noinline nounwind optnone uwtable
+define void @t2() #0 {
+; X86-LABEL: t2:
+; X86: # %bb.0: # %entry
+; X86-NEXT: pushl %ebp
+; X86-NEXT: .cfi_def_cfa_offset 8
+; X86-NEXT: .cfi_offset %ebp, -8
+; X86-NEXT: movl %esp, %ebp
+; X86-NEXT: .cfi_def_cfa_register %ebp
+; X86-NEXT: pushl %ebx
+; X86-NEXT: pushl %eax
+; X86-NEXT: .cfi_offset %ebx, -12
+; X86-NEXT: #APP
+; X86-EMPTY:
+; X86-NEXT: movl -8(%ebp,%eax), %eax
+; X86-NEXT: movl %eax, -8(%ebp,%eax)
+; X86-NEXT: movl 262(%ebp,%ebx), %ebx
+; X86-NEXT: movl %ebx, 820(%ebp,%ebx)
+; X86-NEXT: movl %eax, 39(%ebp,%ebx)
+; X86-EMPTY:
+; X86-NEXT: #NO_APP
+; X86-NEXT: movl $2, -8(%ebp)
+; X86-NEXT: addl $4, %esp
+; X86-NEXT: popl %ebx
+; X86-NEXT: popl %ebp
+; X86-NEXT: .cfi_def_cfa %esp, 4
+; X86-NEXT: retl
+;
+; X86PIC-LABEL: t2:
+; X86PIC: # %bb.0: # %entry
+; X86PIC-NEXT: pushl %ebp
+; X86PIC-NEXT: .cfi_def_cfa_offset 8
+; X86PIC-NEXT: .cfi_offset %ebp, -8
+; X86PIC-NEXT: movl %esp, %ebp
+; X86PIC-NEXT: .cfi_def_cfa_register %ebp
+; X86PIC-NEXT: pushl %ebx
+; X86PIC-NEXT: pushl %eax
+; X86PIC-NEXT: .cfi_offset %ebx, -12
+; X86PIC-NEXT: #APP
+; X86PIC-EMPTY:
+; X86PIC-NEXT: movl -8(%ebp,%eax), %eax
+; X86PIC-NEXT: movl %eax, -8(%ebp,%eax)
+; X86PIC-NEXT: movl 262(%ebp,%ebx), %ebx
+; X86PIC-NEXT: movl %ebx, 820(%ebp,%ebx)
+; X86PIC-NEXT: movl %eax, 39(%ebp,%ebx)
+; X86PIC-EMPTY:
+; X86PIC-NEXT: #NO_APP
+; X86PIC-NEXT: movl $2, -8(%ebp)
+; X86PIC-NEXT: addl $4, %esp
+; X86PIC-NEXT: popl %ebx
+; X86PIC-NEXT: popl %ebp
+; X86PIC-NEXT: .cfi_def_cfa %esp, 4
+; X86PIC-NEXT: retl
+entry:
+ %lVar = alloca i32, align 4
+ call void asm sideeffect inteldialect "mov eax, dword ptr $3[eax]\0A\09mov dword ptr $0[eax], eax\0A\09mov ebx, dword ptr $4[ebx + $$270]\0A\09mov dword ptr $1[ebx + $$828], ebx\0A\09mov $2[ebx + $$47], eax", "=*m,=*m,=*m,*m,*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar)
+ store i32 2, i32* %lVar, align 4
+ ret void
+}
+
+attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { nounwind }
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"NumRegisterParameters", i32 0}
diff --git a/llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-2-regs.ll b/llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-2-regs.ll
new file mode 100644
index 0000000000000..fa10277750e05
--- /dev/null
+++ b/llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-2-regs.ll
@@ -0,0 +1,54 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=i386-unknown-unknown %s -o - | FileCheck --check-prefix=X86 %s
+; RUN: not llc -mtriple=i386-unknown-unknown -relocation-model=pic %s -o /dev/null 2>&1 | FileCheck --check-prefix=X86PIC %s
+
+; Tests come from "clang/test/CodeGen/ms-inline-asm-variables.c"
+;
+; int gVar;
+; void t1() {
+; __asm add ecx, dword ptr gVar[4590 + eax + ecx*4]
+; __asm add dword ptr [gVar + eax + 45 + 23 - 53 + 60 - 2 + ecx*8], ecx
+; __asm add 1 + 1 + 2 + 3[gVar + ecx + ebx], eax
+;
+; gVar = 3;
+; }
+
+ at gVar = global i32 0, align 4
+
+; Function Attrs: noinline nounwind optnone uwtable
+define void @t1() #0 {
+; X86-LABEL: t1:
+; X86: # %bb.0: # %entry
+; X86-NEXT: pushl %ebp
+; X86-NEXT: .cfi_def_cfa_offset 8
+; X86-NEXT: .cfi_offset %ebp, -8
+; X86-NEXT: movl %esp, %ebp
+; X86-NEXT: .cfi_def_cfa_register %ebp
+; X86-NEXT: #APP
+; X86-EMPTY:
+; X86-NEXT: addl gVar+4590(%eax,%ecx,4), %ecx
+; X86-NEXT: addl %ecx, gVar+73(%eax,%ecx,8)
+; X86-NEXT: addl %eax, gVar+7(%ecx,%ebx)
+; X86-EMPTY:
+; X86-NEXT: #NO_APP
+; X86-NEXT: movl $3, gVar
+; X86-NEXT: popl %ebp
+; X86-NEXT: .cfi_def_cfa %esp, 4
+; X86-NEXT: retl
+
+; X86PIC: error: Don't use 2 or more regs for mem offset in PIC model
+; X86PIC: error: Don't use 2 or more regs for mem offset in PIC model
+; X86PIC: error: Don't use 2 or more regs for mem offset in PIC model
+
+entry:
+ call void asm sideeffect inteldialect "add ecx, dword ptr ${2:P}[eax + ecx * $$4 + $$4590]\0A\09add dword ptr ${0:P}[eax + ecx * $$8 + $$73], ecx\0A\09add ${1:P}[ecx + ebx + $$7], eax", "=*m,=*m,*m,~{eax},~{ecx},~{flags},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar) #1
+ store i32 3, i32* @gVar, align 4
+ ret void
+}
+
+attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { nounwind }
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"NumRegisterParameters", i32 0}
More information about the llvm-commits
mailing list