[llvm] r240425 - MIR Serialization: Serialize physical register machine operands.
Alex L
arphaman at gmail.com
Thu Jun 25 08:13:26 PDT 2015
Yeah, I can see why this kind of pattern would be useful. I think I will
try to adopt it, as there are a couple of cases in the main lexing routine
that would benefit from this a lot.
Cheers,
Alex
2015-06-24 18:37 GMT-07:00 Sean Silva <chisophugis at gmail.com>:
>
>
> On Tue, Jun 23, 2015 at 9:35 AM, Alex Lorenz <arphaman at gmail.com> wrote:
>
>> Author: arphaman
>> Date: Tue Jun 23 11:35:26 2015
>> New Revision: 240425
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=240425&view=rev
>> Log:
>> MIR Serialization: Serialize physical register machine operands.
>>
>> This commit introduces functionality that's used to serialize machine
>> operands.
>> Only the physical register operands are serialized by this commit.
>>
>> Reviewers: Duncan P. N. Exon Smith
>>
>> Differential Revision: http://reviews.llvm.org/D10525
>>
>> Added:
>> llvm/trunk/test/CodeGen/MIR/X86/expected-machine-operand.mir
>> llvm/trunk/test/CodeGen/MIR/X86/missing-comma.mir
>> llvm/trunk/test/CodeGen/MIR/X86/named-registers.mir
>> llvm/trunk/test/CodeGen/MIR/X86/unknown-register.mir
>> Modified:
>> llvm/trunk/lib/CodeGen/MIRParser/MILexer.cpp
>> llvm/trunk/lib/CodeGen/MIRParser/MILexer.h
>> llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp
>> llvm/trunk/lib/CodeGen/MIRPrinter.cpp
>>
>> Modified: llvm/trunk/lib/CodeGen/MIRParser/MILexer.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRParser/MILexer.cpp?rev=240425&r1=240424&r2=240425&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/MIRParser/MILexer.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/MIRParser/MILexer.cpp Tue Jun 23 11:35:26 2015
>> @@ -68,6 +68,33 @@ static Cursor lexIdentifier(Cursor C, MI
>> return C;
>> }
>>
>> +static Cursor lexPercent(Cursor C, MIToken &Token) {
>> + auto Range = C;
>> + C.advance(); // Skip '%'
>> + while (isIdentifierChar(C.peek()))
>> + C.advance();
>> + Token = MIToken(MIToken::NamedRegister, Range.upto(C));
>> + return C;
>> +}
>> +
>> +static MIToken::TokenKind symbolToken(char C) {
>> + switch (C) {
>> + case ',':
>> + return MIToken::comma;
>> + case '=':
>> + return MIToken::equal;
>> + default:
>> + return MIToken::Error;
>> + }
>> +}
>> +
>> +static Cursor lexSymbol(Cursor C, MIToken::TokenKind Kind, MIToken
>> &Token) {
>> + auto Range = C;
>> + C.advance();
>> + Token = MIToken(Kind, Range.upto(C));
>> + return C;
>> +}
>> +
>> StringRef llvm::lexMIToken(
>> StringRef Source, MIToken &Token,
>> function_ref<void(StringRef::iterator Loc, const Twine &)>
>> ErrorCallback) {
>> @@ -80,6 +107,11 @@ StringRef llvm::lexMIToken(
>> auto Char = C.peek();
>> if (isalpha(Char) || Char == '_')
>> return lexIdentifier(C, Token).remaining();
>> + if (Char == '%')
>> + return lexPercent(C, Token).remaining();
>> + MIToken::TokenKind Kind = symbolToken(Char);
>> + if (Kind != MIToken::Error)
>> + return lexSymbol(C, Kind, Token).remaining();
>>
>
> If you end up with many more of these cases of "determining what token
> kind we need to lex requires work that needs to be shared with the actual
> lexing of the token", you may want to look into this pattern:
> ```
> if (... = maybeLexFoo(...))
> return ...;
> if (... = maybeLexBar(...))
> return ...;
> ```
>
> This helps keep the top-level routine having a highly regular structure.
> Another advantage is that the maybeLex* functions are then completely
> self-contained as to what they lex (except for a couple nasty cases; IIRC
> in VHDL the complicated one I ran into was bit string literals vs numeric
> literals with explicit base).
>
> -- Sean Silva
>
>
>> Token = MIToken(MIToken::Error, C.remaining());
>> ErrorCallback(C.location(),
>> Twine("unexpected character '") + Twine(Char) + "'");
>>
>> Modified: llvm/trunk/lib/CodeGen/MIRParser/MILexer.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRParser/MILexer.h?rev=240425&r1=240424&r2=240425&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/MIRParser/MILexer.h (original)
>> +++ llvm/trunk/lib/CodeGen/MIRParser/MILexer.h Tue Jun 23 11:35:26 2015
>> @@ -30,8 +30,13 @@ struct MIToken {
>> Eof,
>> Error,
>>
>> + // Tokens with no info.
>> + comma,
>> + equal,
>> +
>> // Identifier tokens
>> - Identifier
>> + Identifier,
>> + NamedRegister
>> };
>>
>> private:
>> @@ -45,6 +50,8 @@ public:
>>
>> bool isError() const { return Kind == Error; }
>>
>> + bool isRegister() const { return Kind == NamedRegister; }
>> +
>> bool is(TokenKind K) const { return Kind == K; }
>>
>> bool isNot(TokenKind K) const { return Kind != K; }
>>
>> Modified: llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp?rev=240425&r1=240424&r2=240425&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp Tue Jun 23 11:35:26 2015
>> @@ -34,6 +34,8 @@ class MIParser {
>> MIToken Token;
>> /// Maps from instruction names to op codes.
>> StringMap<unsigned> Names2InstrOpCodes;
>> + /// Maps from register names to registers.
>> + StringMap<unsigned> Names2Regs;
>>
>> public:
>> MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error,
>> @@ -53,6 +55,10 @@ public:
>>
>> MachineInstr *parse();
>>
>> + bool parseRegister(unsigned &Reg);
>> + bool parseRegisterOperand(MachineOperand &Dest, bool IsDef = false);
>> + bool parseMachineOperand(MachineOperand &Dest);
>> +
>> private:
>> void initNames2InstrOpCodes();
>>
>> @@ -61,6 +67,12 @@ private:
>> bool parseInstrName(StringRef InstrName, unsigned &OpCode);
>>
>> bool parseInstruction(unsigned &OpCode);
>> +
>> + void initNames2Regs();
>> +
>> + /// Try to convert a register name to a register number. Return true
>> if the
>> + /// register name is invalid.
>> + bool getRegisterByName(StringRef RegName, unsigned &Reg);
>> };
>>
>> } // end anonymous namespace
>> @@ -92,13 +104,60 @@ bool MIParser::error(StringRef::iterator
>> MachineInstr *MIParser::parse() {
>> lex();
>>
>> + // Parse any register operands before '='
>> + // TODO: Allow parsing of multiple operands before '='
>> + MachineOperand MO = MachineOperand::CreateImm(0);
>> + SmallVector<MachineOperand, 8> Operands;
>> + if (Token.isRegister()) {
>> + if (parseRegisterOperand(MO, /*IsDef=*/true))
>> + return nullptr;
>> + Operands.push_back(MO);
>> + if (Token.isNot(MIToken::equal)) {
>> + error("expected '='");
>> + return nullptr;
>> + }
>> + lex();
>> + }
>> +
>> unsigned OpCode;
>> if (Token.isError() || parseInstruction(OpCode))
>> return nullptr;
>>
>> - // TODO: Parse the rest of instruction - machine operands, etc.
>> + // TODO: Parse the instruction flags and memory operands.
>> +
>> + // Parse the remaining machine operands.
>> + while (Token.isNot(MIToken::Eof)) {
>> + if (parseMachineOperand(MO))
>> + return nullptr;
>> + Operands.push_back(MO);
>> + if (Token.is(MIToken::Eof))
>> + break;
>> + if (Token.isNot(MIToken::comma)) {
>> + error("expected ',' before the next machine operand");
>> + return nullptr;
>> + }
>> + lex();
>> + }
>> +
>> const auto &MCID = MF.getSubtarget().getInstrInfo()->get(OpCode);
>> - auto *MI = MF.CreateMachineInstr(MCID, DebugLoc());
>> +
>> + // Verify machine operands.
>> + if (!MCID.isVariadic()) {
>> + for (size_t I = 0, E = Operands.size(); I < E; ++I) {
>> + if (I < MCID.getNumOperands())
>> + continue;
>> + // Mark this register as implicit to prevent an assertion when
>> it's added
>> + // to an instruction. This is a temporary workaround until the
>> implicit
>> + // register flag can be parsed.
>> + Operands[I].setImplicit();
>> + }
>> + }
>> +
>> + // TODO: Determine the implicit behaviour when implicit register flags
>> are
>> + // parsed.
>> + auto *MI = MF.CreateMachineInstr(MCID, DebugLoc(),
>> /*NoImplicit=*/true);
>> + for (const auto &Operand : Operands)
>> + MI->addOperand(MF, Operand);
>> return MI;
>> }
>>
>> @@ -108,6 +167,46 @@ bool MIParser::parseInstruction(unsigned
>> StringRef InstrName = Token.stringValue();
>> if (parseInstrName(InstrName, OpCode))
>> return error(Twine("unknown machine instruction name '") + InstrName
>> + "'");
>> + lex();
>> + return false;
>> +}
>> +
>> +bool MIParser::parseRegister(unsigned &Reg) {
>> + switch (Token.kind()) {
>> + case MIToken::NamedRegister: {
>> + StringRef Name = Token.stringValue().drop_front(1); // Drop the '%'
>> + if (getRegisterByName(Name, Reg))
>> + return error(Twine("unknown register name '") + Name + "'");
>> + break;
>> + }
>> + // TODO: Parse other register kinds.
>> + default:
>> + llvm_unreachable("The current token should be a register");
>> + }
>> + return false;
>> +}
>> +
>> +bool MIParser::parseRegisterOperand(MachineOperand &Dest, bool IsDef) {
>> + unsigned Reg;
>> + // TODO: Parse register flags.
>> + if (parseRegister(Reg))
>> + return true;
>> + lex();
>> + // TODO: Parse subregister.
>> + Dest = MachineOperand::CreateReg(Reg, IsDef);
>> + return false;
>> +}
>> +
>> +bool MIParser::parseMachineOperand(MachineOperand &Dest) {
>> + switch (Token.kind()) {
>> + case MIToken::NamedRegister:
>> + return parseRegisterOperand(Dest);
>> + case MIToken::Error:
>> + return true;
>> + default:
>> + // TODO: parse the other machine operands.
>> + return error("expected a machine operand");
>> + }
>> return false;
>> }
>>
>> @@ -129,6 +228,29 @@ bool MIParser::parseInstrName(StringRef
>> return false;
>> }
>>
>> +void MIParser::initNames2Regs() {
>> + if (!Names2Regs.empty())
>> + return;
>> + const auto *TRI = MF.getSubtarget().getRegisterInfo();
>> + assert(TRI && "Expected target register info");
>> + for (unsigned I = 0, E = TRI->getNumRegs(); I < E; ++I) {
>> + bool WasInserted =
>> +
>> Names2Regs.insert(std::make_pair(StringRef(TRI->getName(I)).lower(), I))
>> + .second;
>> + (void)WasInserted;
>> + assert(WasInserted && "Expected registers to be unique
>> case-insensitively");
>> + }
>> +}
>> +
>> +bool MIParser::getRegisterByName(StringRef RegName, unsigned &Reg) {
>> + initNames2Regs();
>> + auto RegInfo = Names2Regs.find(RegName);
>> + if (RegInfo == Names2Regs.end())
>> + return true;
>> + Reg = RegInfo->getValue();
>> + return false;
>> +}
>> +
>> MachineInstr *llvm::parseMachineInstr(SourceMgr &SM, MachineFunction &MF,
>> StringRef Src, SMDiagnostic
>> &Error) {
>> return MIParser(SM, MF, Error, Src).parse();
>>
>> Modified: llvm/trunk/lib/CodeGen/MIRPrinter.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRPrinter.cpp?rev=240425&r1=240424&r2=240425&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/MIRPrinter.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/MIRPrinter.cpp Tue Jun 23 11:35:26 2015
>> @@ -50,6 +50,7 @@ public:
>> MIPrinter(raw_ostream &OS) : OS(OS) {}
>>
>> void print(const MachineInstr &MI);
>> + void print(const MachineOperand &Op, const TargetRegisterInfo *TRI);
>> };
>>
>> } // end anonymous namespace
>> @@ -110,11 +111,58 @@ void MIRPrinter::convert(yaml::MachineBa
>>
>> void MIPrinter::print(const MachineInstr &MI) {
>> const auto &SubTarget = MI.getParent()->getParent()->getSubtarget();
>> + const auto *TRI = SubTarget.getRegisterInfo();
>> + assert(TRI && "Expected target register info");
>> const auto *TII = SubTarget.getInstrInfo();
>> assert(TII && "Expected target instruction info");
>>
>> + unsigned I = 0, E = MI.getNumOperands();
>> + for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
>> + !MI.getOperand(I).isImplicit();
>> + ++I) {
>> + if (I)
>> + OS << ", ";
>> + print(MI.getOperand(I), TRI);
>> + }
>> +
>> + if (I)
>> + OS << " = ";
>> OS << TII->getName(MI.getOpcode());
>> - // TODO: Print the instruction flags, machine operands, machine mem
>> operands.
>> + // TODO: Print the instruction flags, machine mem operands.
>> + if (I < E)
>> + OS << ' ';
>> +
>> + bool NeedComma = false;
>> + for (; I < E; ++I) {
>> + if (NeedComma)
>> + OS << ", ";
>> + print(MI.getOperand(I), TRI);
>> + NeedComma = true;
>> + }
>> +}
>> +
>> +static void printReg(unsigned Reg, raw_ostream &OS,
>> + const TargetRegisterInfo *TRI) {
>> + // TODO: Print Stack Slots.
>> + // TODO: Print no register.
>> + // TODO: Print virtual registers.
>> + if (Reg < TRI->getNumRegs())
>> + OS << '%' << StringRef(TRI->getName(Reg)).lower();
>> + else
>> + llvm_unreachable("Can't print this kind of register yet");
>> +}
>> +
>> +void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo
>> *TRI) {
>> + switch (Op.getType()) {
>> + case MachineOperand::MO_Register:
>> + // TODO: Print register flags.
>> + printReg(Op.getReg(), OS, TRI);
>> + // TODO: Print sub register.
>> + break;
>> + default:
>> + // TODO: Print the other machine operands.
>> + llvm_unreachable("Can't print this machine operand at the moment");
>> + }
>> }
>>
>> void llvm::printMIR(raw_ostream &OS, const Module &M) {
>>
>> Added: llvm/trunk/test/CodeGen/MIR/X86/expected-machine-operand.mir
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/expected-machine-operand.mir?rev=240425&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/MIR/X86/expected-machine-operand.mir (added)
>> +++ llvm/trunk/test/CodeGen/MIR/X86/expected-machine-operand.mir Tue Jun
>> 23 11:35:26 2015
>> @@ -0,0 +1,20 @@
>> +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after
>> branch-folder -o /dev/null %s 2>&1 | FileCheck %s
>> +
>> +--- |
>> +
>> + define i32 @foo() {
>> + entry:
>> + ret i32 0
>> + }
>> +
>> +...
>> +---
>> +name: foo
>> +body:
>> + - name: entry
>> + instructions:
>> + # CHECK: 1:16: expected a machine operand
>> + - '%eax = XOR32rr ='
>> + - 'RETQ %eax'
>> +...
>> +
>>
>> Added: llvm/trunk/test/CodeGen/MIR/X86/missing-comma.mir
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/missing-comma.mir?rev=240425&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/MIR/X86/missing-comma.mir (added)
>> +++ llvm/trunk/test/CodeGen/MIR/X86/missing-comma.mir Tue Jun 23 11:35:26
>> 2015
>> @@ -0,0 +1,20 @@
>> +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after
>> branch-folder -o /dev/null %s 2>&1 | FileCheck %s
>> +
>> +--- |
>> +
>> + define i32 @foo() {
>> + entry:
>> + ret i32 0
>> + }
>> +
>> +...
>> +---
>> +name: foo
>> +body:
>> + - name: entry
>> + instructions:
>> + # CHECK: 1:21: expected ',' before the next machine operand
>> + - '%eax = XOR32rr %eax %eflags'
>> + - 'RETQ %eax'
>> +...
>> +
>>
>> Added: llvm/trunk/test/CodeGen/MIR/X86/named-registers.mir
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/named-registers.mir?rev=240425&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/MIR/X86/named-registers.mir (added)
>> +++ llvm/trunk/test/CodeGen/MIR/X86/named-registers.mir Tue Jun 23
>> 11:35:26 2015
>> @@ -0,0 +1,22 @@
>> +# RUN: llc -march=x86-64 -start-after branch-folder -stop-after
>> branch-folder -o /dev/null %s | FileCheck %s
>> +# This test ensures that the MIR parser parses X86 registers correctly.
>> +
>> +--- |
>> +
>> + define i32 @foo() {
>> + entry:
>> + ret i32 0
>> + }
>> +
>> +...
>> +---
>> +# CHECK: name: foo
>> +name: foo
>> +body:
>> + - name: entry
>> + instructions:
>> + # CHECK: - '%eax = MOV32r0
>> + # CHECK-NEXT: - 'RETQ %eax
>> + - '%eax = MOV32r0'
>> + - 'RETQ %eax'
>> +...
>>
>> Added: llvm/trunk/test/CodeGen/MIR/X86/unknown-register.mir
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/unknown-register.mir?rev=240425&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/MIR/X86/unknown-register.mir (added)
>> +++ llvm/trunk/test/CodeGen/MIR/X86/unknown-register.mir Tue Jun 23
>> 11:35:26 2015
>> @@ -0,0 +1,21 @@
>> +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after
>> branch-folder -o /dev/null %s 2>&1 | FileCheck %s
>> +# This test ensures that an error is reported when an unknown register is
>> +# encountered.
>> +
>> +--- |
>> +
>> + define i32 @foo() {
>> + entry:
>> + ret i32 0
>> + }
>> +
>> +...
>> +---
>> +name: foo
>> +body:
>> + - name: entry
>> + instructions:
>> + # CHECK: 1:1: unknown register name 'xax'
>> + - '%xax = MOV32r0'
>> + - 'RETQ %xax'
>> +...
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150625/0c5355f6/attachment.html>
More information about the llvm-commits
mailing list