| Index: src/PNaClTranslator.cpp
|
| diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
|
| index df2989c948dc8ad30cb95483d01d0a7411facfc9..5489d5aba27531635dbb4ab91b2f68d50a75aa7e 100644
|
| --- a/src/PNaClTranslator.cpp
|
| +++ b/src/PNaClTranslator.cpp
|
| @@ -814,6 +814,7 @@ public:
|
| FcnId(Context->getNextFunctionBlockValueID()),
|
| LLVMFunc(cast<Function>(Context->getGlobalValueByID(FcnId))),
|
| CachedNumGlobalValueIDs(Context->getNumGlobalValueIDs()),
|
| + NextLocalInstIndex(Context->getNumGlobalValueIDs()),
|
| InstIsTerminating(false) {
|
| Func->setFunctionName(LLVMFunc->getName());
|
| Func->setReturnType(Context->convertToIceType(LLVMFunc->getReturnType()));
|
| @@ -830,7 +831,9 @@ public:
|
| ~FunctionParser() LLVM_OVERRIDE;
|
|
|
| // Set the next constant ID to the given constant C.
|
| - void setNextConstantID(Ice::Constant *C) { LocalOperands.push_back(C); }
|
| + void setNextConstantID(Ice::Constant *C) {
|
| + setOperand(NextLocalInstIndex++, C);
|
| + }
|
|
|
| private:
|
| // Timer for reading function bitcode and converting to ICE.
|
| @@ -845,11 +848,14 @@ private:
|
| unsigned FcnId;
|
| // The corresponding LLVM function.
|
| Function *LLVMFunc;
|
| + // Holds the dividing point between local and global absolute value indices.
|
| + uint32_t CachedNumGlobalValueIDs;
|
| // Holds operands local to the function block, based on indices
|
| // defined in the bitcode file.
|
| std::vector<Ice::Operand *> LocalOperands;
|
| - // Holds the dividing point between local and global absolute value indices.
|
| - uint32_t CachedNumGlobalValueIDs;
|
| + // Holds the index within LocalOperands corresponding to the next
|
| + // instruction that generates a value.
|
| + uint32_t NextLocalInstIndex;
|
| // True if the last processed instruction was a terminating
|
| // instruction.
|
| bool InstIsTerminating;
|
| @@ -910,15 +916,42 @@ private:
|
| return getBasicBlock(Index);
|
| }
|
|
|
| - // Generates the next available local variable using the given type.
|
| - Ice::Variable *getNextInstVar(Ice::Type Ty) {
|
| + // Generate an instruction variable with type Ty.
|
| + Ice::Variable *createInstVar(Ice::Type Ty) {
|
| if (Ty == Ice::IceType_void) {
|
| Error("Can't define instruction value using type void");
|
| // Recover since we can't throw an exception.
|
| Ty = Ice::IceType_i32;
|
| }
|
| - Ice::Variable *Var = Func->makeVariable(Ty, CurrentNode);
|
| - LocalOperands.push_back(Var);
|
| + return Func->makeVariable(Ty, CurrentNode);
|
| + }
|
| +
|
| + // Generates the next available local variable using the given type.
|
| + Ice::Variable *getNextInstVar(Ice::Type Ty) {
|
| + assert(NextLocalInstIndex >= CachedNumGlobalValueIDs);
|
| + // Before creating one, see if a forwardtyperef has already defined it.
|
| + uint32_t LocalIndex = NextLocalInstIndex - CachedNumGlobalValueIDs;
|
| + if (LocalIndex < LocalOperands.size()) {
|
| + Ice::Operand *Op = LocalOperands[LocalIndex];
|
| + if (Op != NULL) {
|
| + if (Ice::Variable *Var = dyn_cast<Ice::Variable>(Op)) {
|
| + if (Var->getType() == Ty) {
|
| + ++NextLocalInstIndex;
|
| + return Var;
|
| + }
|
| + }
|
| + std::string Buffer;
|
| + raw_string_ostream StrBuf(Buffer);
|
| + StrBuf << "Illegal forward referenced instruction ("
|
| + << NextLocalInstIndex << "): " << *Op;
|
| + Error(StrBuf.str());
|
| + // TODO(kschimpf) Remove error recovery once implementation complete.
|
| + ++NextLocalInstIndex;
|
| + return createInstVar(Ty);
|
| + }
|
| + }
|
| + Ice::Variable *Var = createInstVar(Ty);
|
| + setOperand(NextLocalInstIndex++, Var);
|
| return Var;
|
| }
|
|
|
| @@ -947,12 +980,54 @@ private:
|
| if (LocalIndex >= LocalOperands.size()) {
|
| std::string Buffer;
|
| raw_string_ostream StrBuf(Buffer);
|
| - StrBuf << "Value index " << Index << " out of range. Must be less than "
|
| - << (LocalOperands.size() + CachedNumGlobalValueIDs);
|
| + StrBuf << "Value index " << Index << " not defined!";
|
| Error(StrBuf.str());
|
| report_fatal_error("Unable to continue");
|
| }
|
| - return LocalOperands[LocalIndex];
|
| + Ice::Operand *Op = LocalOperands[LocalIndex];
|
| + if (Op == NULL) {
|
| + std::string Buffer;
|
| + raw_string_ostream StrBuf(Buffer);
|
| + StrBuf << "Value index " << Index << " not defined!";
|
| + Error(StrBuf.str());
|
| + report_fatal_error("Unable to continue");
|
| + }
|
| + return Op;
|
| + }
|
| +
|
| + // Sets element Index (in the local operands list) to Op.
|
| + void setOperand(uint32_t Index, Ice::Operand *Op) {
|
| + assert(Op);
|
| + // Check if simple push works.
|
| + uint32_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 == NULL) {
|
| + LocalOperands[LocalIndex] = Op;
|
| + return;
|
| + }
|
| +
|
| + // See if forward reference matches.
|
| + if (OldOp == Op)
|
| + return;
|
| +
|
| + // Error has occurred.
|
| + std::string Buffer;
|
| + raw_string_ostream StrBuf(Buffer);
|
| + StrBuf << "Multiple definitions for index " << Index
|
| + << ": " << *Op << " and " << *OldOp;
|
| + Error(StrBuf.str());
|
| + // TODO(kschimpf) Remove error recovery once implementation complete.
|
| + LocalOperands[LocalIndex] = Op;
|
| }
|
|
|
| // Returns the relative operand (wrt to BaseIndex) referenced by
|
| @@ -963,7 +1038,7 @@ private:
|
|
|
| // Returns the absolute index of the next value generating instruction.
|
| uint32_t getNextInstIndex() const {
|
| - return CachedNumGlobalValueIDs + LocalOperands.size();
|
| + return NextLocalInstIndex;
|
| }
|
|
|
| // Generates type error message for binary operator Op
|
| @@ -1702,10 +1777,17 @@ void FunctionParser::ProcessRecord() {
|
| Ice::InstStore::create(Func, Value, Address, Alignment));
|
| break;
|
| }
|
| + case naclbitc::FUNC_CODE_INST_FORWARDTYPEREF: {
|
| + // FORWARDTYPEREF: [opval, ty]
|
| + if (!isValidRecordSize(2, "function block forward type ref"))
|
| + return;
|
| + setOperand(Values[0], createInstVar(
|
| + Context->convertToIceType(Context->getTypeByID(Values[1]))));
|
| + break;
|
| + }
|
| case naclbitc::FUNC_CODE_INST_SWITCH:
|
| case naclbitc::FUNC_CODE_INST_CALL:
|
| case naclbitc::FUNC_CODE_INST_CALL_INDIRECT:
|
| - case naclbitc::FUNC_CODE_INST_FORWARDTYPEREF:
|
| default:
|
| // Generate error message!
|
| BlockParserBaseClass::ProcessRecord();
|
|
|