]> granicus.if.org Git - llvm/commitdiff
Recognize ${:uid} escapes in intel syntax inline asm
authorReid Kleckner <rnk@google.com>
Tue, 29 Nov 2016 00:29:27 +0000 (00:29 +0000)
committerReid Kleckner <rnk@google.com>
Tue, 29 Nov 2016 00:29:27 +0000 (00:29 +0000)
It looks like this logic was duplicated long ago and the GCC side of
things has grown additional functionality. We need ${:uid} at least to
generate unique MS inline asm labels (PR23715), so expose these.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288092 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
test/CodeGen/X86/ms-inline-asm.ll

index 2ce6c182235fef3f1441992ab3a3f5869e0957bb..20075e41977fb7028a0d9b1c80e4f90a7ff5bb3e 100644 (file)
@@ -193,6 +193,23 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
       }
       if (Done) break;
 
+      // If we have ${:foo}, then this is not a real operand reference, it is a
+      // "magic" string reference, just like in .td files.  Arrange to call
+      // PrintSpecial.
+      if (LastEmitted[0] == '{' && LastEmitted[1] == ':') {
+        LastEmitted += 2;
+        const char *StrStart = LastEmitted;
+        const char *StrEnd = strchr(StrStart, '}');
+        if (!StrEnd)
+          report_fatal_error("Unterminated ${:foo} operand in inline asm"
+                             " string: '" + Twine(AsmStr) + "'");
+
+        std::string Val(StrStart, StrEnd);
+        AP->PrintSpecial(MI, OS, Val.c_str());
+        LastEmitted = StrEnd+1;
+        break;
+      }
+
       const char *IDStart = LastEmitted;
       const char *IDEnd = IDStart;
       while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd;
index 428eb1b7190b54b5237893437e103c4c4a15c016..ec0630a4ce08a4cdfbb9d970c40562f1d5b2601d 100644 (file)
@@ -126,6 +126,37 @@ entry:
 ; CHECK: ret
 }
 
+; Make sure ${:uid} works. Clang uses it for MS inline asm labels.
+;
+; C source:
+; int uid() {
+;   int r;
+;   __asm {
+;     xor eax, eax
+; wloop:
+;     inc eax
+;     cmp eax, 42
+;     jne wloop
+;     mov r, eax
+;   }
+;   return r;
+; }
+define i32 @uid() {
+entry:
+  %r = alloca i32, align 4
+  %0 = bitcast i32* %r to i8*
+  call void asm sideeffect inteldialect "xor eax, eax\0A\09.L__MSASMLABEL_.${:uid}__wloop:\0A\09inc eax\0A\09cmp eax, $$42\0A\09jne .L__MSASMLABEL_.${:uid}__wloop\0A\09mov dword ptr $0, eax", "=*m,~{eax},~{flags},~{dirflag},~{fpsr},~{flags}"(i32* nonnull %r)
+  %1 = load i32, i32* %r, align 4
+  ret i32 %1
+; CHECK-LABEL: uid:
+; CHECK: {{## InlineAsm Start|#APP}}
+; CHECK: .L__MSASMLABEL_.0__wloop:
+; CHECK: jne .L__MSASMLABEL_.0__wloop
+; CHECK: .att_syntax
+; CHECK: {{## InlineAsm End|#NO_APP}}
+; CHECK: ret
+}
+
 declare hidden void @other_func()
 
 define void @naked() #0 {