[llvm-dev] error: expected memory with 32-bit signed offset

Leslie Zhai via llvm-dev llvm-dev at lists.llvm.org
Fri Sep 28 20:19:59 PDT 2018


Hi Daniel,

Thanks for your teaching!


在 2018年09月28日 23:56, Daniel Sanders 写道:
>
>> On 28 Sep 2018, at 00:09, Leslie Zhai <zhaixiang at loongson.cn> wrote:
>>
>> Hi,
>>
>> I want to encode Loongson ISA initially https://gist.github.com/xiangzhai/8ae6966e2f02a94e180dd16ff1cd60ac
>>
>> gslbx           $2,0($3,$4)
>>
>> It is equivalent to:
>>
>> dadd $1, $3, $4
>>
>> lb $2,0($1)
>>
>> I just use  mem_simmptr  as the default value of  DAGOperand MO , because  MipsMemAsmOperand  use  parseMemOperand  to parse general  MemOffset  and only *one*  AnyRegister , for example:
>>
>> 0($1)
>>
>> But  Comma  isNot  AsmToken::RParen , for example:
>>
>> 0($3,$4)
>>
>> Then llvm-mc thrown such error:
>>
>> test/MC/Mips/loongson3a/valid.s:32:32: error: ')' expected
>>          gslbx           $2,0($3,$4)
>>                                            ^
>> test/MC/Mips/loongson3a/valid.s:32:32: error: unexpected token in argument list
>>          gslbx           $2,0($3,$4)
>>                                            ^
>>
>> So I just changed  MipsAsmParser::parseMemOffset :
> I assume you mean parseMemOperand. parseMemOffset doesn't have the code you're referring to.
Sorry for typo...

>
>>     if (Parser.getTok().isNot(AsmToken::RParen)) {
>> -    Error(Parser.getTok().getLoc(), "')' expected");
>> -    return MatchOperand_ParseFail;
>> +    if (hasLoongson3A()) {
>> +      if (Parser.getTok().isNot(AsmToken::Comma)) {
>> +        Error(Parser.getTok().getLoc(), "',' expected");
>> +    return MatchOperand_ParseFail;
>> +      }
> This is going to break instructions like lw when Loongson3A is enabled because it makes the comma mandatory. You need to accept both 0($3) and 0($3, $4) and handle the difference in what you pass to Operands.push_back(). I expect you'll need to add another operand kind to MipsOperand to handle the 0($3,$4) case.
Thank you for pointing out my fault!  I added  OpStr startswith_lower  
check:

    if (Parser.getTok().isNot(AsmToken::RParen)) {
-    Error(Parser.getTok().getLoc(), "')' expected");
-    return MatchOperand_ParseFail;
+    StringRef OpStr = static_cast<MipsOperand &>(*Operands[0]).getToken();
+    if (hasLoongson3A() && OpStr.startswith_lower(LoongISAPrefix)) {
+      if (Parser.getTok().isNot(AsmToken::Comma)) {
+        Error(Parser.getTok().getLoc(), "',' expected");
+    return MatchOperand_ParseFail;
+      }
+
+      Parser.Lex(); // Eat the ',' token.
+
+      Res = parseAnyRegister(Operands);
+      if (Res != MatchOperand_Success)
+        return Res;
+
+      if (Parser.getTok().isNot(AsmToken::RParen)) {
+        Error(Parser.getTok().getLoc(), "')' expected");
+        return MatchOperand_ParseFail;
+      }
+    } else {
+      Error(Parser.getTok().getLoc(), "')' expected");
+      return MatchOperand_ParseFail;
+    }
    }

Then llvm-mc is able to distinguish invalid instructions:
test/MC/Mips/loongson3a/invalid.s:5:19: error: ')' expected
         lb $2,0($3,$4)
                   ^
test/MC/Mips/loongson3a/invalid.s:5:19: error: unexpected token in 
argument list
         lb $2,0($3,$4)
                   ^


>
>> +
>> +      Parser.Lex(); // Eat the ',' token.
>> +
>> +      Res = parseAnyRegister(Operands);
>> +      if (Res != MatchOperand_Success)
>> +        return Res;
>> +
>> +      if (Parser.getTok().isNot(AsmToken::RParen)) {
>> +        Error(Parser.getTok().getLoc(), "')' expected");
>> +        return MatchOperand_ParseFail;
>> +      }
>> +    } else {
>> +      Error(Parser.getTok().getLoc(), "')' expected");
>> +      return MatchOperand_ParseFail;
>> +    }
>>     }
>>
>> ----- 8< -------- 8< -------- 8< -------- 8< -------- 8< -------- 8< ---
>>
>> But I have no idea how to handle custom  getMemEncoding:
>>
>> test/MC/Mips/loongson3a/valid.s:32:30: error: expected memory with 32-bit signed offset
>>          gslbx           $2,0($3,$4)
>>                                        ^
>>
>> I just copy-n-paste  mem_generic  and  getMemEncoding:
>>
>> def gs_mem : Operand<iPTR> {
>>    let PrintMethod = "printMemOperand";
>>    let MIOperandInfo = (ops ptr_rc, ptr_rc, simm16);
>>
>> ^-- for two registers
>>    let EncoderMethod = "getGSMemEncoding";
>>
>>                                              ^-- just encoding two registers and one offset
> The EncoderMethod isn't used by the assembly parser, it's used later when it's encoding the instruction into the binary. You need to look into the ParserMatchClass instead.
>
> There's two bits of the ParserMatchClass that are important. ParserMethod is the function the parser will call to parse the assembly. You can either keep using parseMemOperand and modify it to accept the 0($3,$4) case or change it and implement a new parser there. You have a distinct mnemonic so both options are available but I should mention that if you have more than one instruction with the same mnemonic then it's best to make sure all of them use the same ParserMethod. This is because the parser might only call one of them and you can't be sure which one (it depends on the order in the generated matcher table and whether there's any ambiguity).
>
> The other bit is Name. This is used to choose which methods on MipsOperand are called to decide if the parsed instruction matches an instruction defined by the compiler. If it's set to 'Mem' then MipsOperand::isMem() determines whether the operand matches, and MipsOperand::addMemOperands() adds the MCInst operands to the MCInst.
I need to handle carefully about replacing *two* registers operands with 
the memory operand:

