MIR Serialization: Serialize the block address machine operands.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243453 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Alex Lorenz
2015-07-28 17:28:03 +00:00
parent 6b43809281
commit 6d0376c00c
10 changed files with 373 additions and 4 deletions

View File

@@ -147,6 +147,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
.Case(".cfi_offset", MIToken::kw_cfi_offset) .Case(".cfi_offset", MIToken::kw_cfi_offset)
.Case(".cfi_def_cfa_register", MIToken::kw_cfi_def_cfa_register) .Case(".cfi_def_cfa_register", MIToken::kw_cfi_def_cfa_register)
.Case(".cfi_def_cfa_offset", MIToken::kw_cfi_def_cfa_offset) .Case(".cfi_def_cfa_offset", MIToken::kw_cfi_def_cfa_offset)
.Case("blockaddress", MIToken::kw_blockaddress)
.Default(MIToken::Identifier); .Default(MIToken::Identifier);
} }
@@ -239,8 +240,16 @@ static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) {
return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem); return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem);
} }
static Cursor maybeLexIRBlock(Cursor C, MIToken &Token) { static Cursor maybeLexIRBlock(
return maybeLexIndex(C, Token, "%ir-block.", MIToken::IRBlock); Cursor C, MIToken &Token,
function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
const StringRef Rule = "%ir-block.";
if (!C.remaining().startswith(Rule))
return None;
if (isdigit(C.peek(Rule.size())))
return maybeLexIndex(C, Token, Rule, MIToken::IRBlock);
return lexName(C, Token, MIToken::NamedIRBlock, MIToken::QuotedNamedIRBlock,
Rule.size(), ErrorCallback);
} }
static Cursor lexVirtualRegister(Cursor C, MIToken &Token) { static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
@@ -319,6 +328,10 @@ static MIToken::TokenKind symbolToken(char C) {
return MIToken::colon; return MIToken::colon;
case '!': case '!':
return MIToken::exclaim; return MIToken::exclaim;
case '(':
return MIToken::lparen;
case ')':
return MIToken::rparen;
default: default:
return MIToken::Error; return MIToken::Error;
} }
@@ -355,7 +368,7 @@ StringRef llvm::lexMIToken(
return R.remaining(); return R.remaining();
if (Cursor R = maybeLexConstantPoolItem(C, Token)) if (Cursor R = maybeLexConstantPoolItem(C, Token))
return R.remaining(); return R.remaining();
if (Cursor R = maybeLexIRBlock(C, Token)) if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback))
return R.remaining(); return R.remaining();
if (Cursor R = maybeLexRegister(C, Token)) if (Cursor R = maybeLexRegister(C, Token))
return R.remaining(); return R.remaining();

View File

