Cullen Rhodes via llvm-dev
2020-Apr-15  16:43 UTC
[llvm-dev] Using braces in InstAlias asm string
Hi,
I'm adding MC support for a set of instructions containing braces and
I'm
hitting an issue with InstAlias. I've reproduced it with the ldraa
instruction -
the first AArch64 instruction I found in AArch64InstrFormats.td that uses
InstAlias.
The instruction takes a dst register, base address and optional offset.  An
alias is used to implement no offset form:
    multiclass AuthLoad<bit M, string asm, Operand opr> {
      def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
                                   (ins GPR64sp:$Rn, opr:$offset),
                                   asm, "\t$Rt, [$Rn, $offset]",
"", opr>;
      def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
                                   (ins GPR64sp:$Rn, opr:$offset),
                                   asm, "\t$Rt, [$Rn, $offset]!",
                                   "$Rn = $wback, at earlyclobber
$wback", opr>;
      def : InstAlias<asm # "\t$Rt, [$Rn]",
                      (!cast<Instruction>(NAME # "indexed")
GPR64:$Rt, GPR64sp:$Rn, 0)>;   <-- HERE
      def : InstAlias<asm # "\t$Rt, [$wback]!",
                      (!cast<Instruction>(NAME # "writeback")
GPR64sp:$wback, GPR64:$Rt, 0), 0>;
    }
Example usage:
    $ echo "[0x20,0x04,0x20,0xf8]" | ./bin/llvm-mc -triple=aarch64
-show-encoding -mattr=+v8.3a -disassemble
            .text
            ldraa   x0, [x1]                // encoding: [0x20,0x04,0x20,0xf8]
To recreate the issue I tried adding braces around the dst reg and base
address, e.g.
    ldraa   {x0, [x1]}
The first thing I tried was double braces "{{}}" which seems to work
for the asm
string in an instruction definition, e.g.
    diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    index 6b23c7c..62bf67d 100644
    --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    @@ -1632,7 +1632,7 @@ class BaseAuthLoad<bit M, bit W, dag oops, dag
iops, string asm,
     multiclass AuthLoad<bit M, string asm, Operand opr> {
       def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
                                    (ins GPR64sp:$Rn, opr:$offset),
    -                               asm, "\t$Rt, [$Rn, $offset]",
"", opr>;
    +                               asm, "\t{{$Rt, [$Rn, $offset]}}",
"", opr>;
       def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
                                    (ins GPR64sp:$Rn, opr:$offset),
                                    asm, "\t$Rt, [$Rn, $offset]!",
but doesn't work when defining an InstAlias, e.g.
    diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    index 6b23c7c..44fb9a3 100644
    --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    @@ -1638,7 +1638,7 @@ multiclass AuthLoad<bit M, string asm, Operand
opr> {
                                    asm, "\t$Rt, [$Rn, $offset]!",
                                    "$Rn = $wback, at earlyclobber
$wback", opr>;
    -  def : InstAlias<asm # "\t$Rt, [$Rn]",
    +  def : InstAlias<asm # "\t{{$Rt, [$Rn]}}",
                       (!cast<Instruction>(NAME # "indexed")
GPR64:$Rt, GPR64sp:$Rn, 0)>;
where I'm see the following error from TableGen:
    [17/124] Building AArch64GenAsmMatcher.inc...
    FAILED: cd ./llvm-project/build &&
./llvm-project/build/bin/llvm-tblgen -gen-asm-matcher -I
./llvm-project/llvm/lib/Target/AArch64 -I /usr/include/libxml2 -I
./llvm-project/build/include -I ./llvm-project/llvm/include -I
./llvm-project/llvm/lib/Target ./llvm-project/llvm/lib/Target/AArch64/AArch64.td
--write-if-changed -o lib/Target/AArch64/AArch64GenAsmMatcher.inc -d
lib/Target/AArch64/AArch64GenAsmMatcher.inc.d
    Included from ./llvm-project/llvm/lib/Target/AArch64/AArch64.td:431:
    Included from
./llvm-project/llvm/lib/Target/AArch64/AArch64InstrInfo.td:588:
    ./llvm-project/llvm/lib/Target/AArch64/AArch64InstrFormats.td:1641:3: error:
Instruction 'anonymous_2396' has operand 'Rt' that doesn't
appear in asm string!
      def : InstAlias<asm # "\t{{$Rt, [$Rn]}}",
      ^
    Included from ./llvm-project/llvm/lib/Target/AArch64/AArch64.td:431:
    ./llvm-project/llvm/lib/Target/AArch64/AArch64InstrInfo.td:932:17: note:
instantiated from multiclass
      defm LDRAA  : AuthLoad<0, "ldraa", simm10Scaled>;
                    ^
    [17/71] Building AArch64GenDAGISel.inc...
    ninja: build stopped: subcommand failed.
which led me to think it's trying to do some form of substitution for
braces, so
I tried the following hack using an OR where both sides are the same in the asm
string:
    diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    index 6b23c7c..97ed49e 100644
    --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    @@ -1638,7 +1638,7 @@ multiclass AuthLoad<bit M, string asm, Operand
opr> {
                                    asm, "\t$Rt, [$Rn, $offset]!",
                                    "$Rn = $wback, at earlyclobber
$wback", opr>;
    -  def : InstAlias<asm # "\t$Rt, [$Rn]",
    +  def : InstAlias<asm # "\t{{$Rt, [$Rn]}|{$Rt, [$Rn]}}",
                       (!cast<Instruction>(NAME # "indexed")
GPR64:$Rt, GPR64sp:$Rn, 0)>;
       def : InstAlias<asm # "\t$Rt, [$wback]!",
Which seems to work fine.
Example usage:
    $ echo "[0x20,0x04,0x20,0xf8]" | ./bin/llvm-mc -triple=aarch64
-show-encoding -mattr=+v8.3a -disassemble
            .text
            ldraa   {x0, [x1]}              // encoding: [0x20,0x04,0x20,0xf8]
FWIW I also tried double escaping, e.g.
    diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    index 6b23c7c..1d74aaf 100644
    --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
    @@ -1638,7 +1638,7 @@ multiclass AuthLoad<bit M, string asm, Operand
opr> {
                                    asm, "\t$Rt, [$Rn, $offset]!",
                                    "$Rn = $wback, at earlyclobber
$wback", opr>;
    -  def : InstAlias<asm # "\t$Rt, [$Rn]",
    +  def : InstAlias<asm # "\t\\{$Rt, [$Rn]\\}",
                       (!cast<Instruction>(NAME # "indexed")
GPR64:$Rt, GPR64sp:$Rn, 0)>;
Which actually worked on LLVM 9 but warnings are emitted:
    [20/70] Building CXX object
lib/Target/AArch64/MCTargetDesc/CMakeFiles/LLVMAArch64Desc.dir/AArch64InstPrinter.cpp.o
    In file included from
./llvm-project/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp:39:
    lib/Target/AArch64/AArch64GenAsmWriter.inc:23094:23: warning: use of
non-standard escape character '\{' [-Wpedantic]
        /* 7811 */ "ldraa   \{$\x01, [$\x02]\}\0"
                            ^~
On upstream master I also hit a bunch of the following asserts, just to clarify
addv is unrelated and I made no changes there. This is just an example from one
of the many failures:
    ********************
    FAIL: LLVM :: CodeGen/AArch64/aarch64-addv.ll (6528 of 36856)
    ******************** TEST 'LLVM :: CodeGen/AArch64/aarch64-addv.ll'
FAILED ********************
    Script:
    --
    : 'RUN: at line 1';   ./llvm-project/build/bin/llc <
./llvm-project/llvm/test/CodeGen/AArch64/aarch64-addv.ll -mtriple=aarch64-eabi
-aarch64-neon-syntax=generic | ./llvm-project/build/bin/FileCheck
./llvm-project/llvm/test/CodeGen/AArch64/aarch64-addv.ll
    --
    Exit Code: 2
    Command Output (stderr):
    --
    llc: ./llvm-project/llvm/lib/MC/MCInstPrinter.cpp:168: const char
*llvm::MCInstPrinter::matchAliasPatterns(const llvm::MCInst *, const
llvm::MCSubtargetInfo *, const llvm::AliasMatchingData &): Assertion
`AsmStrOffset < M.AsmStrings.size() && (AsmStrOffset == 0 ||
M.AsmStrings[AsmStrOffset - 1] == '\0') && "bad asm string
offset"' failed.
    PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash
backtrace.
    Stack dump:
    0.      Program arguments: ./llvm-project/build/bin/llc
-mtriple=aarch64-eabi -aarch64-neon-syntax=generic
    1.      Running pass 'Function Pass Manager' on module
'<stdin>'.
    2.      Running pass 'AArch64 Assembly Printer' on function
'@add_B'
     #0 0x00007f2bc94d2167 llvm::sys::PrintStackTrace(llvm::raw_ostream&)
./llvm-project/llvm/lib/Support/Unix/Signals.inc:564:11
     #1 0x00007f2bc94d2309 PrintStackTraceSignalHandler(void*)
./llvm-project/llvm/lib/Support/Unix/Signals.inc:625:1
     #2 0x00007f2bc94d0b1b llvm::sys::RunSignalHandlers()
./llvm-project/llvm/lib/Support/Signals.cpp:67:5
     #3 0x00007f2bc94d2a55 SignalHandler(int)
./llvm-project/llvm/lib/Support/Unix/Signals.inc:406:1
     #4 0x00007f2bc8695390 __restore_rt
(/lib/x86_64-linux-gnu/libpthread.so.0+0x11390)
     #5 0x00007f2bc79eb428 raise
/build/glibc-LK5gWL/glibc-2.23/signal/../sysdeps/unix/sysv/linux/raise.c:54:0
     #6 0x00007f2bc79ed02a abort
/build/glibc-LK5gWL/glibc-2.23/stdlib/abort.c:91:0
     #7 0x00007f2bc79e3bd7 __assert_fail_base
/build/glibc-LK5gWL/glibc-2.23/assert/assert.c:92:0
     #8 0x00007f2bc79e3c82 (/lib/x86_64-linux-gnu/libc.so.6+0x2dc82)
     #9 0x00007f2bca6a1a2b llvm::MCInstPrinter::matchAliasPatterns(llvm::MCInst
const*, llvm::MCSubtargetInfo const*, llvm::AliasMatchingData const&)
./llvm-project/llvm/lib/MC/MCInstPrinter.cpp:169:10
    #10 0x00007f2bcd11b1be
llvm::AArch64InstPrinter::printAliasInstr(llvm::MCInst const*, unsigned long,
llvm::MCSubtargetInfo const&, llvm::raw_ostream&)
./llvm-project/build/lib/Target/AArch64/AArch64GenAsmWriter.inc:23456:15
    #11 0x00007f2bcd12373c llvm::AArch64InstPrinter::printInst(llvm::MCInst
const*, unsigned long, llvm::StringRef, llvm::MCSubtargetInfo const&,
llvm::raw_ostream&)
./llvm-project/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp:298:7
    #12 0x00007f2bca6c542f
llvm::MCTargetStreamer::prettyPrintAsm(llvm::MCInstPrinter&, unsigned long,
llvm::MCInst const&, llvm::MCSubtargetInfo const&,
llvm::raw_ostream&) ./llvm-project/llvm/lib/MC/MCStreamer.cpp:979:1
    #13 0x00007f2bca63d6b7 (anonymous
namespace)::MCAsmStreamer::emitInstruction(llvm::MCInst const&,
llvm::MCSubtargetInfo const&)
./llvm-project/llvm/lib/MC/MCAsmStreamer.cpp:1972:5
    #14 0x00007f2bcbf60c8c
llvm::AsmPrinter::EmitToStreamer(llvm::MCStreamer&, llvm::MCInst const&)
./llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp:235:1
    #15 0x00007f2bcdc9d3e2 (anonymous
namespace)::AArch64AsmPrinter::emitInstruction(llvm::MachineInstr const*)
./llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp:1317:1
    #16 0x00007f2bcbf65689 llvm::AsmPrinter::emitFunctionBody()
./llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp:1176:25
    #17 0x00007f2bcdc9af09 (anonymous
namespace)::AArch64AsmPrinter::runOnMachineFunction(llvm::MachineFunction&)
./llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp:142:5
    #18 0x00007f2bcb96bd17
llvm::MachineFunctionPass::runOnFunction(llvm::Function&)
./llvm-project/llvm/lib/CodeGen/MachineFunctionPass.cpp:73:8
    #19 0x00007f2bcae2750c
llvm::FPPassManager::runOnFunction(llvm::Function&)
./llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1482:23
    #20 0x00007f2bcae27935 llvm::FPPassManager::runOnModule(llvm::Module&)
./llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1518:16
    #21 0x00007f2bcae28094 (anonymous
namespace)::MPPassManager::runOnModule(llvm::Module&)
./llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1583:23
    #22 0x00007f2bcae27bd8 llvm::legacy::PassManagerImpl::run(llvm::Module&)
./llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1695:16
    #23 0x00007f2bcae28631 llvm::legacy::PassManager::run(llvm::Module&)
./llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1726:3
    #24 0x000000000022237f compileModule(char**, llvm::LLVMContext&)
./llvm-project/llvm/tools/llc/llc.cpp:627:41
    #25 0x00000000002208df main ./llvm-project/llvm/tools/llc/llc.cpp:360:13
    #26 0x00007f2bc79d6830 __libc_start_main
/build/glibc-LK5gWL/glibc-2.23/csu/../csu/libc-start.c:325:0
    #27 0x0000000000220029 _start (./llvm-project/build/bin/llc+0x220029)
    FileCheck error: '<stdin>' is empty.
    FileCheck command line:  ./llvm-project/build/bin/FileCheck
./llvm-project/llvm/test/CodeGen/AArch64/aarch64-addv.ll
    --
I'm wondering if there is a better way to do this than the hack I came up
with
or if this is a gap in InstAlias/TableGen?
Any ideas or thoughts would greatly appreciated.
Thanks,
Cullen
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20200415/d178feaf/attachment-0001.html>