[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