diff --git a/llvm/test/TableGen/AliasAsmString.td b/llvm/test/TableGen/AliasAsmString.td new file mode 100644 --- /dev/null +++ b/llvm/test/TableGen/AliasAsmString.td @@ -0,0 +1,28 @@ +// RUN: llvm-tblgen -gen-asm-writer -I %p/../../include %s | FileCheck %s + +include "llvm/Target/Target.td" + +def ArchInstrInfo : InstrInfo { } + +def Arch : Target { + let InstructionSet = ArchInstrInfo; +} + +def Reg : Register<"reg">; + +def RegClass : RegisterClass<"foo", [i32], 0, (add Reg)>; + +def IntOperand: Operand; + +def foo : Instruction { + let Size = 2; + let OutOperandList = (outs); + let InOperandList = (ins IntOperand:$imm); + let AsmString = "foo $imm"; + let Namespace = "Arch"; +} + +def FooBraces : InstAlias<"foo \\{$imm\\}", (foo IntOperand:$imm)>; + +// CHECK: static const char AsmStrings[] = +// CHECK-NEXT: /* 0 */ "foo {$\x01}\0" diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp --- a/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -267,6 +267,27 @@ } } +/// UnescapeAliasString - Supports literal braces in InstAlias asm string which +/// are escaped with '\\' to avoid being interpreted as variants. Braces must +/// be unescaped before c++ code is generated as (e.g.): +/// +/// AsmString = "foo \{$\x01\}"; +/// +/// causes non-standard escape character warnings. +static void UnescapeAliasString(std::string &Str) { + for (unsigned i = 0; i != Str.size(); ++i) { + if (Str[i] == '\\' && i != Str.size()-1) { + switch (Str[i+1]) { + default: continue; // Don't execute the code after the switch. + case '{': Str[i] = '{'; break; + case '}': Str[i] = '}'; break; + } + // Nuke the second character. + Str.erase(Str.begin()+i+1); + } + } +} + /// EmitPrintInstruction - Generate the code for the "printInstruction" method /// implementation. Destroys all instances of AsmWriterInst information, by /// clearing the Instructions vector. @@ -803,6 +824,7 @@ std::string FlatAliasAsmString = CodeGenInstruction::FlattenAsmStringVariants(CGA.AsmString, Variant); + UnescapeAliasString(FlatAliasAsmString); // Don't emit the alias if it has more operands than what it's aliasing. if (NumResultOps < CountNumOperands(FlatAliasAsmString, Variant))