@@ -37,6 +37,8 @@ struct MIToken {
underscore, underscore,
colon, colon,
exclaim, exclaim,
lparen,
rparen,
// Keywords // Keywords
kw_implicit, kw_implicit,
@@ -49,6 +51,7 @@ struct MIToken {
kw_cfi_offset, kw_cfi_offset,
kw_cfi_def_cfa_register, kw_cfi_def_cfa_register,
kw_cfi_def_cfa_offset, kw_cfi_def_cfa_offset,
kw_blockaddress,
// Identifier tokens // Identifier tokens
Identifier, Identifier,
@@ -67,6 +70,8 @@ struct MIToken {
VirtualRegister, VirtualRegister,
ConstantPoolItem, ConstantPoolItem,
JumpTableIndex, JumpTableIndex,
NamedIRBlock,
QuotedNamedIRBlock,
IRBlock, IRBlock,
}; };
@@ -105,7 +110,8 @@ public:
StringRef::iterator location() const { return Range.begin(); } StringRef::iterator location() const { return Range.begin(); }
bool isStringValueQuoted() const { bool isStringValueQuoted() const {
return Kind == QuotedNamedGlobalValue || Kind == QuotedExternalSymbol; return Kind == QuotedNamedGlobalValue || Kind == QuotedExternalSymbol ||
Kind == QuotedNamedIRBlock;
} }
/// Return the token's raw string value. /// Return the token's raw string value.

View File

@@ -22,8 +22,10 @@
#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h" #include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h" #include "llvm/Support/SourceMgr.h"
#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Target/TargetSubtargetInfo.h"
@@ -123,6 +125,8 @@ public:
bool parseCFIOffset(int &Offset); bool parseCFIOffset(int &Offset);
bool parseCFIRegister(unsigned &Reg); bool parseCFIRegister(unsigned &Reg);
bool parseCFIOperand(MachineOperand &Dest); bool parseCFIOperand(MachineOperand &Dest);
bool parseIRBlock(BasicBlock *&BB, const Function &F);
bool parseBlockAddressOperand(MachineOperand &Dest);
bool parseMachineOperand(MachineOperand &Dest); bool parseMachineOperand(MachineOperand &Dest);
private: private:
@@ -200,6 +204,10 @@ static const char *toString(MIToken::TokenKind TokenKind) {
switch (TokenKind) { switch (TokenKind) {
case MIToken::comma: case MIToken::comma:
return "','"; return "','";
case MIToken::lparen:
return "'('";
case MIToken::rparen:
return "')'";
default: default:
return "<unknown token>"; return "<unknown token>";
} }
@@ -741,6 +749,65 @@ bool MIParser::parseCFIOperand(MachineOperand &Dest) {
return false; return false;
} }
bool MIParser::parseIRBlock(BasicBlock *&BB, const Function &F) {
switch (Token.kind()) {
case MIToken::NamedIRBlock:
case MIToken::QuotedNamedIRBlock: {
StringValueUtility Name(Token);
BB = dyn_cast_or_null<BasicBlock>(F.getValueSymbolTable().lookup(Name));
if (!BB)
return error(Twine("use of undefined IR block '%ir-block.") +
Token.rawStringValue() + "'");
break;
}
case MIToken::IRBlock: {
unsigned SlotNumber = 0;
if (getUnsigned(SlotNumber))
return true;
BB = const_cast<BasicBlock *>(getIRBlock(SlotNumber));
if (!BB)
return error(Twine("use of undefined IR block '%ir-block.") +
Twine(SlotNumber) + "'");
break;
}
default:
llvm_unreachable("The current token should be an IR block reference");
}
return false;
}
bool MIParser::parseBlockAddressOperand(MachineOperand &Dest) {
assert(Token.is(MIToken::kw_blockaddress));
lex();
if (expectAndConsume(MIToken::lparen))
return true;
if (Token.isNot(MIToken::GlobalValue) &&
Token.isNot(MIToken::NamedGlobalValue) &&
Token.isNot(MIToken::QuotedNamedGlobalValue))
return error("expected a global value");
GlobalValue *GV = nullptr;
if (parseGlobalValue(GV))
return true;
auto *F = dyn_cast<Function>(GV);
if (!F)
return error("expected an IR function reference");
lex();
if (expectAndConsume(MIToken::comma))
return true;
BasicBlock *BB = nullptr;
if (Token.isNot(MIToken::IRBlock) && Token.isNot(MIToken::NamedIRBlock) &&
Token.isNot(MIToken::QuotedNamedIRBlock))
return error("expected an IR block reference");
if (parseIRBlock(BB, *F))
return true;
lex();
if (expectAndConsume(MIToken::rparen))
return true;
// TODO: parse offset and target flags.
Dest = MachineOperand::CreateBA(BlockAddress::get(F, BB), /*Offset=*/0);
return false;
}
bool MIParser::parseMachineOperand(MachineOperand &Dest) { bool MIParser::parseMachineOperand(MachineOperand &Dest) {
switch (Token.kind()) { switch (Token.kind()) {
case MIToken::kw_implicit: case MIToken::kw_implicit:
@@ -777,6 +844,8 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest) {
case MIToken::kw_cfi_def_cfa_register: case MIToken::kw_cfi_def_cfa_register:
case MIToken::kw_cfi_def_cfa_offset: case MIToken::kw_cfi_def_cfa_offset:
return parseCFIOperand(Dest); return parseCFIOperand(Dest);
case MIToken::kw_blockaddress:
return parseBlockAddressOperand(Dest);
case MIToken::Error: case MIToken::Error:
return true; return true;
case MIToken::Identifier: case MIToken::Identifier:

View File

@@ -21,6 +21,7 @@
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MIRYamlMapping.h" #include "llvm/CodeGen/MIRYamlMapping.h"
#include "llvm/IR/BasicBlock.h" #include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
@@ -103,6 +104,7 @@ public:
void print(const MachineInstr &MI); void print(const MachineInstr &MI);
void printMBBReference(const MachineBasicBlock &MBB); void printMBBReference(const MachineBasicBlock &MBB);
void printIRBlockReference(const BasicBlock &BB);
void printStackObjectReference(int FrameIndex); void printStackObjectReference(int FrameIndex);
void print(const MachineOperand &Op, const TargetRegisterInfo *TRI); void print(const MachineOperand &Op, const TargetRegisterInfo *TRI);
@@ -428,6 +430,19 @@ void MIPrinter::printMBBReference(const MachineBasicBlock &MBB) {
} }
} }
void MIPrinter::printIRBlockReference(const BasicBlock &BB) {
OS << "%ir-block.";
if (BB.hasName()) {
printLLVMNameWithoutPrefix(OS, BB.getName());
return;
}
int Slot = MST.getLocalSlot(&BB);
if (Slot == -1)
OS << "<badref>";
else
OS << Slot;
}
void MIPrinter::printStackObjectReference(int FrameIndex) { void MIPrinter::printStackObjectReference(int FrameIndex) {
auto ObjectInfo = StackObjectOperandMapping.find(FrameIndex); auto ObjectInfo = StackObjectOperandMapping.find(FrameIndex);
assert(ObjectInfo != StackObjectOperandMapping.end() && assert(ObjectInfo != StackObjectOperandMapping.end() &&
@@ -485,6 +500,15 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST); Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST);
// TODO: Print offset and target flags. // TODO: Print offset and target flags.
break; break;
case MachineOperand::MO_BlockAddress:
OS << "blockaddress(";
Op.getBlockAddress()->getFunction()->printAsOperand(OS, /*PrintType=*/false,
MST);
OS << ", ";
printIRBlockReference(*Op.getBlockAddress()->getBasicBlock());
OS << ')';
// TODO: Print offset and target flags.
break;
case MachineOperand::MO_RegisterMask: { case MachineOperand::MO_RegisterMask: {
auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask()); auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask());
if (RegMaskInfo != RegisterMaskIds.end()) if (RegMaskInfo != RegisterMaskIds.end())

View File

@@ -0,0 +1,89 @@
# 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 the block address operands
# correctly.
--- |
@addr = global i8* null
define void @test() {
entry:
store volatile i8* blockaddress(@test, %block), i8** @addr
%val = load volatile i8*, i8** @addr
indirectbr i8* %val, [label %block]
block:
ret void
}
define void @test2() {
entry:
store volatile i8* blockaddress(@test2, %"quoted block"), i8** @addr
%val = load volatile i8*, i8** @addr
indirectbr i8* %val, [label %"quoted block"]
"quoted block":
ret void
}
define void @test3() {
entry:
store volatile i8* blockaddress(@test3, %0), i8** @addr
%val = load volatile i8*, i8** @addr
indirectbr i8* %val, [label %0]
ret void
}
...
---
name: test
body:
- id: 0
name: entry
successors: [ '%bb.1.block' ]
instructions:
# CHECK: %rax = LEA64r %rip, 1, _, blockaddress(@test, %ir-block.block), _
- '%rax = LEA64r %rip, 1, _, blockaddress(@test, %ir-block.block), _'
- 'MOV64mr %rip, 1, _, @addr, _, killed %rax'
- 'JMP64m %rip, 1, _, @addr, _'
- id: 1
name: block
addressTaken: true
instructions:
- RETQ
...
---
name: test2
tracksRegLiveness: true
body:
- id: 0
name: entry
successors: [ '%bb.1' ]
instructions:
# CHECK: %rax = LEA64r %rip, 1, _, blockaddress(@test2, %ir-block."quoted block"), _
- '%rax = LEA64r %rip, 1, _, blockaddress(@test2, %ir-block."quoted block"), _'
- 'MOV64mr %rip, 1, _, @addr, _, killed %rax'
- 'JMP64m %rip, 1, _, @addr, _'
- id: 1
addressTaken: true
instructions:
- RETQ
...
---
name: test3
tracksRegLiveness: true
body:
- id: 0
name: entry
successors: [ '%bb.1' ]
instructions:
# CHECK: %rax = LEA64r %rip, 1, _, blockaddress(@test3, %ir-block.0), _
- '%rax = LEA64r %rip, 1, _, blockaddress(@test3, %ir-block.0), _'
- 'MOV64mr %rip, 1, _, @addr, _, killed %rax'
- 'JMP64m %rip, 1, _, @addr, _'
- id: 1
addressTaken: true
instructions:
- RETQ
...

View File

@@ -0,0 +1,34 @@
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
--- |
@addr = global i8* null
define void @test() {
entry:
store volatile i8* blockaddress(@test, %block), i8** @addr
%val = load volatile i8*, i8** @addr
indirectbr i8* %val, [label %block]
block:
ret void
}
...
---
name: test
body:
- id: 0
name: entry
successors: [ '%bb.1.block' ]
instructions:
# CHECK: [[@LINE+1]]:56: expected an IR block reference
- '%rax = LEA64r %rip, 1, _, blockaddress(@test, _), _'
- 'MOV64mr %rip, 1, _, @addr, _, killed %rax'
- 'JMP64m %rip, 1, _, @addr, _'
- id: 1
name: block
addressTaken: true
instructions:
- RETQ
...

View File

@@ -0,0 +1,34 @@
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
--- |
@addr = global i8* null
define void @test() {
entry:
store volatile i8* blockaddress(@test, %block), i8** @addr
%val = load volatile i8*, i8** @addr
indirectbr i8* %val, [label %block]
block:
ret void
}
...
---
name: test
body:
- id: 0
name: entry
successors: [ '%bb.1.block' ]
instructions:
# CHECK: [[@LINE+1]]:49: expected an IR function reference
- '%rax = LEA64r %rip, 1, _, blockaddress(@addr, %ir-block.block), _'
- 'MOV64mr %rip, 1, _, @addr, _, killed %rax'
- 'JMP64m %rip, 1, _, @addr, _'
- id: 1
name: block
addressTaken: true
instructions:
- RETQ
...

View File

@@ -0,0 +1,34 @@
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
--- |
@addr = global i8* null
define void @test() {
entry:
store volatile i8* blockaddress(@test, %block), i8** @addr
%val = load volatile i8*, i8** @addr
indirectbr i8* %val, [label %block]
block:
ret void
}
...
---
name: test
body:
- id: 0
name: entry
successors: [ '%bb.1.block' ]
instructions:
# CHECK: [[@LINE+1]]:49: expected a global value
- '%rax = LEA64r %rip, 1, _, blockaddress(0, %ir-block.block), _'
- 'MOV64mr %rip, 1, _, @addr, _, killed %rax'
- 'JMP64m %rip, 1, _, @addr, _'
- id: 1
name: block
addressTaken: true
instructions:
- RETQ
...

View File

@@ -0,0 +1,34 @@
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
--- |
@addr = global i8* null
define void @test() {
entry:
store volatile i8* blockaddress(@test, %block), i8** @addr
%val = load volatile i8*, i8** @addr
indirectbr i8* %val, [label %block]
block:
ret void
}
...
---
name: test
body:
- id: 0
name: entry
successors: [ '%bb.1.block' ]
instructions:
# CHECK: [[@LINE+1]]:56: use of undefined IR block '%ir-block."block "'
- '%rax = LEA64r %rip, 1, _, blockaddress(@test, %ir-block."block "), _'
- 'MOV64mr %rip, 1, _, @addr, _, killed %rax'
- 'JMP64m %rip, 1, _, @addr, _'
- id: 1
name: block
addressTaken: true
instructions:
- RETQ
...

View File

@@ -0,0 +1,32 @@
# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
--- |
@addr = global i8* null
define void @test() {
entry:
store volatile i8* blockaddress(@test, %0), i8** @addr
%val = load volatile i8*, i8** @addr
indirectbr i8* %val, [label %0]
ret void
}
...
---
name: test
body:
- id: 0
name: entry
successors: [ '%bb.1' ]
instructions:
# CHECK: [[@LINE+1]]:56: use of undefined IR block '%ir-block.1'
- '%rax = LEA64r %rip, 1, _, blockaddress(@test, %ir-block.1), _'
- 'MOV64mr %rip, 1, _, @addr, _, killed %rax'
- 'JMP64m %rip, 1, _, @addr, _'
- id: 1
addressTaken: true
instructions:
- RETQ
...