Carter, Jack
2012-Jan-31 21:26 UTC
[LLVMdev] (MC) Register parsing for AsmParser (standalone assembler)
I'm trying to build a standalone assembler for Mips using AsmParser. Following the lead of X86, ARM and MBlaze I have run tblgen -gen-asm-matcher on Mips.td to produce tables and methods to aid the parser (MipsAsmParser.cpp) which is a stripped down ARM implementation. I am getting an assertion for what I believe are multiple register definitions with the same name. llvm-tblgen: /home/jcarter/workarea/asm/llvm/utils/TableGen/StringMatcher.cpp:52: bool llvm::StringMatcher::EmitStringMatcherForChar(const std::vector<const std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*, std::allocator<const std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*> >&, unsigned int, unsigned int) const: Assertion `Matches.size() == 1 && "Had duplicate keys to match on"' failed. ********************************* Background for Mips register sets: ********************************* The Mips architecture has register names that are context sensitive. For instance, the 32 general purpose registers for both Mips32 and Mips64 have the same name, but each of the Mips32 registers are just a subregister in their Mips64 instance. def AT : MipsGPRReg< 1, "AT">, DwarfRegNum<[1]>; def AT_64 : Mips64GPRReg< 1, "AT", [AT]>; It gets more interesting with floating point where we have 3 different configurations, single precision, double precision aliased with single precision pair and straight double point precision. All of which share the same register name. /// Mips Single point precision FPU Registers def F0 : FPR< 0, "F0">, DwarfRegNum<[32]>; /// Mips Double point precision FPU Registers (aliased /// with the single precision to hold 64 bit values) def D0 : AFPR< 0, "F0", [F0, F1]>; /// Mips Double point precision FPU Registers in MFP64 mode. def D0_64 : AFPR64<0, "F0", [F0]>; Notice that we currently need the symbolic name to be different (F0/D0/D0_64) for use in the codegen. The examples here are from lib/Target/Mips/MipsRegisterInfo.td. Do I just need to use/write another register parser? Or is there a clever way of defining the context sensitive Mips register set? Thanks, Jack -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120131/376c9065/attachment.html>
Chris Lattner
2012-Feb-02 00:10 UTC
[LLVMdev] (MC) Register parsing for AsmParser (standalone assembler)
On Jan 31, 2012, at 1:26 PM, Carter, Jack wrote:> I'm trying to build a standalone assembler for Mips using AsmParser. > > Following the lead of X86, ARM and MBlaze I have run tblgen -gen-asm-matcher on Mips.td to produce tables and methods to aid the parser (MipsAsmParser.cpp) which is a stripped down ARM implementation. > > I am getting an assertion for what I believe are multiple register definitions with the same name. > > llvm-tblgen: /home/jcarter/workarea/asm/llvm/utils/TableGen/StringMatcher.cpp:52: bool llvm::StringMatcher::EmitStringMatcherForChar(const std::vector<const std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*, std::allocator<const std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*> >&, unsigned int, unsigned int) const: Assertion `Matches.size() == 1 && "Had duplicate keys to match on"' failed.I don't know the actual answer for your question, but it would be really great if you could add code to tblgen to have it produce an error for this case, instead of aborting. -Chris> > ********************************* > Background for Mips register sets: > ********************************* > > The Mips architecture has register names that are context sensitive. > > For instance, the 32 general purpose registers for both Mips32 and Mips64 have the same name, but each of the Mips32 registers are just a subregister in their Mips64 instance. > > def AT : MipsGPRReg< 1, "AT">, DwarfRegNum<[1]>; > def AT_64 : Mips64GPRReg< 1, "AT", [AT]>; > > It gets more interesting with floating point where we have 3 different configurations, single precision, double precision aliased with single precision pair and straight double point precision. All of which share the same register name. > > /// Mips Single point precision FPU Registers > def F0 : FPR< 0, "F0">, DwarfRegNum<[32]>; > > /// Mips Double point precision FPU Registers (aliased > /// with the single precision to hold 64 bit values) > def D0 : AFPR< 0, "F0", [F0, F1]>; > > /// Mips Double point precision FPU Registers in MFP64 mode. > def D0_64 : AFPR64<0, "F0", [F0]>; > > Notice that we currently need the symbolic name to be different (F0/D0/D0_64) for use in the codegen. > > The examples here are from lib/Target/Mips/MipsRegisterInfo.td. > > Do I just need to use/write another register parser? Or is there a clever way of defining the context sensitive Mips register set? > > Thanks, > > Jack > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120201/204b4fee/attachment.html>
Carter, Jack
2012-Feb-02 19:54 UTC
[LLVMdev] (MC) Register parsing for AsmParser (standalone assembler)
I agree that a clear error message is necessary to save the developer a lot of time. I am also chronicling my steps and travails of getting the llvm-mc assembler to work for Mips so the next target has it easier. But, it would be really nice to have insight from current AsmParser developers in the philosophy and assumptions for the current tblgen -gen-asm-matcher use. Is it ok to not use it (MipsGenAsmMatcher.inc) and go our own way? I'd rather not, because it goes against the reuse philosophy. Can the target.td definition be changed to allow register predicates if it doesn't already have that? If so, I could change the register name comparison to be a register name plus predicate comparison with no predicate being a type to preserve current use. Cheers, Jack ________________________________ From: Chris Lattner [clattner at apple.com] Sent: Wednesday, February 01, 2012 4:10 PM To: Carter, Jack Cc: List Subject: Re: [LLVMdev] (MC) Register parsing for AsmParser (standalone assembler) On Jan 31, 2012, at 1:26 PM, Carter, Jack wrote: I'm trying to build a standalone assembler for Mips using AsmParser. Following the lead of X86, ARM and MBlaze I have run tblgen -gen-asm-matcher on Mips.td to produce tables and methods to aid the parser (MipsAsmParser.cpp) which is a stripped down ARM implementation. I am getting an assertion for what I believe are multiple register definitions with the same name. llvm-tblgen: /home/jcarter/workarea/asm/llvm/utils/TableGen/StringMatcher.cpp:52: bool llvm::StringMatcher::EmitStringMatcherForChar(const std::vector<const std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*, std::allocator<const std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*> >&, unsigned int, unsigned int) const: Assertion `Matches.size() == 1 && "Had duplicate keys to match on"' failed. I don't know the actual answer for your question, but it would be really great if you could add code to tblgen to have it produce an error for this case, instead of aborting. -Chris ********************************* Background for Mips register sets: ********************************* The Mips architecture has register names that are context sensitive. For instance, the 32 general purpose registers for both Mips32 and Mips64 have the same name, but each of the Mips32 registers are just a subregister in their Mips64 instance. def AT : MipsGPRReg< 1, "AT">, DwarfRegNum<[1]>; def AT_64 : Mips64GPRReg< 1, "AT", [AT]>; It gets more interesting with floating point where we have 3 different configurations, single precision, double precision aliased with single precision pair and straight double point precision. All of which share the same register name. /// Mips Single point precision FPU Registers def F0 : FPR< 0, "F0">, DwarfRegNum<[32]>; /// Mips Double point precision FPU Registers (aliased /// with the single precision to hold 64 bit values) def D0 : AFPR< 0, "F0", [F0, F1]>; /// Mips Double point precision FPU Registers in MFP64 mode. def D0_64 : AFPR64<0, "F0", [F0]>; Notice that we currently need the symbolic name to be different (F0/D0/D0_64) for use in the codegen. The examples here are from lib/Target/Mips/MipsRegisterInfo.td. Do I just need to use/write another register parser? Or is there a clever way of defining the context sensitive Mips register set? Thanks, Jack _______________________________________________ LLVM Developers mailing list LLVMdev at cs.uiuc.edu<mailto:LLVMdev at cs.uiuc.edu> http://llvm.cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120202/43a45de5/attachment.html>
Jim Grosbach
2012-Feb-03 00:43 UTC
[LLVMdev] (MC) Register parsing for AsmParser (standalone assembler)
Hi Jack, You're running into a fundamental problem with the current table generated asmmatcher. Specifically, wants to believe that assembly parsing is context insensitive, or at least close enough that operands can be parsed w/o knowing the context of the instruction. Its idea is to use the operand types to disambiguate which instruction should be selected. It sounds like MIPS 64vs.32 does things the other way around and uses the mnemonic to disambiguate what the operands mean. You may be able to work around this a bit w/ some tblgen hacking. First, you'll need to disable the TableGen emission of MatchRegisterName(), which is almost certainly where this is running into trouble. That's currently unconditionally generated, and will need parameterized. Second, you'll need to have your register name matcher explicitly check for all the valid reg names complete w/ context to disambiguate. The ARM backend does some trivial additional (not context sensitive) handling there to match register name aliases. -Jim On Jan 31, 2012, at 1:26 PM, "Carter, Jack" <jcarter at mips.com> wrote:> I'm trying to build a standalone assembler for Mips using AsmParser. > > Following the lead of X86, ARM and MBlaze I have run tblgen -gen-asm-matcher on Mips.td to produce tables and methods to aid the parser (MipsAsmParser.cpp) which is a stripped down ARM implementation. > > I am getting an assertion for what I believe are multiple register definitions with the same name. > > llvm-tblgen: /home/jcarter/workarea/asm/llvm/utils/TableGen/StringMatcher.cpp:52: bool llvm::StringMatcher::EmitStringMatcherForChar(const std::vector<const std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*, std::allocator<const std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*> >&, unsigned int, unsigned int) const: Assertion `Matches.size() == 1 && "Had duplicate keys to match on"' failed. > > ********************************* > Background for Mips register sets: > ********************************* > > The Mips architecture has register names that are context sensitive. > > For instance, the 32 general purpose registers for both Mips32 and Mips64 have the same name, but each of the Mips32 registers are just a subregister in their Mips64 instance. > > def AT : MipsGPRReg< 1, "AT">, DwarfRegNum<[1]>; > def AT_64 : Mips64GPRReg< 1, "AT", [AT]>; > > It gets more interesting with floating point where we have 3 different configurations, single precision, double precision aliased with single precision pair and straight double point precision. All of which share the same register name. > > /// Mips Single point precision FPU Registers > def F0 : FPR< 0, "F0">, DwarfRegNum<[32]>; > > /// Mips Double point precision FPU Registers (aliased > /// with the single precision to hold 64 bit values) > def D0 : AFPR< 0, "F0", [F0, F1]>; > > /// Mips Double point precision FPU Registers in MFP64 mode. > def D0_64 : AFPR64<0, "F0", [F0]>; > > Notice that we currently need the symbolic name to be different (F0/D0/D0_64) for use in the codegen. > > The examples here are from lib/Target/Mips/MipsRegisterInfo.td. > > Do I just need to use/write another register parser? Or is there a clever way of defining the context sensitive Mips register set? > > Thanks, > > Jack > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120202/ace00ecc/attachment.html>
Carter, Jack
2012-Feb-03 01:33 UTC
[LLVMdev] (MC) Register parsing for AsmParser (standalone assembler)
Thank you, thank you , thank you Knowing what the problem is a great help. I can start towards the solution now. Jack ________________________________ From: Jim Grosbach [grosbach at apple.com] Sent: Thursday, February 02, 2012 4:43 PM To: Carter, Jack Cc: List Subject: Re: [LLVMdev] (MC) Register parsing for AsmParser (standalone assembler) Hi Jack, You're running into a fundamental problem with the current table generated asmmatcher. Specifically, wants to believe that assembly parsing is context insensitive, or at least close enough that operands can be parsed w/o knowing the context of the instruction. Its idea is to use the operand types to disambiguate which instruction should be selected. It sounds like MIPS 64vs.32 does things the other way around and uses the mnemonic to disambiguate what the operands mean. You may be able to work around this a bit w/ some tblgen hacking. First, you'll need to disable the TableGen emission of MatchRegisterName(), which is almost certainly where this is running into trouble. That's currently unconditionally generated, and will need parameterized. Second, you'll need to have your register name matcher explicitly check for all the valid reg names complete w/ context to disambiguate. The ARM backend does some trivial additional (not context sensitive) handling there to match register name aliases. -Jim On Jan 31, 2012, at 1:26 PM, "Carter, Jack" <jcarter at mips.com<mailto:jcarter at mips.com>> wrote: I'm trying to build a standalone assembler for Mips using AsmParser. Following the lead of X86, ARM and MBlaze I have run tblgen -gen-asm-matcher on Mips.td to produce tables and methods to aid the parser (MipsAsmParser.cpp) which is a stripped down ARM implementation. I am getting an assertion for what I believe are multiple register definitions with the same name. llvm-tblgen: /home/jcarter/workarea/asm/llvm/utils/TableGen/StringMatcher.cpp:52: bool llvm::StringMatcher::EmitStringMatcherForChar(const std::vector<const std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*, std::allocator<const std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*> >&, unsigned int, unsigned int) const: Assertion `Matches.size() == 1 && "Had duplicate keys to match on"' failed. ********************************* Background for Mips register sets: ********************************* The Mips architecture has register names that are context sensitive. For instance, the 32 general purpose registers for both Mips32 and Mips64 have the same name, but each of the Mips32 registers are just a subregister in their Mips64 instance. def AT : MipsGPRReg< 1, "AT">, DwarfRegNum<[1]>; def AT_64 : Mips64GPRReg< 1, "AT", [AT]>; It gets more interesting with floating point where we have 3 different configurations, single precision, double precision aliased with single precision pair and straight double point precision. All of which share the same register name. /// Mips Single point precision FPU Registers def F0 : FPR< 0, "F0">, DwarfRegNum<[32]>; /// Mips Double point precision FPU Registers (aliased /// with the single precision to hold 64 bit values) def D0 : AFPR< 0, "F0", [F0, F1]>; /// Mips Double point precision FPU Registers in MFP64 mode. def D0_64 : AFPR64<0, "F0", [F0]>; Notice that we currently need the symbolic name to be different (F0/D0/D0_64) for use in the codegen. The examples here are from lib/Target/Mips/MipsRegisterInfo.td. Do I just need to use/write another register parser? Or is there a clever way of defining the context sensitive Mips register set? Thanks, Jack _______________________________________________ LLVM Developers mailing list LLVMdev at cs.uiuc.edu<mailto:LLVMdev at cs.uiuc.edu> http://llvm.cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120203/f3807474/attachment.html>
Apparently Analagous Threads
- [LLVMdev] (MC) Register parsing for AsmParser (standalone assembler)
- [LLVMdev] (MC) Register parsing for AsmParser (standalone assembler)
- TableGen - cryptic error messages (~feature request)
- [LLVMdev] LLVM register number for MIPS DAGToDAG
- [LLVMdev] Calling conventions for YMM registers on AVX