mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 22:20:37 +00:00
full asmparser support for blockaddress. We can now do:
$ llvm-as foo.ll -d -disable-output which reads and prints the .ll file. BC encoding is the next project. Testcase will go in once that works. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85368 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
73050e1c38
commit
09d9ef4122
@ -576,6 +576,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(oge); KEYWORD(ord); KEYWORD(uno); KEYWORD(ueq); KEYWORD(une);
|
||||
|
||||
KEYWORD(x);
|
||||
KEYWORD(blockaddress);
|
||||
#undef KEYWORD
|
||||
|
||||
// Keywords for types.
|
||||
|
@ -29,34 +29,6 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
/// ValID - Represents a reference of a definition of some sort with no type.
|
||||
/// There are several cases where we have to parse the value but where the
|
||||
/// type can depend on later context. This may either be a numeric reference
|
||||
/// or a symbolic (%var) reference. This is just a discriminated union.
|
||||
struct ValID {
|
||||
enum {
|
||||
t_LocalID, t_GlobalID, // ID in UIntVal.
|
||||
t_LocalName, t_GlobalName, // Name in StrVal.
|
||||
t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal.
|
||||
t_Null, t_Undef, t_Zero, // No value.
|
||||
t_EmptyArray, // No value: []
|
||||
t_Constant, // Value in ConstantVal.
|
||||
t_InlineAsm, // Value in StrVal/StrVal2/UIntVal.
|
||||
t_Metadata // Value in MetadataVal.
|
||||
} Kind;
|
||||
|
||||
LLParser::LocTy Loc;
|
||||
unsigned UIntVal;
|
||||
std::string StrVal, StrVal2;
|
||||
APSInt APSIntVal;
|
||||
APFloat APFloatVal;
|
||||
Constant *ConstantVal;
|
||||
MetadataBase *MetadataVal;
|
||||
ValID() : APFloatVal(0.0) {}
|
||||
};
|
||||
}
|
||||
|
||||
/// Run: module ::= toplevelentity*
|
||||
bool LLParser::Run() {
|
||||
// Prime the lexer.
|
||||
@ -77,7 +49,7 @@ bool LLParser::ValidateEndOfModule() {
|
||||
// declaration of "malloc". In that case, iterate over all calls to MallocF
|
||||
// and get them to call the declared "malloc" instead.
|
||||
if (MallocF->getName() != "malloc") {
|
||||
Constant* RealMallocF = M->getFunction("malloc");
|
||||
Constant *RealMallocF = M->getFunction("malloc");
|
||||
if (RealMallocF->getType() != MallocF->getType())
|
||||
RealMallocF = ConstantExpr::getBitCast(RealMallocF, MallocF->getType());
|
||||
MallocF->replaceAllUsesWith(RealMallocF);
|
||||
@ -85,7 +57,32 @@ bool LLParser::ValidateEndOfModule() {
|
||||
MallocF = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// If there are entries in ForwardRefBlockAddresses at this point, they are
|
||||
// references after the function was defined. Resolve those now.
|
||||
while (!ForwardRefBlockAddresses.empty()) {
|
||||
// Okay, we are referencing an already-parsed function, resolve them now.
|
||||
Function *TheFn = 0;
|
||||
const ValID &Fn = ForwardRefBlockAddresses.begin()->first;
|
||||
if (Fn.Kind == ValID::t_GlobalName)
|
||||
TheFn = M->getFunction(Fn.StrVal);
|
||||
else if (Fn.UIntVal < NumberedVals.size())
|
||||
TheFn = dyn_cast<Function>(NumberedVals[Fn.UIntVal]);
|
||||
|
||||
if (TheFn == 0)
|
||||
return Error(Fn.Loc, "unknown function referenced by blockaddress");
|
||||
|
||||
// Resolve all these references.
|
||||
if (ResolveForwardRefBlockAddresses(TheFn,
|
||||
ForwardRefBlockAddresses.begin()->second,
|
||||
0))
|
||||
return true;
|
||||
|
||||
ForwardRefBlockAddresses.erase(ForwardRefBlockAddresses.begin());
|
||||
}
|
||||
|
||||
|
||||
if (!ForwardRefTypes.empty())
|
||||
return Error(ForwardRefTypes.begin()->second.second,
|
||||
"use of undefined type named '" +
|
||||
@ -120,6 +117,38 @@ bool LLParser::ValidateEndOfModule() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLParser::ResolveForwardRefBlockAddresses(Function *TheFn,
|
||||
std::vector<std::pair<ValID, GlobalValue*> > &Refs,
|
||||
PerFunctionState *PFS) {
|
||||
// Loop over all the references, resolving them.
|
||||
for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
|
||||
BasicBlock *Res;
|
||||
if (PFS) {
|
||||
if (Refs[i].first.Kind == ValID::t_LocalName)
|
||||
Res = PFS->GetBB(Refs[i].first.StrVal, Refs[i].first.Loc);
|
||||
else
|
||||
Res = PFS->GetBB(Refs[i].first.UIntVal, Refs[i].first.Loc);
|
||||
} else if (Refs[i].first.Kind == ValID::t_LocalID) {
|
||||
return Error(Refs[i].first.Loc,
|
||||
"cannot take address of numeric label after it the function is defined");
|
||||
} else {
|
||||
Res = dyn_cast_or_null<BasicBlock>(
|
||||
TheFn->getValueSymbolTable().lookup(Refs[i].first.StrVal));
|
||||
}
|
||||
|
||||
if (Res == 0)
|
||||
return Error(Refs[i].first.Loc,
|
||||
"referenced value is not a basic block");
|
||||
|
||||
// Get the BlockAddress for this and update references to use it.
|
||||
BlockAddress *BA = BlockAddress::get(TheFn, Res);
|
||||
Refs[i].second->replaceAllUsesWith(BA);
|
||||
Refs[i].second->eraseFromParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Top-Level Entities
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1575,8 +1604,9 @@ bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) {
|
||||
// Function Semantic Analysis.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
LLParser::PerFunctionState::PerFunctionState(LLParser &p, Function &f)
|
||||
: P(p), F(f) {
|
||||
LLParser::PerFunctionState::PerFunctionState(LLParser &p, Function &f,
|
||||
int functionNumber)
|
||||
: P(p), F(f), FunctionNumber(functionNumber) {
|
||||
|
||||
// Insert unnamed arguments into the NumberedVals list.
|
||||
for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end();
|
||||
@ -1606,7 +1636,29 @@ LLParser::PerFunctionState::~PerFunctionState() {
|
||||
}
|
||||
}
|
||||
|
||||
bool LLParser::PerFunctionState::VerifyFunctionComplete() {
|
||||
bool LLParser::PerFunctionState::FinishFunction() {
|
||||
// Check to see if someone took the address of labels in this block.
|
||||
if (!P.ForwardRefBlockAddresses.empty()) {
|
||||
ValID FunctionID;
|
||||
if (!F.getName().empty()) {
|
||||
FunctionID.Kind = ValID::t_GlobalName;
|
||||
FunctionID.StrVal = F.getName();
|
||||
} else {
|
||||
FunctionID.Kind = ValID::t_GlobalID;
|
||||
FunctionID.UIntVal = FunctionNumber;
|
||||
}
|
||||
|
||||
std::map<ValID, std::vector<std::pair<ValID, GlobalValue*> > >::iterator
|
||||
FRBAI = P.ForwardRefBlockAddresses.find(FunctionID);
|
||||
if (FRBAI != P.ForwardRefBlockAddresses.end()) {
|
||||
// Resolve all these references.
|
||||
if (P.ResolveForwardRefBlockAddresses(&F, FRBAI->second, this))
|
||||
return true;
|
||||
|
||||
P.ForwardRefBlockAddresses.erase(FRBAI);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ForwardRefVals.empty())
|
||||
return P.Error(ForwardRefVals.begin()->second.second,
|
||||
"use of undefined value '%" + ForwardRefVals.begin()->first +
|
||||
@ -1990,6 +2042,35 @@ bool LLParser::ParseValID(ValID &ID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
case lltok::kw_blockaddress: {
|
||||
// ValID ::= 'blockaddress' '(' @foo ',' %bar ')'
|
||||
Lex.Lex();
|
||||
|
||||
ValID Fn, Label;
|
||||
LocTy FnLoc, LabelLoc;
|
||||
|
||||
if (ParseToken(lltok::lparen, "expected '(' in block address expression") ||
|
||||
ParseValID(Fn) ||
|
||||
ParseToken(lltok::comma, "expected comma in block address expression")||
|
||||
ParseValID(Label) ||
|
||||
ParseToken(lltok::rparen, "expected ')' in block address expression"))
|
||||
return true;
|
||||
|
||||
if (Fn.Kind != ValID::t_GlobalID && Fn.Kind != ValID::t_GlobalName)
|
||||
return Error(Fn.Loc, "expected function name in blockaddress");
|
||||
if (Label.Kind != ValID::t_LocalID && Label.Kind != ValID::t_LocalName)
|
||||
return Error(Label.Loc, "expected basic block name in blockaddress");
|
||||
|
||||
// Make a global variable as a placeholder for this reference.
|
||||
GlobalVariable *FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context),
|
||||
false, GlobalValue::InternalLinkage,
|
||||
0, "");
|
||||
ForwardRefBlockAddresses[Fn].push_back(std::make_pair(Label, FwdRef));
|
||||
ID.ConstantVal = FwdRef;
|
||||
ID.Kind = ValID::t_Constant;
|
||||
return false;
|
||||
}
|
||||
|
||||
case lltok::kw_trunc:
|
||||
case lltok::kw_zext:
|
||||
case lltok::kw_sext:
|
||||
@ -2637,7 +2718,10 @@ bool LLParser::ParseFunctionBody(Function &Fn) {
|
||||
return TokError("expected '{' in function body");
|
||||
Lex.Lex(); // eat the {.
|
||||
|
||||
PerFunctionState PFS(*this, Fn);
|
||||
int FunctionNumber = -1;
|
||||
if (!Fn.hasName()) FunctionNumber = NumberedVals.size()-1;
|
||||
|
||||
PerFunctionState PFS(*this, Fn, FunctionNumber);
|
||||
|
||||
while (Lex.getKind() != lltok::rbrace && Lex.getKind() != lltok::kw_end)
|
||||
if (ParseBasicBlock(PFS)) return true;
|
||||
@ -2646,7 +2730,7 @@ bool LLParser::ParseFunctionBody(Function &Fn) {
|
||||
Lex.Lex();
|
||||
|
||||
// Verify function is ok.
|
||||
return PFS.VerifyFunctionComplete();
|
||||
return PFS.FinishFunction();
|
||||
}
|
||||
|
||||
/// ParseBasicBlock
|
||||
|
@ -31,8 +31,41 @@ namespace llvm {
|
||||
class MetadataBase;
|
||||
class MDString;
|
||||
class MDNode;
|
||||
struct ValID;
|
||||
|
||||
/// ValID - Represents a reference of a definition of some sort with no type.
|
||||
/// There are several cases where we have to parse the value but where the
|
||||
/// type can depend on later context. This may either be a numeric reference
|
||||
/// or a symbolic (%var) reference. This is just a discriminated union.
|
||||
struct ValID {
|
||||
enum {
|
||||
t_LocalID, t_GlobalID, // ID in UIntVal.
|
||||
t_LocalName, t_GlobalName, // Name in StrVal.
|
||||
t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal.
|
||||
t_Null, t_Undef, t_Zero, // No value.
|
||||
t_EmptyArray, // No value: []
|
||||
t_Constant, // Value in ConstantVal.
|
||||
t_InlineAsm, // Value in StrVal/StrVal2/UIntVal.
|
||||
t_Metadata // Value in MetadataVal.
|
||||
} Kind;
|
||||
|
||||
LLLexer::LocTy Loc;
|
||||
unsigned UIntVal;
|
||||
std::string StrVal, StrVal2;
|
||||
APSInt APSIntVal;
|
||||
APFloat APFloatVal;
|
||||
Constant *ConstantVal;
|
||||
MetadataBase *MetadataVal;
|
||||
ValID() : APFloatVal(0.0) {}
|
||||
|
||||
bool operator<(const ValID &RHS) const {
|
||||
if (Kind == t_LocalID || Kind == t_GlobalID)
|
||||
return UIntVal < RHS.UIntVal;
|
||||
assert((Kind == t_LocalName || Kind == t_GlobalName) &&
|
||||
"Ordering not defined for this ValID kind yet");
|
||||
return StrVal < RHS.StrVal;
|
||||
}
|
||||
};
|
||||
|
||||
class LLParser {
|
||||
public:
|
||||
typedef LLLexer::LocTy LocTy;
|
||||
@ -75,7 +108,13 @@ namespace llvm {
|
||||
std::map<std::string, std::pair<GlobalValue*, LocTy> > ForwardRefVals;
|
||||
std::map<unsigned, std::pair<GlobalValue*, LocTy> > ForwardRefValIDs;
|
||||
std::vector<GlobalValue*> NumberedVals;
|
||||
Function* MallocF;
|
||||
|
||||
// References to blockaddress. The key is the function ValID, the value is
|
||||
// a list of references to blocks in that function.
|
||||
std::map<ValID, std::vector<std::pair<ValID, GlobalValue*> > >
|
||||
ForwardRefBlockAddresses;
|
||||
|
||||
Function *MallocF;
|
||||
public:
|
||||
LLParser(MemoryBuffer *F, SourceMgr &SM, SMDiagnostic &Err, Module *m) :
|
||||
Context(m->getContext()), Lex(F, SM, Err, m->getContext()),
|
||||
@ -184,13 +223,17 @@ namespace llvm {
|
||||
std::map<std::string, std::pair<Value*, LocTy> > ForwardRefVals;
|
||||
std::map<unsigned, std::pair<Value*, LocTy> > ForwardRefValIDs;
|
||||
std::vector<Value*> NumberedVals;
|
||||
|
||||
/// FunctionNumber - If this is an unnamed function, this is the slot
|
||||
/// number of it, otherwise it is -1.
|
||||
int FunctionNumber;
|
||||
public:
|
||||
PerFunctionState(LLParser &p, Function &f);
|
||||
PerFunctionState(LLParser &p, Function &f, int FunctionNumber);
|
||||
~PerFunctionState();
|
||||
|
||||
Function &getFunction() const { return F; }
|
||||
|
||||
bool VerifyFunctionComplete();
|
||||
bool FinishFunction();
|
||||
|
||||
/// GetVal - Get a value with the specified name or ID, creating a
|
||||
/// forward reference record if needed. This can return null if the value
|
||||
@ -294,6 +337,10 @@ namespace llvm {
|
||||
bool ParseGetElementPtr(Instruction *&I, PerFunctionState &PFS);
|
||||
bool ParseExtractValue(Instruction *&I, PerFunctionState &PFS);
|
||||
bool ParseInsertValue(Instruction *&I, PerFunctionState &PFS);
|
||||
|
||||
bool ResolveForwardRefBlockAddresses(Function *TheFn,
|
||||
std::vector<std::pair<ValID, GlobalValue*> > &Refs,
|
||||
PerFunctionState *PFS);
|
||||
};
|
||||
} // End llvm namespace
|
||||
|
||||
|
@ -117,7 +117,7 @@ namespace lltok {
|
||||
kw_malloc, kw_alloca, kw_free, kw_load, kw_store, kw_getelementptr,
|
||||
|
||||
kw_extractelement, kw_insertelement, kw_shufflevector, kw_getresult,
|
||||
kw_extractvalue, kw_insertvalue,
|
||||
kw_extractvalue, kw_insertvalue, kw_blockaddress,
|
||||
|
||||
// Unsigned Valued tokens (UIntVal).
|
||||
GlobalID, // @42
|
||||
|
Loading…
Reference in New Issue
Block a user