diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index f95110e57c6..1b7c9c6d04c 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -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. diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index aba02648e89..07bf261573c 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -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(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 > &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( + 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 > >::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 diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index ca2e2b695f8..d60bceacb67 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -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 > ForwardRefVals; std::map > ForwardRefValIDs; std::vector 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 > > + 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 > ForwardRefVals; std::map > ForwardRefValIDs; std::vector 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 > &Refs, + PerFunctionState *PFS); }; } // End llvm namespace diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index d6efaf4d448..797c32ea67c 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -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