// Replace the register operand with the memory operand.
   std::unique_ptr<MipsOperand> op(
       static_cast<MipsOperand *>(Operands.back().release()));
   // Remove the register from the operands.
   // "op" will be managed by k_Memory.
Operands.pop_back();
   // Add the memory operand.
   if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
     int64_t Imm;
     if (IdVal->evaluateAsAbsolute(Imm))
       IdVal = MCConstantExpr::create(Imm, getContext());
     else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
       IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), 
BE->getLHS(),
getContext());
}

   Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, 
*this));
----- 8< -------- 8< -------- 8< -------- 8< -------- 8< -------- 8< ---
As you mentioned, I need to add  MipsGSOperand to handle ($3, $4) case.

Thanks,
Leslie Zhai

>
>>    let ParserMatchClass = MipsMemAsmOperand;
>>    let OperandType = "OPERAND_MEMORY";
>> }
>>
>> ----- 8< -------- 8< -------- 8< -------- 8< -------- 8< -------- 8< ---
>>
>> I couldn't fool llvm-mc :)
>>
>> test/MC/Mips/loongson3a/valid.s:32:30: error: invalid operand for instruction
>>          gslbx           $2,0($3,$4)
>>                                        ^
>>
>> Compare with Loongson GCC toolchain:
>>
>> .text
>> gs:
>>      .set    noat
>>      gslble    $2, $3, $4              # encoding: [0x10,0x20,0x62,0xc8]
>>                                          # <MCInst #1546 GSLBLE
>>                                          #  <MCOperand Reg:321>
>>                                          #  <MCOperand Reg:322>
>>                                          #  <MCOperand Reg:22>>
>>      gslbgt    $5, $6, $7              # encoding: [0x11,0x38,0xc5,0xc8]
>>                                          # <MCInst #1545 GSLBGT
>>                                          #  <MCOperand Reg:23>
>>                                          #  <MCOperand Reg:24>
>>                                          #  <MCOperand Reg:25>>
>>      gslhle    $8, $9, $10             # encoding: [0x12,0x50,0x28,0xc9]
>>                                          # <MCInst #1553 GSLHLE
>>                                          #  <MCOperand Reg:311>
>>                                          #  <MCOperand Reg:312>
>>                                          #  <MCOperand Reg:313>>
>>      gslhgt    $11, $12, $13           # encoding: [0x13,0x68,0x8b,0xc9]
>>                                          # <MCInst #1552 GSLHGT
>>                                          #  <MCOperand Reg:314>
>>                                          #  <MCOperand Reg:315>
>>                                          #  <MCOperand Reg:316>>
>>      gslwle    $14, $15, $16           # encoding: [0x14,0x80,0xee,0xc9]
>>                                          # <MCInst #1557 GSLWLE
>>                                          #  <MCOperand Reg:317>
>>                                          #  <MCOperand Reg:318>
>>                                          #  <MCOperand Reg:302>>
>>      gslwgt    $17, $18, $19           # encoding: [0x15,0x98,0x51,0xca]
>>                                          # <MCInst #1555 GSLWGT
>>                                          #  <MCOperand Reg:303>
>>                                          #  <MCOperand Reg:304>
>>                                          #  <MCOperand Reg:305>>
>>      gsldle    $20, $21, $22           # encoding: [0x16,0xb0,0xb4,0xca]
>>                                          # <MCInst #1550 GSLDLE
>>                                          #  <MCOperand Reg:402>
>>                                          #  <MCOperand Reg:403>
>>                                          #  <MCOperand Reg:404>>
>>      gsldgt    $23, $24, $25           # encoding: [0x17,0xc8,0x17,0xcb]
>>                                          # <MCInst #1548 GSLDGT
>>                                          #  <MCOperand Reg:405>
>>                                          #  <MCOperand Reg:414>
>>                                          #  <MCOperand Reg:415>>
>>      gslwlec1    $f0, $2, $3     # encoding: [0x1c,0x18,0x40,0xc8]
>>                                          # <MCInst #1558 GSLWLEC1
>>                                          #  <MCOperand Reg:147>
>>                                          #  <MCOperand Reg:321>
>>                                          #  <MCOperand Reg:322>>
>>      gslwgtc1    $f1, $4, $5     # encoding: [0x1d,0x28,0x81,0xc8]
>>                                          # <MCInst #1556 GSLWGTC1
>>                                          #  <MCOperand Reg:148>
>>                                          #  <MCOperand Reg:22>
>>                                          #  <MCOperand Reg:23>>
>>      gsldlec1    $f2, $6, $7     # encoding: [0x1e,0x38,0xc2,0xc8]
>>                                          # <MCInst #1551 GSLDLEC1
>>                                          #  <MCOperand Reg:363>
>>                                          #  <MCOperand Reg:358>
>>                                          #  <MCOperand Reg:359>>
>>      gsldgtc1    $f3, $8, $9     # encoding: [0x1f,0x48,0x03,0xc9]
>>                                          # <MCInst #1549 GSLDGTC1
>>                                          #  <MCOperand Reg:364>
>>                                          #  <MCOperand Reg:406>
>>                                          #  <MCOperand Reg:407>>
>>      gslq    $10, $11, 4080($12)     # encoding: [0xea,0x3f,0x8b,0xc9]
>>                                          # <MCInst #1554 GSLQ
>>                                          #  <MCOperand Reg:408>
>>                                          #  <MCOperand Reg:409>
>>                                          #  <MCOperand Reg:410>
>>                                          #  <MCOperand Imm:4080>>
>>      gssble    $2, $3, $4              # encoding: [0x10,0x20,0x62,0xe8]
>>                                          # <MCInst #1560 GSSBLE
>>                                          #  <MCOperand Reg:321>
>>                                          #  <MCOperand Reg:322>
>>                                          #  <MCOperand Reg:22>>
>>      gssbgt    $5, $6, $7              # encoding: [0x11,0x38,0xc5,0xe8]
>>                                          # <MCInst #1559 GSSBGT
>>                                          #  <MCOperand Reg:23>
>>                                          #  <MCOperand Reg:24>
>>                                          #  <MCOperand Reg:25>>
>>      gsshle    $8, $9, $10             # encoding: [0x12,0x50,0x28,0xe9]
>>                                          # <MCInst #1566 GSSHLE
>>                                          #  <MCOperand Reg:311>
>>                                          #  <MCOperand Reg:312>
>>                                          #  <MCOperand Reg:313>>
>>      gsshgt    $11, $12, $13           # encoding: [0x13,0x68,0x8b,0xe9]
>>                                          # <MCInst #1565 GSSHGT
>>                                          #  <MCOperand Reg:314>
>>                                          #  <MCOperand Reg:315>
>>                                          #  <MCOperand Reg:316>>
>>      gsswle    $14, $15, $16           # encoding: [0x14,0x80,0xee,0xe9]
>>                                          # <MCInst #1570 GSSWLE
>>                                          #  <MCOperand Reg:317>
>>                                          #  <MCOperand Reg:318>
>>                                          #  <MCOperand Reg:302>>
>>      gsswgt    $17, $18, $19           # encoding: [0x15,0x98,0x51,0xea]
>>                                          # <MCInst #1568 GSSWGT
>>                                          #  <MCOperand Reg:303>
>>                                          #  <MCOperand Reg:304>
>>                                          #  <MCOperand Reg:305>>
>>      gssdle    $20, $21, $22           # encoding: [0x16,0xb0,0xb4,0xea]
>>                                          # <MCInst #1563 GSSDLE
>>                                          #  <MCOperand Reg:402>
>>                                          #  <MCOperand Reg:403>
>>                                          #  <MCOperand Reg:404>>
>>      gssdgt    $23, $24, $25           # encoding: [0x17,0xc8,0x17,0xeb]
>>                                          # <MCInst #1561 GSSDGT
>>                                          #  <MCOperand Reg:405>
>>                                          #  <MCOperand Reg:414>
>>                                          #  <MCOperand Reg:415>>
>>      gsswlec1    $f4, $10, $11   # encoding: [0x1c,0x58,0x44,0xe9]
>>                                          # <MCInst #1571 GSSWLEC1
>>                                          #  <MCOperand Reg:151>
>>                                          #  <MCOperand Reg:313>
>>                                          #  <MCOperand Reg:314>>
>>      gsswgtc1    $f5, $12, $13   # encoding: [0x1d,0x68,0x85,0xe9]
>>                                          # <MCInst #1569 GSSWGTC1
>>                                          #  <MCOperand Reg:152>
>>                                          #  <MCOperand Reg:315>
>>                                          #  <MCOperand Reg:316>>
>>      gssdlec1    $f6, $14, $15   # encoding: [0x1e,0x78,0xc6,0xe9]
>>                                          # <MCInst #1564 GSSDLEC1
>>                                          #  <MCOperand Reg:367>
>>                                          #  <MCOperand Reg:412>
>>                                          #  <MCOperand Reg:413>>
>>      gssdgtc1    $f7, $16, $17   # encoding: [0x1f,0x88,0x07,0xea]
>>                                          # <MCInst #1562 GSSDGTC1
>>                                          #  <MCOperand Reg:368>
>>                                          #  <MCOperand Reg:398>
>>                                          #  <MCOperand Reg:399>>
>>      gssq    $13, $14, -4096($15)    # encoding: [0x2d,0x40,0xee,0xe9]
>>                                          # <MCInst #1567 GSSQ
>>                                          #  <MCOperand Reg:411>
>>                                          #  <MCOperand Reg:412>
>>                                          #  <MCOperand Reg:413>
>>                                          #  <MCOperand Imm:-4096>>
>> test/MC/Mips/loongson3a/valid.s:32:30: error: invalid operand for instruction
>>          gslbx           $2,0($3,$4)
>>                                        ^
>>
>> valid-gnu.o:     file format elf64-tradlittlemips
>>
>>
>> Disassembly of section .text:
>>
>> 0000000000000000 <gs>:
>>     0:    c8622010     gslble    v0,v1,a0
>>     4:    c8c53811     gslbgt    a1,a2,a3
>>     8:    c9285012     gslhle    a4,a5,a6
>>     c:    00000000     nop
>>    10:    c98b6813     gslhgt    a7,t0,t1
>>    14:    c9ee8014     gslwle    t2,t3,s0
>>    18:    ca519815     gslwgt    s1,s2,s3
>>    1c:    00000000     nop
>>    20:    cab4b016     gsldle    s4,s5,s6
>>    24:    cb17c817     gsldgt    s7,t8,t9
>>    28:    c840181c     gslwlec1    $f0,v0,v1
>>    2c:    00000000     nop
>>    30:    c881281d     gslwgtc1    $f1,a0,a1
>>    34:    c8c2381e     gsldlec1    $f2,a2,a3
>>    38:    c903481f     gsldgtc1    $f3,a4,a5
>>    3c:    c98b3fea     gslq    a6,a7,4080(t0)
>>    40:    e8622010     gssble    v0,v1,a0
>>    44:    e8c53811     gssbgt    a1,a2,a3
>>    48:    e9285012     gsshle    a4,a5,a6
>>    4c:    e98b6813     gsshgt    a7,t0,t1
>>    50:    e9ee8014     gsswle    t2,t3,s0
>>    54:    ea519815     gsswgt    s1,s2,s3
>>    58:    eab4b016     gssdle    s4,s5,s6
>>    5c:    eb17c817     gssdgt    s7,t8,t9
>>    60:    e944581c     gsswlec1    $f4,a6,a7
>>    64:    e985681d     gsswgtc1    $f5,t0,t1
>>    68:    e9c6781e     gssdlec1    $f6,t2,t3
>>    6c:    ea07881f     gssdgtc1    $f7,s0,s1
>>    70:    e9ee402d     gssq    t1,t2,-4096(t3)
>>    74:    d8622000     gslbx    v0,0(v1,a0)
>>      ...
>> -- Testing: 1 tests, 1 threads --
>> FAIL: LLVM :: MC/Mips/loongson3a/valid.s (1 of 1)
>> Testing Time: 0.45s
>> ********************
>> Failing Tests (1):
>>      LLVM :: MC/Mips/loongson3a/valid.s
>>
>>    Unexpected Failures: 1
>>
>> ----- 8< -------- 8< -------- 8< -------- 8< -------- 8< -------- 8< ---
>>
>> Please teach me how to implement custom MemEncoding.
>>
>> Thanks,
>>
>> Leslie Zhai
>>
>>




More information about the llvm-dev mailing list