[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