Skip to content

Commit

Permalink
MIR Serialization: Serialize machine basic block operands.
Browse files Browse the repository at this point in the history
This commit serializes machine basic block operands. The
machine basic block operands use the following syntax:

  %bb.<id>[.<name>]

This commit also modifies the YAML representation for the
machine basic blocks - a new, required field 'id' is added
to the MBB YAML mapping.

The id is used to resolve the MBB references to the
actual MBBs. And while the name of the MBB can be
included in a MBB reference, this name isn't used to
resolve MBB references - as it's possible that multiple
MBBs will reference the same BB and thus they will have the
same name. If the name is specified, the parser will verify
that it is equal to the name of the MBB with the specified id.

Reviewers: Duncan P. N. Exon Smith

Differential Revision: http://reviews.llvm.org/D10608

llvm-svn: 240792
  • Loading branch information
hyp committed Jun 26, 2015
1 parent a67e50c commit 33f0aef
Show file tree
Hide file tree
Showing 25 changed files with 417 additions and 39 deletions.
2 changes: 2 additions & 0 deletions llvm/include/llvm/CodeGen/MIRYamlMapping.h
Expand Up @@ -64,6 +64,7 @@ namespace llvm {
namespace yaml {

struct MachineBasicBlock {
unsigned ID;
std::string Name;
unsigned Alignment = 0;
bool IsLandingPad = false;
Expand All @@ -75,6 +76,7 @@ struct MachineBasicBlock {

template <> struct MappingTraits<MachineBasicBlock> {
static void mapping(IO &YamlIO, MachineBasicBlock &MBB) {
YamlIO.mapRequired("id", MBB.ID);
YamlIO.mapOptional("name", MBB.Name,
std::string()); // Don't print out an empty name.
YamlIO.mapOptional("alignment", MBB.Alignment);
Expand Down
36 changes: 33 additions & 3 deletions llvm/lib/CodeGen/MIRParser/MILexer.cpp
Expand Up @@ -35,7 +35,7 @@ class Cursor {

char peek(int I = 0) const { return End - Ptr <= I ? 0 : Ptr[I]; }

void advance() { ++Ptr; }
void advance(unsigned I = 1) { Ptr += I; }

StringRef remaining() const { return StringRef(Ptr, End - Ptr); }

Expand Down Expand Up @@ -70,12 +70,39 @@ static Cursor lexIdentifier(Cursor C, MIToken &Token) {
return C;
}

static Cursor lexMachineBasicBlock(
Cursor C, MIToken &Token,
function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
auto Range = C;
C.advance(4); // Skip '%bb.'
if (!isdigit(C.peek())) {
Token = MIToken(MIToken::Error, C.remaining());
ErrorCallback(C.location(), "expected a number after '%bb.'");
return C;
}
auto NumberRange = C;
while (isdigit(C.peek()))
C.advance();
StringRef Number = NumberRange.upto(C);
unsigned StringOffset = 4 + Number.size(); // Drop '%bb.<id>'
if (C.peek() == '.') {
C.advance(); // Skip '.'
++StringOffset;
while (isIdentifierChar(C.peek()))
C.advance();
}
Token = MIToken(MIToken::MachineBasicBlock, Range.upto(C), APSInt(Number),
StringOffset);
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));
Token = MIToken(MIToken::NamedRegister, Range.upto(C),
/*StringOffset=*/1); // Drop the '%'
return C;
}

Expand Down Expand Up @@ -119,8 +146,11 @@ StringRef llvm::lexMIToken(
auto Char = C.peek();
if (isalpha(Char) || Char == '_')
return lexIdentifier(C, Token).remaining();
if (Char == '%')
if (Char == '%') {
if (C.remaining().startswith("%bb."))
return lexMachineBasicBlock(C, Token, ErrorCallback).remaining();
return lexPercent(C, Token).remaining();
}
if (isdigit(Char) || (Char == '-' && isdigit(C.peek(1))))
return lexIntegerLiteral(C, Token).remaining();
MIToken::TokenKind Kind = symbolToken(Char);
Expand Down
16 changes: 12 additions & 4 deletions llvm/lib/CodeGen/MIRParser/MILexer.h
Expand Up @@ -39,21 +39,25 @@ struct MIToken {
// Identifier tokens
Identifier,
NamedRegister,
MachineBasicBlock,

// Other tokens
IntegerLiteral
};

private:
TokenKind Kind;
unsigned StringOffset;
StringRef Range;
APSInt IntVal;

public:
MIToken(TokenKind Kind, StringRef Range) : Kind(Kind), Range(Range) {}
MIToken(TokenKind Kind, StringRef Range, unsigned StringOffset = 0)
: Kind(Kind), StringOffset(StringOffset), Range(Range) {}

MIToken(TokenKind Kind, StringRef Range, const APSInt &IntVal)
: Kind(Kind), Range(Range), IntVal(IntVal) {}
MIToken(TokenKind Kind, StringRef Range, const APSInt &IntVal,
unsigned StringOffset = 0)
: Kind(Kind), StringOffset(StringOffset), Range(Range), IntVal(IntVal) {}

TokenKind kind() const { return Kind; }

Expand All @@ -69,9 +73,13 @@ struct MIToken {

StringRef::iterator location() const { return Range.begin(); }

StringRef stringValue() const { return Range; }
StringRef stringValue() const { return Range.drop_front(StringOffset); }

const APSInt &integerValue() const { return IntVal; }

bool hasIntegerValue() const {
return Kind == IntegerLiteral || Kind == MachineBasicBlock;
}
};

/// Consume a single machine instruction token in the given source and return
Expand Down
56 changes: 49 additions & 7 deletions llvm/lib/CodeGen/MIRParser/MIParser.cpp
Expand Up @@ -32,14 +32,17 @@ class MIParser {
SMDiagnostic &Error;
StringRef Source, CurrentSource;
MIToken Token;
/// Maps from basic block numbers to MBBs.
const DenseMap<unsigned, MachineBasicBlock *> &MBBSlots;
/// 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,
StringRef Source);
StringRef Source,
const DenseMap<unsigned, MachineBasicBlock *> &MBBSlots);

void lex();

Expand All @@ -58,9 +61,15 @@ class MIParser {
bool parseRegister(unsigned &Reg);
bool parseRegisterOperand(MachineOperand &Dest, bool IsDef = false);
bool parseImmediateOperand(MachineOperand &Dest);
bool parseMBBOperand(MachineOperand &Dest);
bool parseMachineOperand(MachineOperand &Dest);

private:
/// Convert the integer literal in the current token into an unsigned integer.
///
/// Return true if an error occurred.
bool getUnsigned(unsigned &Result);

void initNames2InstrOpCodes();

/// Try to convert an instruction name to an opcode. Return true if the
Expand All @@ -79,9 +88,10 @@ class MIParser {
} // end anonymous namespace

MIParser::MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error,
StringRef Source)
StringRef Source,
const DenseMap<unsigned, MachineBasicBlock *> &MBBSlots)
: SM(SM), MF(MF), Error(Error), Source(Source), CurrentSource(Source),
Token(MIToken::Error, StringRef()) {}
Token(MIToken::Error, StringRef()), MBBSlots(MBBSlots) {}

void MIParser::lex() {
CurrentSource = lexMIToken(
Expand Down Expand Up @@ -178,7 +188,7 @@ bool MIParser::parseRegister(unsigned &Reg) {
Reg = 0;
break;
case MIToken::NamedRegister: {
StringRef Name = Token.stringValue().drop_front(1); // Drop the '%'
StringRef Name = Token.stringValue();
if (getRegisterByName(Name, Reg))
return error(Twine("unknown register name '") + Name + "'");
break;
Expand Down Expand Up @@ -212,13 +222,43 @@ bool MIParser::parseImmediateOperand(MachineOperand &Dest) {
return false;
}

bool MIParser::getUnsigned(unsigned &Result) {
assert(Token.hasIntegerValue() && "Expected a token with an integer value");
const uint64_t Limit = uint64_t(std::numeric_limits<unsigned>::max()) + 1;
uint64_t Val64 = Token.integerValue().getLimitedValue(Limit);
if (Val64 == Limit)
return error("expected 32-bit integer (too large)");
Result = Val64;
return false;
}

bool MIParser::parseMBBOperand(MachineOperand &Dest) {
assert(Token.is(MIToken::MachineBasicBlock));
unsigned Number;
if (getUnsigned(Number))
return true;
auto MBBInfo = MBBSlots.find(Number);
if (MBBInfo == MBBSlots.end())
return error(Twine("use of undefined machine basic block #") +
Twine(Number));
MachineBasicBlock *MBB = MBBInfo->second;
if (!Token.stringValue().empty() && Token.stringValue() != MBB->getName())
return error(Twine("the name of machine basic block #") + Twine(Number) +
" isn't '" + Token.stringValue() + "'");
Dest = MachineOperand::CreateMBB(MBB);
lex();
return false;
}

bool MIParser::parseMachineOperand(MachineOperand &Dest) {
switch (Token.kind()) {
case MIToken::underscore:
case MIToken::NamedRegister:
return parseRegisterOperand(Dest);
case MIToken::IntegerLiteral:
return parseImmediateOperand(Dest);
case MIToken::MachineBasicBlock:
return parseMBBOperand(Dest);
case MIToken::Error:
return true;
default:
Expand Down Expand Up @@ -271,7 +311,9 @@ bool MIParser::getRegisterByName(StringRef RegName, unsigned &Reg) {
return false;
}

MachineInstr *llvm::parseMachineInstr(SourceMgr &SM, MachineFunction &MF,
StringRef Src, SMDiagnostic &Error) {
return MIParser(SM, MF, Error, Src).parse();
MachineInstr *
llvm::parseMachineInstr(SourceMgr &SM, MachineFunction &MF, StringRef Src,
const DenseMap<unsigned, MachineBasicBlock *> &MBBSlots,
SMDiagnostic &Error) {
return MIParser(SM, MF, Error, Src, MBBSlots).parse();
}
8 changes: 6 additions & 2 deletions llvm/lib/CodeGen/MIRParser/MIParser.h
Expand Up @@ -14,17 +14,21 @@
#ifndef LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H
#define LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"

namespace llvm {

class MachineBasicBlock;
class MachineInstr;
class MachineFunction;
class SMDiagnostic;
class SourceMgr;

MachineInstr *parseMachineInstr(SourceMgr &SM, MachineFunction &MF,
StringRef Src, SMDiagnostic &Error);
MachineInstr *
parseMachineInstr(SourceMgr &SM, MachineFunction &MF, StringRef Src,
const DenseMap<unsigned, MachineBasicBlock *> &MBBSlots,
SMDiagnostic &Error);

} // end namespace llvm

Expand Down
26 changes: 21 additions & 5 deletions llvm/lib/CodeGen/MIRParser/MIRParser.cpp
Expand Up @@ -14,6 +14,7 @@

#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "MIParser.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/STLExtras.h"
Expand Down Expand Up @@ -81,8 +82,10 @@ class MIRParserImpl {
/// Initialize the machine basic block using it's YAML representation.
///
/// Return true if an error occurred.
bool initializeMachineBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB,
const yaml::MachineBasicBlock &YamlMBB);
bool initializeMachineBasicBlock(
MachineFunction &MF, MachineBasicBlock &MBB,
const yaml::MachineBasicBlock &YamlMBB,
const DenseMap<unsigned, MachineBasicBlock *> &MBBSlots);

bool initializeRegisterInfo(MachineRegisterInfo &RegInfo,
const yaml::MachineFunction &YamlMF);
Expand Down Expand Up @@ -220,6 +223,7 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
return true;

const auto &F = *MF.getFunction();
DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
for (const auto &YamlMBB : YamlMF.BasicBlocks) {
const BasicBlock *BB = nullptr;
if (!YamlMBB.Name.empty()) {
Expand All @@ -231,23 +235,35 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
}
auto *MBB = MF.CreateMachineBasicBlock(BB);
MF.insert(MF.end(), MBB);
if (initializeMachineBasicBlock(MF, *MBB, YamlMBB))
bool WasInserted = MBBSlots.insert(std::make_pair(YamlMBB.ID, MBB)).second;
if (!WasInserted)
return error(Twine("redefinition of machine basic block with id #") +
Twine(YamlMBB.ID));
}

// Initialize the machine basic blocks after creating them all so that the
// machine instructions parser can resolve the MBB references.
unsigned I = 0;
for (const auto &YamlMBB : YamlMF.BasicBlocks) {
if (initializeMachineBasicBlock(MF, *MF.getBlockNumbered(I++), YamlMBB,
MBBSlots))
return true;
}
return false;
}

bool MIRParserImpl::initializeMachineBasicBlock(
MachineFunction &MF, MachineBasicBlock &MBB,
const yaml::MachineBasicBlock &YamlMBB) {
const yaml::MachineBasicBlock &YamlMBB,
const DenseMap<unsigned, MachineBasicBlock *> &MBBSlots) {
MBB.setAlignment(YamlMBB.Alignment);
if (YamlMBB.AddressTaken)
MBB.setHasAddressTaken();
MBB.setIsLandingPad(YamlMBB.IsLandingPad);
// Parse the instructions.
for (const auto &MISource : YamlMBB.Instructions) {
SMDiagnostic Error;
if (auto *MI = parseMachineInstr(SM, MF, MISource.Value, Error)) {
if (auto *MI = parseMachineInstr(SM, MF, MISource.Value, MBBSlots, Error)) {
MBB.insert(MBB.end(), MI);
continue;
}
Expand Down
17 changes: 17 additions & 0 deletions llvm/lib/CodeGen/MIRPrinter.cpp
Expand Up @@ -81,7 +81,15 @@ void MIRPrinter::print(const MachineFunction &MF) {
YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
YamlMF.HasInlineAsm = MF.hasInlineAsm();
convert(YamlMF, MF.getRegInfo());

int I = 0;
for (const auto &MBB : MF) {
// TODO: Allow printing of non sequentially numbered MBBs.
// This is currently needed as the basic block references get their index
// from MBB.getNumber(), thus it should be sequential so that the parser can
// map back to the correct MBBs when parsing the output.
assert(MBB.getNumber() == I++ &&
"Can't print MBBs that aren't sequentially numbered");
yaml::MachineBasicBlock YamlMBB;
convert(YamlMBB, MBB);
YamlMF.BasicBlocks.push_back(YamlMBB);
Expand All @@ -99,6 +107,8 @@ void MIRPrinter::convert(yaml::MachineFunction &MF,

void MIRPrinter::convert(yaml::MachineBasicBlock &YamlMBB,
const MachineBasicBlock &MBB) {
assert(MBB.getNumber() >= 0 && "Invalid MBB number");
YamlMBB.ID = (unsigned)MBB.getNumber();
// TODO: Serialize unnamed BB references.
if (const auto *BB = MBB.getBasicBlock())
YamlMBB.Name = BB->hasName() ? BB->getName() : "<unnamed bb>";
Expand Down Expand Up @@ -173,6 +183,13 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
case MachineOperand::MO_Immediate:
OS << Op.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
OS << "%bb." << Op.getMBB()->getNumber();
if (const auto *BB = Op.getMBB()->getBasicBlock()) {
if (BB->hasName())
OS << '.' << BB->getName();
}
break;
default:
// TODO: Print the other machine operands.
llvm_unreachable("Can't print this machine operand at the moment");
Expand Down
3 changes: 2 additions & 1 deletion llvm/test/CodeGen/MIR/X86/expected-machine-operand.mir
Expand Up @@ -11,7 +11,8 @@
---
name: foo
body:
- name: entry
- id: 0
name: entry
instructions:
# CHECK: [[@LINE+1]]:24: expected a machine operand
- '%eax = XOR32rr ='
Expand Down

0 comments on commit 33f0aef

Please sign in to comment.