diff --git a/gen/asm-gcc.cpp b/gen/asm-gcc.cpp index 934cbac71a..9df3c55c2e 100644 --- a/gen/asm-gcc.cpp +++ b/gen/asm-gcc.cpp @@ -36,7 +36,10 @@ std::string translateTemplate(GccAsmStatement *stmt) { result += "$$"; // escape for LLVM: $ => $$ break; case '%': - if (i < N - 1 && insn[i + 1] == '%') { // unescape for LLVM: %% => % + if (i < N - 1 && insn[i + 1] == '=') { // unique ID: %= => ${:uid} + result += "${:uid}"; + ++i; + } else if (i < N - 1 && insn[i + 1] == '%') { // unescape for LLVM: %% => % result += '%'; ++i; } else { diff --git a/tests/codegen/asm_gcc_unique_id.d b/tests/codegen/asm_gcc_unique_id.d new file mode 100644 index 0000000000..a972914a4d --- /dev/null +++ b/tests/codegen/asm_gcc_unique_id.d @@ -0,0 +1,35 @@ +// Tests that GCC-style asm %= (unique ID) is correctly translated to LLVM ${:uid} +// which generates unique labels for each asm statement. +// See: https://github.com/ldc-developers/ldc/issues/4294 + +// REQUIRES: target_X86 + +// RUN: %ldc -mtriple=x86_64-linux-gnu -output-s -of=%t.s %s +// RUN: FileCheck %s < %t.s + +// Two functions with identical asm that use %= should get different label numbers. +// The ${:uid} mechanism in LLVM generates sequential numbers (0, 1, 2, ...). + +int func1() { + int result; + // CHECK-LABEL: func1 + // CHECK: loop_[[ID1:[0-9]+]]: + // CHECK: jmp loop_[[ID1]] + asm { + "xorl %0, %0\n\tloop_%=:\n\tincl %0\n\tjmp loop_%=" + : "=r" (result); + } + return result; +} + +int func2() { + int result; + // CHECK-LABEL: func2 + // CHECK: loop_[[ID2:[0-9]+]]: + // CHECK: jmp loop_[[ID2]] + asm { + "xorl %0, %0\n\tloop_%=:\n\tincl %0\n\tjmp loop_%=" + : "=r" (result); + } + return result; +}