From: Reid Kleckner Date: Tue, 29 Nov 2016 00:29:27 +0000 (+0000) Subject: Recognize ${:uid} escapes in intel syntax inline asm X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bde207a0f269310a941785e1edf61beb7a33eccc;p=llvm Recognize ${:uid} escapes in intel syntax inline asm 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 --- diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 2ce6c182235..20075e41977 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -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; diff --git a/test/CodeGen/X86/ms-inline-asm.ll b/test/CodeGen/X86/ms-inline-asm.ll index 428eb1b7190..ec0630a4ce0 100644 --- a/test/CodeGen/X86/ms-inline-asm.ll +++ b/test/CodeGen/X86/ms-inline-asm.ll @@ -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 {