diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -126,7 +126,9 @@ // References to blockaddress. The key is the function ValID, the value is // a list of references to blocks in that function. - std::map> ForwardRefBlockAddresses; + std::map> ForwardRefBlockAddressNames; + std::map> ForwardRefBlockAddressIDs; + class PerFunctionState; /// Reference to per-function state to allow basic blocks to be /// forward-referenced by blockaddress instructions within the same diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -211,10 +211,13 @@ } } - // If there are entries in ForwardRefBlockAddresses at this point, the - // function was never defined. - if (!ForwardRefBlockAddresses.empty()) - return error(ForwardRefBlockAddresses.begin()->first.Loc, + // If there are entries in ForwardRefBlockAddress{Names,IDs} at this + // point, the function was never defined. + if (!ForwardRefBlockAddressNames.empty()) + return error(ForwardRefBlockAddressNames.begin()->first.Loc, + "expected function name in blockaddress"); + if (!ForwardRefBlockAddressIDs.empty()) + return error(ForwardRefBlockAddressIDs.begin()->first.Loc, "expected function name in blockaddress"); auto ResolveForwardRefDSOLocalEquivalents = [&](const ValID &GVRef, @@ -3478,11 +3481,15 @@ } if (!F) { + auto &forwardRefBlockAddresses = Label.Kind == ValID::t_LocalName + ? ForwardRefBlockAddressNames + : ForwardRefBlockAddressIDs; + // Make a global variable as a placeholder for this reference. GlobalValue *&FwdRef = - ForwardRefBlockAddresses.insert(std::make_pair( - std::move(Fn), - std::map())) + forwardRefBlockAddresses + .insert(std::make_pair(std::move(Fn), + std::map())) .first->second.insert(std::make_pair(std::move(Label), nullptr)) .first->second; if (!FwdRef) { @@ -5939,10 +5946,16 @@ ID.Kind = ValID::t_GlobalName; ID.StrVal = FunctionName; } - auto Blocks = ForwardRefBlockAddresses.find(ID); - if (Blocks != ForwardRefBlockAddresses.end()) + + auto Blocks = ForwardRefBlockAddressNames.find(ID); + if (Blocks != ForwardRefBlockAddressNames.end()) return error(Blocks->first.Loc, "cannot take blockaddress inside a declaration"); + Blocks = ForwardRefBlockAddressIDs.find(ID); + if (Blocks != ForwardRefBlockAddressIDs.end()) + return error(Blocks->first.Loc, + "cannot take blockaddress inside a declaration"); + return false; } @@ -5956,35 +5969,41 @@ ID.UIntVal = FunctionNumber; } - auto Blocks = P.ForwardRefBlockAddresses.find(ID); - if (Blocks == P.ForwardRefBlockAddresses.end()) - return false; + auto ResolveForwardRefBlockAddresses = [&](auto &forwardRefBlockAddresses) { + auto Blocks = forwardRefBlockAddresses.find(ID); + if (Blocks == forwardRefBlockAddresses.end()) + return false; - for (const auto &I : Blocks->second) { - const ValID &BBID = I.first; - GlobalValue *GV = I.second; + for (const auto &I : Blocks->second) { + const ValID &BBID = I.first; + GlobalValue *GV = I.second; - assert((BBID.Kind == ValID::t_LocalID || BBID.Kind == ValID::t_LocalName) && - "Expected local id or name"); - BasicBlock *BB; - if (BBID.Kind == ValID::t_LocalName) - BB = getBB(BBID.StrVal, BBID.Loc); - else - BB = getBB(BBID.UIntVal, BBID.Loc); - if (!BB) - return P.error(BBID.Loc, "referenced value is not a basic block"); - - Value *ResolvedVal = BlockAddress::get(&F, BB); - ResolvedVal = P.checkValidVariableType(BBID.Loc, BBID.StrVal, GV->getType(), - ResolvedVal); - if (!ResolvedVal) - return true; - GV->replaceAllUsesWith(ResolvedVal); - GV->eraseFromParent(); - } + assert( + (BBID.Kind == ValID::t_LocalID || BBID.Kind == ValID::t_LocalName) && + "Expected local id or name"); + BasicBlock *BB; + if (BBID.Kind == ValID::t_LocalName) + BB = getBB(BBID.StrVal, BBID.Loc); + else + BB = getBB(BBID.UIntVal, BBID.Loc); + if (!BB) + return P.error(BBID.Loc, "referenced value is not a basic block"); - P.ForwardRefBlockAddresses.erase(Blocks); - return false; + Value *ResolvedVal = BlockAddress::get(&F, BB); + ResolvedVal = P.checkValidVariableType(BBID.Loc, BBID.StrVal, + GV->getType(), ResolvedVal); + if (!ResolvedVal) + return true; + GV->replaceAllUsesWith(ResolvedVal); + GV->eraseFromParent(); + } + + forwardRefBlockAddresses.erase(Blocks); + return false; + }; + + return ResolveForwardRefBlockAddresses(P.ForwardRefBlockAddressNames) || + ResolveForwardRefBlockAddresses(P.ForwardRefBlockAddressIDs); } /// parseFunctionBody diff --git a/llvm/test/Bitcode/blockaddress-forwardref.ll b/llvm/test/Bitcode/blockaddress-forwardref.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/blockaddress-forwardref.ll @@ -0,0 +1,14 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s +; RUN: verify-uselistorder < %s + +; CHECK: i8* blockaddress(@f, %0), i8* blockaddress(@f, %bb) +@g = global [2 x i8*] [i8* blockaddress(@f, %0), i8* blockaddress(@f, %bb)] + +define void @f() { +entry: + br label %bb +bb: + br label %0 +; %0 + ret void +}