return Context->getGlobalConstantByID(Index);
}
NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs;
- if (LocalIndex >= LocalOperands.size()) {
- std::string Buffer;
- raw_string_ostream StrBuf(Buffer);
- StrBuf << "Value index " << Index << " not defined!";
- Fatal(StrBuf.str());
- }
Ice::Operand *Op = LocalOperands[LocalIndex];
if (Op == nullptr) {
if (isIRGenerationDisabled())
}
private:
+ typedef std::unordered_map<NaClBcIndexSize_t, Ice::Operand *> OperandMap;
typedef std::unordered_map<NaClBcIndexSize_t, Ice::CfgNode *> CfgNodeMap;
Ice::TimerMarker Timer;
size_t CachedNumGlobalValueIDs;
// Holds operands local to the function block, based on indices
// defined in the bitcode file.
- std::vector<Ice::Operand *> LocalOperands;
+ OperandMap LocalOperands;
// Holds the index within LocalOperands corresponding to the next
// instruction that generates a value.
NaClBcIndexSize_t NextLocalInstIndex;
bool verifyAndRenameBasicBlocks();
+ bool verifyAllForwardRefsDefined();
+
// Returns the Index-th basic block in the list of basic blocks.
// Assumes Index corresponds to a branch instruction. Hence, if
// the branch references the entry block, it also generates a
assert(Op || isIRGenerationDisabled());
// Check if simple push works.
NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs;
- if (LocalIndex == LocalOperands.size()) {
- LocalOperands.push_back(Op);
- return;
- }
-
- // Must be forward reference, expand vector to accommodate.
- if (LocalIndex >= LocalOperands.size())
- LocalOperands.resize(LocalIndex + 1);
// If element not defined, set it.
- Ice::Operand *OldOp = LocalOperands[LocalIndex];
- if (OldOp == nullptr) {
- LocalOperands[LocalIndex] = Op;
+ Ice::Operand *&IndexedOp = LocalOperands[LocalIndex];
+ if (IndexedOp == nullptr) {
+ IndexedOp = Op;
return;
}
- // See if forward reference matches.
- if (OldOp == Op)
+ // See if forward reference matchers.
+ if (IndexedOp == Op)
return;
// Error has occurred.
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Multiple definitions for index " << Index << ": " << *Op
- << " and " << *OldOp;
+ << " and " << *IndexedOp;
Error(StrBuf.str());
// TODO(kschimpf) Remove error recovery once implementation complete.
- LocalOperands[LocalIndex] = Op;
+ IndexedOp = Op;
}
// Returns the relative operand (wrt to BaseIndex) referenced by
}
};
+bool FunctionParser::verifyAllForwardRefsDefined() {
+ NaClBcIndexSize_t NumInstructions =
+ NextLocalInstIndex - CachedNumGlobalValueIDs;
+ if (NumInstructions == LocalOperands.size())
+ return true;
+ // Find undefined forward references and report.
+ std::vector<NaClBcIndexSize_t> UndefinedFwdRefs;
+ for (const OperandMap::value_type &Elmt : LocalOperands)
+ if (Elmt.first >= NextLocalInstIndex)
+ UndefinedFwdRefs.push_back(Elmt.first);
+ std::sort(UndefinedFwdRefs.begin(), UndefinedFwdRefs.end());
+ for (const NaClBcIndexSize_t Index : UndefinedFwdRefs) {
+ std::string Buffer;
+ raw_string_ostream StrBuf(Buffer);
+ StrBuf << "Instruction forward reference not defined: " << Index;
+ Error(StrBuf.str());
+ }
+ return false;
+}
+
bool FunctionParser::verifyAndRenameBasicBlocks() {
const size_t NumFoundBbs = BbMap.size();
// Verify number of basic blocks found match amount specified in function.
}
if (isIRGenerationDisabled())
return;
+ if (!verifyAllForwardRefsDefined())
+ return;
if (!verifyAndRenameBasicBlocks())
return;
// Before translating, check for blocks without instructions, and