Commit ac7d7344 by Karl Schimpf

Fix translator handling of basic block indices.

The code used to use a vector to hold basic blocks associated with indices. This had two problem: 1) The "number of blocks" record would generate a vector of the given size (even if very large); and 2) Indices would expand the vector to define the index (even if very large). In most cases, such large values are incorrect. To fix this, this patch uses a map from block index, to the corresponding basic block. Only after all basic block indices have been processed, we check that the size makes sense, and convert it to a vector. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4261 R=jpp@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/1275953002 .
parent 2c862522
...@@ -61,6 +61,12 @@ CfgNode *Cfg::makeNode() { ...@@ -61,6 +61,12 @@ CfgNode *Cfg::makeNode() {
return Node; return Node;
} }
void Cfg::swapNodes(NodeList &NewNodes) {
Nodes.swap(NewNodes);
for (SizeT I = 0, NumNodes = getNumNodes(); I < NumNodes; ++I)
Nodes[I]->resetIndex(I);
}
void Cfg::addArg(Variable *Arg) { void Cfg::addArg(Variable *Arg) {
Arg->setIsArg(); Arg->setIsArg();
Args.push_back(Arg); Args.push_back(Arg);
...@@ -358,14 +364,14 @@ void Cfg::reorderNodes() { ...@@ -358,14 +364,14 @@ void Cfg::reorderNodes() {
} }
// Reorder Nodes according to the built-up lists. // Reorder Nodes according to the built-up lists.
SizeT OldSize = Nodes.size(); NodeList Reordered;
(void)OldSize; Reordered.reserve(Placed.size() + Unreachable.size());
Nodes.clear();
for (CfgNode *Node : Placed) for (CfgNode *Node : Placed)
Nodes.push_back(Node); Reordered.push_back(Node);
for (CfgNode *Node : Unreachable) for (CfgNode *Node : Unreachable)
Nodes.push_back(Node); Reordered.push_back(Node);
assert(Nodes.size() == OldSize); assert(getNumNodes() == Reordered.size());
swapNodes(Reordered);
} }
namespace { namespace {
...@@ -400,15 +406,14 @@ void Cfg::shuffleNodes() { ...@@ -400,15 +406,14 @@ void Cfg::shuffleNodes() {
if (ToVisit[Node->getIndex()]) if (ToVisit[Node->getIndex()])
Unreachable.push_back(Node); Unreachable.push_back(Node);
// Copy the layout list to the Nodes. // Copy the layout list to the Nodes.
SizeT OldSize = Nodes.size(); NodeList Shuffled;
(void)OldSize; Shuffled.reserve(ReversedReachable.size() + Unreachable.size());
Nodes.clear();
for (CfgNode *Node : reverse_range(ReversedReachable)) for (CfgNode *Node : reverse_range(ReversedReachable))
Nodes.emplace_back(Node); Shuffled.push_back(Node);
for (CfgNode *Node : Unreachable) { for (CfgNode *Node : Unreachable)
Nodes.emplace_back(Node); Shuffled.push_back(Node);
} assert(Nodes.size() == Shuffled.size());
assert(Nodes.size() == OldSize); swapNodes(Shuffled);
dump("After basic block shuffling"); dump("After basic block shuffling");
} }
......
...@@ -90,6 +90,8 @@ public: ...@@ -90,6 +90,8 @@ public:
CfgNode *makeNode(); CfgNode *makeNode();
SizeT getNumNodes() const { return Nodes.size(); } SizeT getNumNodes() const { return Nodes.size(); }
const NodeList &getNodes() const { return Nodes; } const NodeList &getNodes() const { return Nodes; }
/// Swap nodes of Cfg with given list of nodes.
void swapNodes(NodeList &NewNodes);
/// @} /// @}
typedef int32_t IdentifierIndexType; typedef int32_t IdentifierIndexType;
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <system_error> #include <system_error>
#include <unordered_map>
#include <vector> #include <vector>
namespace Ice { namespace Ice {
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <algorithm> // max() #include <algorithm> // max()
#include <cctype> // isdigit(), isupper() #include <cctype> // isdigit(), isupper()
#include <locale> // locale #include <locale> // locale
#include <unordered_map>
namespace std { namespace std {
template <> struct hash<Ice::RelocatableTuple> { template <> struct hash<Ice::RelocatableTuple> {
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include "IceTargetLowering.h" #include "IceTargetLowering.h"
#include <type_traits> #include <type_traits>
#include <unordered_map>
#include <utility> #include <utility>
namespace Ice { namespace Ice {
......
...@@ -1215,7 +1215,8 @@ public: ...@@ -1215,7 +1215,8 @@ public:
Func->setFunctionName(FuncDecl->getName()); Func->setFunctionName(FuncDecl->getName());
Func->setReturnType(Signature.getReturnType()); Func->setReturnType(Signature.getReturnType());
Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage); Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage);
CurrentNode = installNextBasicBlock(); constexpr NaClBcIndexSize_t EntryBlock = 0;
CurrentNode = getBasicBlock(EntryBlock);
Func->setEntryNode(CurrentNode); Func->setEntryNode(CurrentNode);
for (Ice::Type ArgType : Signature.getArgList()) { for (Ice::Type ArgType : Signature.getArgList()) {
Func->addArg(getNextInstVar(ArgType)); Func->addArg(getNextInstVar(ArgType));
...@@ -1283,14 +1284,30 @@ public: ...@@ -1283,14 +1284,30 @@ public:
return Op; return Op;
} }
// Returns the Index-th basic block in the list of basic blocks.
Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) {
assert(!isIRGenerationDisabled());
Ice::CfgNode *&Node = BbMap[Index];
if (Node == nullptr)
Node = Func->makeNode();
return Node;
}
private: private:
typedef std::unordered_map<NaClBcIndexSize_t, Ice::CfgNode *> CfgNodeMap;
Ice::TimerMarker Timer; Ice::TimerMarker Timer;
// The corresponding ICE function defined by the function block. // The corresponding ICE function defined by the function block.
std::unique_ptr<Ice::Cfg> Func; std::unique_ptr<Ice::Cfg> Func;
// The specified number of basic blocks in the bitcode file.
NaClBcIndexSize_t SpecifiedNumBbs = 0;
// The index to the current basic block being built. // The index to the current basic block being built.
NaClBcIndexSize_t CurrentBbIndex = 0; NaClBcIndexSize_t CurrentBbIndex = 0;
// The basic block being built. // The basic block being built.
Ice::CfgNode *CurrentNode = nullptr; Ice::CfgNode *CurrentNode = nullptr;
// Map from basic block id (as defined in the bitcode file) to
// the corresponding basic block that implements it.
CfgNodeMap BbMap;
// The ID for the function. // The ID for the function.
NaClBcIndexSize_t FcnId; NaClBcIndexSize_t FcnId;
// The corresponding function declaration. // The corresponding function declaration.
...@@ -1333,27 +1350,7 @@ private: ...@@ -1333,27 +1350,7 @@ private:
void ExitBlock() override; void ExitBlock() override;
// Creates and appends a new basic block to the list of basic blocks. bool verifyAndRenameBasicBlocks();
Ice::CfgNode *installNextBasicBlock() {
assert(!isIRGenerationDisabled());
return Func->makeNode();
}
// Returns the Index-th basic block in the list of basic blocks.
Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) {
assert(!isIRGenerationDisabled());
const Ice::NodeList &Nodes = Func->getNodes();
if (Index >= Nodes.size()) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Reference to basic block " << Index
<< " not found. Must be less than " << Nodes.size();
Error(StrBuf.str());
// TODO(kschimpf) Remove error recovery once implementation complete.
Index = 0;
}
return Nodes[Index];
}
// Returns the Index-th basic block in the list of basic blocks. // Returns the Index-th basic block in the list of basic blocks.
// Assumes Index corresponds to a branch instruction. Hence, if // Assumes Index corresponds to a branch instruction. Hence, if
...@@ -1961,6 +1958,44 @@ private: ...@@ -1961,6 +1958,44 @@ private:
} }
}; };
bool FunctionParser::verifyAndRenameBasicBlocks() {
const size_t NumFoundBbs = BbMap.size();
// Verify number of basic blocks found match amount specified in function.
if (NumFoundBbs != SpecifiedNumBbs) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Function specified " << SpecifiedNumBbs
<< "basic blocks. Found: " << NumFoundBbs;
Error(StrBuf.str());
return false;
}
// Verify size limit allowed for basic blocks.
if (NumFoundBbs > NaClBcIndexSize_t_Max) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Functions can't define more than " << NaClBcIndexSize_t_Max
<< "basic blocks. Found: " << NumFoundBbs;
Error(StrBuf.str());
return false;
}
// Sort list of Bbs, verifying that no basic blocks are missing.
Ice::NodeList SortedBbs;
for (size_t i = 0; i < NumFoundBbs; ++i) {
CfgNodeMap::iterator pos = BbMap.find(i);
if (pos == BbMap.end()) {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Can't find definition for basic block " << i << ".";
Error(StrBuf.str());
return false;
}
SortedBbs.push_back(pos->second);
}
// Install sorted basic blocks.
Func->swapNodes(SortedBbs);
return true;
}
void FunctionParser::ExitBlock() { void FunctionParser::ExitBlock() {
// Check if the last instruction in the function was terminating. // Check if the last instruction in the function was terminating.
if (!InstIsTerminating) { if (!InstIsTerminating) {
...@@ -1972,6 +2007,8 @@ void FunctionParser::ExitBlock() { ...@@ -1972,6 +2007,8 @@ void FunctionParser::ExitBlock() {
} }
if (isIRGenerationDisabled()) if (isIRGenerationDisabled())
return; return;
if (!verifyAndRenameBasicBlocks())
return;
// Before translating, check for blocks without instructions, and // Before translating, check for blocks without instructions, and
// insert unreachable. This shouldn't happen, but be safe. // insert unreachable. This shouldn't happen, but be safe.
size_t Index = 0; size_t Index = 0;
...@@ -2030,14 +2067,11 @@ void FunctionParser::ProcessRecord() { ...@@ -2030,14 +2067,11 @@ void FunctionParser::ProcessRecord() {
} }
if (isIRGenerationDisabled()) if (isIRGenerationDisabled())
return; return;
if (Func->getNodes().size() != 1) { if (SpecifiedNumBbs != 0) {
Error("Duplicate function block count record"); Error("Duplicate function block count record");
return; return;
} }
// Install the basic blocks, skipping bb0 which was created in the SpecifiedNumBbs = NumBbsRaw;
// constructor.
for (size_t i = 1, NumBbs = NumBbsRaw; i < NumBbs; ++i)
installNextBasicBlock();
return; return;
} }
case naclbitc::FUNC_CODE_INST_BINOP: { case naclbitc::FUNC_CODE_INST_BINOP: {
...@@ -2861,15 +2895,13 @@ void FunctionValuesymtabParser::setValueName(NaClBcIndexSize_t Index, ...@@ -2861,15 +2895,13 @@ void FunctionValuesymtabParser::setValueName(NaClBcIndexSize_t Index,
void FunctionValuesymtabParser::setBbName(NaClBcIndexSize_t Index, void FunctionValuesymtabParser::setBbName(NaClBcIndexSize_t Index,
StringType &Name) { StringType &Name) {
if (isIRGenerationDisabled()) if (!Ice::BuildDefs::dump())
return; return;
if (Index >= getFunctionParser()->getFunc()->getNumNodes()) { if (isIRGenerationDisabled())
reportUnableToAssign("block", Index, Name);
return; return;
} Ice::CfgNode *Bb = getFunctionParser()->getBasicBlock(Index);
std::string Nm(Name.data(), Name.size()); std::string Nm(Name.data(), Name.size());
if (Ice::BuildDefs::dump()) Bb->setName(Nm);
getFunctionParser()->getFunc()->getNodes()[Index]->setName(Nm);
} }
bool FunctionParser::ParseBlock(unsigned BlockID) { bool FunctionParser::ParseBlock(unsigned BlockID) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment