OSDN Git Service

Subzero: Manage each Cfg as a std::unique_ptr<Cfg>.
authorJim Stichnoth <stichnot@chromium.org>
Tue, 3 Feb 2015 01:03:08 +0000 (17:03 -0800)
committerJim Stichnoth <stichnot@chromium.org>
Tue, 3 Feb 2015 01:03:08 +0000 (17:03 -0800)
The Cfg::create() method now returns a unique_ptr.  Once the parser fully builds the Cfg, it is released onto the work queue, and then acquired and ultimately deleted by the translator thread.

BUG= none
R=jfb@chromium.org

Review URL: https://codereview.chromium.org/892063002

src/IceCfg.cpp
src/IceCfg.h
src/IceConverter.cpp
src/IceDefs.h
src/IceGlobalContext.cpp
src/IceGlobalContext.h
src/IceTranslator.cpp
src/IceTranslator.h
src/PNaClTranslator.cpp

index 53f9a9f..b284d06 100644 (file)
@@ -46,11 +46,7 @@ Cfg::Cfg(GlobalContext *Ctx)
          "Attempt to build cfg when IR generation disabled");
 }
 
-Cfg::~Cfg() {
-  assert(ICE_TLS_GET_FIELD(CurrentCfg) == this);
-  // Reset the thread-local CurrentCfg pointer.
-  ICE_TLS_SET_FIELD(CurrentCfg, nullptr);
-}
+Cfg::~Cfg() { assert(ICE_TLS_GET_FIELD(CurrentCfg) == nullptr); }
 
 void Cfg::setError(const IceString &Message) {
   HasError = true;
index 71f0a0d..605dcf7 100644 (file)
@@ -30,17 +30,14 @@ class Cfg {
 public:
   ~Cfg();
 
-  // TODO(stichnot): Change this to return unique_ptr<Cfg>, and plumb
-  // it through the callers, to make ownership and lifetime and
-  // destruction requirements more explicit.
-  static Cfg *create(GlobalContext *Ctx) {
-    Cfg *Func = new Cfg(Ctx);
-    ICE_TLS_SET_FIELD(CurrentCfg, Func);
-    return Func;
+  static std::unique_ptr<Cfg> create(GlobalContext *Ctx) {
+    return std::unique_ptr<Cfg>(new Cfg(Ctx));
   }
   // Gets a pointer to the current thread's Cfg.
   static const Cfg *getCurrentCfg() { return ICE_TLS_GET_FIELD(CurrentCfg); }
-  void updateTLS() const { ICE_TLS_SET_FIELD(CurrentCfg, this); }
+  static void setCurrentCfg(const Cfg *Func) {
+    ICE_TLS_SET_FIELD(CurrentCfg, Func);
+  }
   // Gets a pointer to the current thread's Cfg's allocator.
   static ArenaAllocator<> *getCurrentCfgAllocator() {
     assert(ICE_TLS_GET_FIELD(CurrentCfg));
index e8ec56d..47f8b39 100644 (file)
@@ -48,6 +48,10 @@ template <typename T> static std::string LLVMObjectAsString(const T *O) {
 }
 
 // Base class for converting LLVM to ICE.
+// TODO(stichnot): Redesign Converter, LLVM2ICEConverter,
+// LLVM2ICEFunctionConverter, and LLVM2ICEGlobalsConverter with
+// respect to Translator.  In particular, the unique_ptr ownership
+// rules in LLVM2ICEFunctionConverter.
 class LLVM2ICEConverter {
   LLVM2ICEConverter(const LLVM2ICEConverter &) = delete;
   LLVM2ICEConverter &operator=(const LLVM2ICEConverter &) = delete;
@@ -79,15 +83,16 @@ public:
   LLVM2ICEFunctionConverter(Ice::Converter &Converter)
       : LLVM2ICEConverter(Converter), Func(nullptr) {}
 
-  // Caller is expected to delete the returned Ice::Cfg object.
-  Ice::Cfg *convertFunction(const Function *F) {
+  void convertFunction(const Function *F) {
+    Func = Ice::Cfg::create(Ctx);
+    Ice::Cfg::setCurrentCfg(Func.get());
+
     VarMap.clear();
     NodeMap.clear();
-    Func = Ice::Cfg::create(Ctx);
     Func->setFunctionName(F->getName());
     Func->setReturnType(convertToIceType(F->getReturnType()));
     Func->setInternal(F->hasInternalLinkage());
-    Ice::TimerMarker T(Ice::TimerStack::TT_llvmConvert, Func);
+    Ice::TimerMarker T(Ice::TimerStack::TT_llvmConvert, Func.get());
 
     // The initial definition/use of each arg is the entry node.
     for (auto ArgI = F->arg_begin(), ArgE = F->arg_end(); ArgI != ArgE;
@@ -106,7 +111,8 @@ public:
     Func->setEntryNode(mapBasicBlockToNode(&F->getEntryBlock()));
     Func->computePredecessors();
 
-    return Func;
+    Ice::Cfg::setCurrentCfg(nullptr);
+    Converter.translateFcn(std::move(Func));
   }
 
   // convertConstant() does not use Func or require it to be a valid
@@ -147,7 +153,7 @@ private:
     if (VarMap.find(V) == VarMap.end()) {
       VarMap[V] = Func->makeVariable(IceTy);
       if (ALLOW_DUMP)
-        VarMap[V]->setName(Func, V->getName());
+        VarMap[V]->setName(Func.get(), V->getName());
     }
     return VarMap[V];
   }
@@ -304,13 +310,13 @@ private:
   Ice::Inst *convertLoadInstruction(const LoadInst *Inst) {
     Ice::Operand *Src = convertOperand(Inst, 0);
     Ice::Variable *Dest = mapValueToIceVar(Inst);
-    return Ice::InstLoad::create(Func, Dest, Src);
+    return Ice::InstLoad::create(Func.get(), Dest, Src);
   }
 
   Ice::Inst *convertStoreInstruction(const StoreInst *Inst) {
     Ice::Operand *Addr = convertOperand(Inst, 1);
     Ice::Operand *Val = convertOperand(Inst, 0);
-    return Ice::InstStore::create(Func, Val, Addr);
+    return Ice::InstStore::create(Func.get(), Val, Addr);
   }
 
   Ice::Inst *convertArithInstruction(const Instruction *Inst,
@@ -319,13 +325,13 @@ private:
     Ice::Operand *Src0 = convertOperand(Inst, 0);
     Ice::Operand *Src1 = convertOperand(Inst, 1);
     Ice::Variable *Dest = mapValueToIceVar(BinOp);
-    return Ice::InstArithmetic::create(Func, Opcode, Dest, Src0, Src1);
+    return Ice::InstArithmetic::create(Func.get(), Opcode, Dest, Src0, Src1);
   }
 
   Ice::Inst *convertPHINodeInstruction(const PHINode *Inst) {
     unsigned NumValues = Inst->getNumIncomingValues();
     Ice::InstPhi *IcePhi =
-        Ice::InstPhi::create(Func, NumValues, mapValueToIceVar(Inst));
+        Ice::InstPhi::create(Func.get(), NumValues, mapValueToIceVar(Inst));
     for (unsigned N = 0, E = NumValues; N != E; ++N) {
       IcePhi->addArgument(convertOperand(Inst, N),
                           mapBasicBlockToNode(Inst->getIncomingBlock(N)));
@@ -340,31 +346,31 @@ private:
       BasicBlock *BBElse = Inst->getSuccessor(1);
       Ice::CfgNode *NodeThen = mapBasicBlockToNode(BBThen);
       Ice::CfgNode *NodeElse = mapBasicBlockToNode(BBElse);
-      return Ice::InstBr::create(Func, Src, NodeThen, NodeElse);
+      return Ice::InstBr::create(Func.get(), Src, NodeThen, NodeElse);
     } else {
       BasicBlock *BBSucc = Inst->getSuccessor(0);
-      return Ice::InstBr::create(Func, mapBasicBlockToNode(BBSucc));
+      return Ice::InstBr::create(Func.get(), mapBasicBlockToNode(BBSucc));
     }
   }
 
   Ice::Inst *convertIntToPtrInstruction(const IntToPtrInst *Inst) {
     Ice::Operand *Src = convertOperand(Inst, 0);
     Ice::Variable *Dest = mapValueToIceVar(Inst, Ice::getPointerType());
-    return Ice::InstAssign::create(Func, Dest, Src);
+    return Ice::InstAssign::create(Func.get(), Dest, Src);
   }
 
   Ice::Inst *convertPtrToIntInstruction(const PtrToIntInst *Inst) {
     Ice::Operand *Src = convertOperand(Inst, 0);
     Ice::Variable *Dest = mapValueToIceVar(Inst);
-    return Ice::InstAssign::create(Func, Dest, Src);
+    return Ice::InstAssign::create(Func.get(), Dest, Src);
   }
 
   Ice::Inst *convertRetInstruction(const ReturnInst *Inst) {
     Ice::Operand *RetOperand = convertOperand(Inst, 0);
     if (RetOperand) {
-      return Ice::InstRet::create(Func, RetOperand);
+      return Ice::InstRet::create(Func.get(), RetOperand);
     } else {
-      return Ice::InstRet::create(Func);
+      return Ice::InstRet::create(Func.get());
     }
   }
 
@@ -372,7 +378,7 @@ private:
                                     Ice::InstCast::OpKind CastKind) {
     Ice::Operand *Src = convertOperand(Inst, 0);
     Ice::Variable *Dest = mapValueToIceVar(Inst);
-    return Ice::InstCast::create(Func, CastKind, Dest, Src);
+    return Ice::InstCast::create(Func.get(), CastKind, Dest, Src);
   }
 
   Ice::Inst *convertICmpInstruction(const ICmpInst *Inst) {
@@ -416,7 +422,7 @@ private:
       break;
     }
 
-    return Ice::InstIcmp::create(Func, Cond, Dest, Src0, Src1);
+    return Ice::InstIcmp::create(Func.get(), Cond, Dest, Src0, Src1);
   }
 
   Ice::Inst *convertFCmpInstruction(const FCmpInst *Inst) {
@@ -480,14 +486,14 @@ private:
       break;
     }
 
-    return Ice::InstFcmp::create(Func, Cond, Dest, Src0, Src1);
+    return Ice::InstFcmp::create(Func.get(), Cond, Dest, Src0, Src1);
   }
 
   Ice::Inst *convertExtractElementInstruction(const ExtractElementInst *Inst) {
     Ice::Variable *Dest = mapValueToIceVar(Inst);
     Ice::Operand *Source1 = convertValue(Inst->getOperand(0));
     Ice::Operand *Source2 = convertValue(Inst->getOperand(1));
-    return Ice::InstExtractElement::create(Func, Dest, Source1, Source2);
+    return Ice::InstExtractElement::create(Func.get(), Dest, Source1, Source2);
   }
 
   Ice::Inst *convertInsertElementInstruction(const InsertElementInst *Inst) {
@@ -495,7 +501,7 @@ private:
     Ice::Operand *Source1 = convertValue(Inst->getOperand(0));
     Ice::Operand *Source2 = convertValue(Inst->getOperand(1));
     Ice::Operand *Source3 = convertValue(Inst->getOperand(2));
-    return Ice::InstInsertElement::create(Func, Dest, Source1, Source2,
+    return Ice::InstInsertElement::create(Func.get(), Dest, Source1, Source2,
                                           Source3);
   }
 
@@ -504,7 +510,7 @@ private:
     Ice::Operand *Cond = convertValue(Inst->getCondition());
     Ice::Operand *Source1 = convertValue(Inst->getTrueValue());
     Ice::Operand *Source2 = convertValue(Inst->getFalseValue());
-    return Ice::InstSelect::create(Func, Dest, Cond, Source1, Source2);
+    return Ice::InstSelect::create(Func.get(), Dest, Cond, Source1, Source2);
   }
 
   Ice::Inst *convertSwitchInstruction(const SwitchInst *Inst) {
@@ -512,7 +518,7 @@ private:
     Ice::CfgNode *LabelDefault = mapBasicBlockToNode(Inst->getDefaultDest());
     unsigned NumCases = Inst->getNumCases();
     Ice::InstSwitch *Switch =
-        Ice::InstSwitch::create(Func, NumCases, Source, LabelDefault);
+        Ice::InstSwitch::create(Func.get(), NumCases, Source, LabelDefault);
     unsigned CurrentCase = 0;
     for (SwitchInst::ConstCaseIt I = Inst->case_begin(), E = Inst->case_end();
          I != E; ++I, ++CurrentCase) {
@@ -544,14 +550,14 @@ private:
           report_fatal_error(std::string("Invalid PNaCl intrinsic call: ") +
                              LLVMObjectAsString(Inst));
         }
-        NewInst = Ice::InstIntrinsicCall::create(Func, NumArgs, Dest,
+        NewInst = Ice::InstIntrinsicCall::create(Func.get(), NumArgs, Dest,
                                                  CallTarget, Info->Info);
       }
     }
 
     // Not an intrinsic call.
     if (NewInst == nullptr) {
-      NewInst = Ice::InstCall::create(Func, NumArgs, Dest, CallTarget,
+      NewInst = Ice::InstCall::create(Func.get(), NumArgs, Dest, CallTarget,
                                       Inst->isTailCall());
     }
     for (unsigned i = 0; i < NumArgs; ++i) {
@@ -569,11 +575,11 @@ private:
     uint32_t Align = Inst->getAlignment();
     Ice::Variable *Dest = mapValueToIceVar(Inst, Ice::getPointerType());
 
-    return Ice::InstAlloca::create(Func, ByteCount, Align, Dest);
+    return Ice::InstAlloca::create(Func.get(), ByteCount, Align, Dest);
   }
 
   Ice::Inst *convertUnreachableInstruction(const UnreachableInst * /*Inst*/) {
-    return Ice::InstUnreachable::create(Func);
+    return Ice::InstUnreachable::create(Func.get());
   }
 
   Ice::CfgNode *convertBasicBlock(const BasicBlock *BB) {
@@ -621,7 +627,7 @@ private:
 
 private:
   // Data
-  Ice::Cfg *Func;
+  std::unique_ptr<Ice::Cfg> Func;
   std::map<const Value *, Ice::Variable *> VarMap;
   std::map<const BasicBlock *, Ice::CfgNode *> NodeMap;
 };
@@ -872,21 +878,21 @@ void Converter::convertGlobals(Module *Mod) {
 }
 
 void Converter::convertFunctions() {
-  TimerStackIdT StackID = GlobalContext::TSK_Funcs;
+  const TimerStackIdT StackID = GlobalContext::TSK_Funcs;
   for (const Function &I : *Mod) {
     if (I.empty())
       continue;
 
     TimerIdT TimerID = 0;
-    if (ALLOW_DUMP && Ctx->getFlags().TimeEachFunction) {
+    const bool TimeThisFunction =
+        ALLOW_DUMP && Ctx->getFlags().TimeEachFunction;
+    if (TimeThisFunction) {
       TimerID = Ctx->getTimerID(StackID, I.getName());
       Ctx->pushTimer(TimerID, StackID);
     }
     LLVM2ICEFunctionConverter FunctionConverter(*this);
-
-    Cfg *Fcn = FunctionConverter.convertFunction(&I);
-    translateFcn(Fcn);
-    if (ALLOW_DUMP && Ctx->getFlags().TimeEachFunction)
+    FunctionConverter.convertFunction(&I);
+    if (TimeThisFunction)
       Ctx->popTimer(TimerID, StackID);
   }
 }
index 368e92c..19b0694 100644 (file)
@@ -23,6 +23,7 @@
 #include <limits>
 #include <list>
 #include <map>
+#include <memory>
 #include <mutex>
 #include <string>
 #include <system_error>
index 7b782e9..4324f97 100644 (file)
@@ -162,11 +162,11 @@ GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit,
 }
 
 void GlobalContext::translateFunctions() {
-  while (Cfg *Func = cfgQueueBlockingPop()) {
+  while (std::unique_ptr<Cfg> Func = cfgQueueBlockingPop()) {
+    // Install Func in TLS for Cfg-specific container allocators.
+    Cfg::setCurrentCfg(Func.get());
     // Reset per-function stats being accumulated in TLS.
     resetStats();
-    // Install Func in TLS for Cfg-specific container allocators.
-    Func->updateTLS();
     // Set verbose level to none if the current function does NOT
     // match the -verbose-focus command-line option.
     if (!matchSymbolName(Func->getFunctionName(), getFlags().VerboseFocusOn))
@@ -191,10 +191,10 @@ void GlobalContext::translateFunctions() {
           Func->emit();
         // TODO(stichnot): actually add to emit queue
       }
-      // TODO(stichnot): fix multithreaded stats dumping.
       dumpStats(Func->getFunctionName());
     }
-    delete Func;
+    Cfg::setCurrentCfg(nullptr);
+    // The Cfg now gets deleted as Func goes out of scope.
   }
 }
 
@@ -548,6 +548,19 @@ void GlobalContext::setTimerName(TimerStackIdT StackID,
   Timers->at(StackID).setName(NewName);
 }
 
+// Note: cfgQueueBlockingPush and cfgQueueBlockingPop use unique_ptr
+// at the interface to take and transfer ownership, but they
+// internally store the raw Cfg pointer in the work queue.  This
+// allows e.g. future queue optimizations such as the use of atomics
+// to modify queue elements.
+void GlobalContext::cfgQueueBlockingPush(std::unique_ptr<Cfg> Func) {
+  CfgQ.blockingPush(Func.release());
+}
+
+std::unique_ptr<Cfg> GlobalContext::cfgQueueBlockingPop() {
+  return std::unique_ptr<Cfg>(CfgQ.blockingPop());
+}
+
 void GlobalContext::dumpStats(const IceString &Name, bool Final) {
   if (!ALLOW_DUMP || !getFlags().DumpStats)
     return;
index 2bb8f62..e3e0810 100644 (file)
@@ -280,12 +280,12 @@ public:
   // queue.  Notifies any idle workers that a new function is
   // available for translating.  May block if the work queue is too
   // large, in order to control memory footprint.
-  void cfgQueueBlockingPush(Cfg *Func) { CfgQ.blockingPush(Func); }
+  void cfgQueueBlockingPush(std::unique_ptr<Cfg> Func);
   // Takes a Cfg from the work queue for translating.  May block if
   // the work queue is currently empty.  Returns nullptr if there is
   // no more work - the queue is empty and either end() has been
   // called or the Sequential flag was set.
-  Cfg *cfgQueueBlockingPop() { return CfgQ.blockingPop(); }
+  std::unique_ptr<Cfg> cfgQueueBlockingPop();
   // Notifies that no more work will be added to the work queue.
   void cfgQueueNotifyEnd() { CfgQ.notifyEnd(); }
 
index c05f58d..4753b22 100644 (file)
@@ -53,8 +53,8 @@ bool Translator::checkIfUnnamedNameSafe(const IceString &Name, const char *Kind,
   return false;
 }
 
-void Translator::translateFcn(Cfg *Func) {
-  Ctx->cfgQueueBlockingPush(Func);
+void Translator::translateFcn(std::unique_ptr<Cfg> Func) {
+  Ctx->cfgQueueBlockingPush(std::move(Func));
   if (Ctx->getFlags().NumTranslationThreads == 0) {
     Ctx->translateFunctions();
   }
index cd5a8d6..6b35b25 100644 (file)
@@ -45,7 +45,7 @@ public:
 
   /// Translates the constructed ICE function Fcn to machine code.
   /// Takes ownership of Func.
-  void translateFcn(Cfg *Func);
+  void translateFcn(std::unique_ptr<Cfg> Func);
 
   /// Emits the constant pool.
   void emitConstants();
index 0c06231..249875f 100644 (file)
@@ -1052,19 +1052,27 @@ public:
   FunctionParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
       : BlockParserBaseClass(BlockID, EnclosingParser),
         Timer(Ice::TimerStack::TT_parseFunctions, getTranslator().getContext()),
-        Func(isIRGenerationDisabled()
-                 ? nullptr
-                 : Ice::Cfg::create(getTranslator().getContext())),
-        CurrentBbIndex(0), FcnId(Context->getNextFunctionBlockValueID()),
+        Func(nullptr), CurrentBbIndex(0),
+        FcnId(Context->getNextFunctionBlockValueID()),
         FuncDecl(Context->getFunctionByID(FcnId)),
         CachedNumGlobalValueIDs(Context->getNumGlobalIDs()),
         NextLocalInstIndex(Context->getNumGlobalIDs()),
-        InstIsTerminating(false) {
-    if (ALLOW_DUMP && getFlags().TimeEachFunction)
-      getTranslator().getContext()->pushTimer(
-          getTranslator().getContext()->getTimerID(
-              Ice::GlobalContext::TSK_Funcs, FuncDecl->getName()),
-          Ice::GlobalContext::TSK_Funcs);
+        InstIsTerminating(false) {}
+
+  bool convertFunction() {
+    const Ice::TimerStackIdT StackID = Ice::GlobalContext::TSK_Funcs;
+    Ice::TimerIdT TimerID = 0;
+    const bool TimeThisFunction = ALLOW_DUMP && getFlags().TimeEachFunction;
+    if (TimeThisFunction) {
+      TimerID = getTranslator().getContext()->getTimerID(StackID,
+                                                         FuncDecl->getName());
+      getTranslator().getContext()->pushTimer(TimerID, StackID);
+    }
+
+    if (!isIRGenerationDisabled())
+      Func = Ice::Cfg::create(getTranslator().getContext());
+    Ice::Cfg::setCurrentCfg(Func.get());
+
     // TODO(kschimpf) Clean up API to add a function signature to
     // a CFG.
     const Ice::FuncSigType &Signature = FuncDecl->getSignature();
@@ -1084,13 +1092,34 @@ public:
         Func->addArg(getNextInstVar(ArgType));
       }
     }
+    bool ParserResult = ParseThisBlock();
+
+    // Temporarily end per-function timing, which will be resumed by
+    // the translator function.  This is because translation may be
+    // done asynchronously in a separate thread.
+    if (TimeThisFunction)
+      getTranslator().getContext()->popTimer(TimerID, StackID);
+
+    Ice::Cfg::setCurrentCfg(nullptr);
+    // Note: Once any errors have been found, we turn off all
+    // translation of all remaining functions. This allows successive
+    // parsing errors to be reported, without adding extra checks to
+    // the translator for such parsing errors.
+    if (Context->getNumErrors() == 0) {
+      getTranslator().translateFcn(std::move(Func));
+      // The translator now has ownership of Func.
+    } else {
+      Func.reset();
+    }
+
+    return ParserResult;
   }
 
   ~FunctionParser() final {}
 
   const char *getBlockName() const override { return "function"; }
 
-  Ice::Cfg *getFunc() const { return Func; }
+  Ice::Cfg *getFunc() const { return Func.get(); }
 
   uint32_t getNumGlobalIDs() const { return CachedNumGlobalValueIDs; }
 
@@ -1130,7 +1159,7 @@ public:
 private:
   Ice::TimerMarker Timer;
   // The corresponding ICE function defined by the function block.
-  Ice::Cfg *Func;
+  std::unique_ptr<Ice::Cfg> Func;
   // The index to the current basic block being built.
   uint32_t CurrentBbIndex;
   // The basic block being built.
@@ -1153,15 +1182,6 @@ private:
   // Upper limit of alignment power allowed by LLVM
   static const uint32_t AlignPowerLimit = 29;
 
-  void popTimerIfTimingEachFunction() const {
-    if (ALLOW_DUMP && getFlags().TimeEachFunction) {
-      getTranslator().getContext()->popTimer(
-          getTranslator().getContext()->getTimerID(
-              Ice::GlobalContext::TSK_Funcs, FuncDecl->getName()),
-          Ice::GlobalContext::TSK_Funcs);
-    }
-  }
-
   // Extracts the corresponding Alignment to use, given the AlignPower
   // (i.e. 2**(AlignPower-1), or 0 if AlignPower == 0). InstName is the
   // name of the instruction the alignment appears in.
@@ -1820,14 +1840,12 @@ private:
     if (Ty == Ice::IceType_void)
       return;
     Ice::Variable *Var = getNextInstVar(Ty);
-    CurrentNode->appendInst(Ice::InstAssign::create(Func, Var, Var));
+    CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var));
   }
 };
 
 void FunctionParser::ExitBlock() {
   if (isIRGenerationDisabled()) {
-    popTimerIfTimingEachFunction();
-    delete Func;
     return;
   }
   // Before translating, check for blocks without instructions, and
@@ -1840,21 +1858,11 @@ void FunctionParser::ExitBlock() {
       StrBuf << "Basic block " << Index << " contains no instructions";
       Error(StrBuf.str());
       // TODO(kschimpf) Remove error recovery once implementation complete.
-      Node->appendInst(Ice::InstUnreachable::create(Func));
+      Node->appendInst(Ice::InstUnreachable::create(Func.get()));
     }
     ++Index;
   }
   Func->computePredecessors();
-  // Temporarily end per-function timing, which will be resumed by the
-  // translator function.  This is because translation may be done
-  // asynchronously in a separate thread.
-  popTimerIfTimingEachFunction();
-  // Note: Once any errors have been found, we turn off all
-  // translation of all remaining functions. This allows use to see
-  // multiple errors, without adding extra checks to the translator
-  // for such parsing errors.
-  if (Context->getNumErrors() == 0)
-    getTranslator().translateFcn(Func);
 }
 
 void FunctionParser::ReportInvalidBinaryOp(Ice::InstArithmetic::OpKind Op,
@@ -1930,7 +1938,7 @@ void FunctionParser::ProcessRecord() {
       return;
     }
     CurrentNode->appendInst(Ice::InstArithmetic::create(
-        Func, Opcode, getNextInstVar(Type1), Op1, Op2));
+        Func.get(), Opcode, getNextInstVar(Type1), Op1, Op2));
     return;
   }
   case naclbitc::FUNC_CODE_INST_CAST: {
@@ -1949,8 +1957,8 @@ void FunctionParser::ProcessRecord() {
       appendErrorInstruction(CastType);
       return;
     }
-    CurrentNode->appendInst(
-        Ice::InstCast::create(Func, CastKind, getNextInstVar(CastType), Src));
+    CurrentNode->appendInst(Ice::InstCast::create(
+        Func.get(), CastKind, getNextInstVar(CastType), Src));
     return;
   }
   case naclbitc::FUNC_CODE_INST_VSELECT: {
@@ -1999,7 +2007,7 @@ void FunctionParser::ProcessRecord() {
       return;
     }
     CurrentNode->appendInst(Ice::InstSelect::create(
-        Func, getNextInstVar(ThenType), CondVal, ThenVal, ElseVal));
+        Func.get(), getNextInstVar(ThenType), CondVal, ThenVal, ElseVal));
     return;
   }
   case naclbitc::FUNC_CODE_INST_EXTRACTELT: {
@@ -2026,7 +2034,7 @@ void FunctionParser::ProcessRecord() {
       return;
     }
     CurrentNode->appendInst(Ice::InstExtractElement::create(
-        Func, getNextInstVar(typeElementType(VecType)), Vec, Index));
+        Func.get(), getNextInstVar(typeElementType(VecType)), Vec, Index));
     return;
   }
   case naclbitc::FUNC_CODE_INST_INSERTELT: {
@@ -2055,7 +2063,7 @@ void FunctionParser::ProcessRecord() {
       return;
     }
     CurrentNode->appendInst(Ice::InstInsertElement::create(
-        Func, getNextInstVar(VecType), Vec, Elt, Index));
+        Func.get(), getNextInstVar(VecType), Vec, Elt, Index));
     return;
   }
   case naclbitc::FUNC_CODE_INST_CMP2: {
@@ -2100,7 +2108,7 @@ void FunctionParser::ProcessRecord() {
         appendErrorInstruction(DestType);
       }
       CurrentNode->appendInst(
-          Ice::InstIcmp::create(Func, Cond, Dest, Op1, Op2));
+          Ice::InstIcmp::create(Func.get(), Cond, Dest, Op1, Op2));
     } else if (isFloatingType(Op1Type)) {
       Ice::InstFcmp::FCond Cond;
       if (!convertNaClBitcFCompOpToIce(Values[2], Cond)) {
@@ -2112,7 +2120,7 @@ void FunctionParser::ProcessRecord() {
         appendErrorInstruction(DestType);
       }
       CurrentNode->appendInst(
-          Ice::InstFcmp::create(Func, Cond, Dest, Op1, Op2));
+          Ice::InstFcmp::create(Func.get(), Cond, Dest, Op1, Op2));
     } else {
       // Not sure this can happen, but be safe.
       std::string Buffer;
@@ -2131,14 +2139,14 @@ void FunctionParser::ProcessRecord() {
     if (Values.empty()) {
       if (isIRGenerationDisabled())
         return;
-      CurrentNode->appendInst(Ice::InstRet::create(Func));
+      CurrentNode->appendInst(Ice::InstRet::create(Func.get()));
     } else {
       Ice::Operand *RetVal = getRelativeOperand(Values[0], BaseIndex);
       if (isIRGenerationDisabled()) {
         assert(RetVal == nullptr);
         return;
       }
-      CurrentNode->appendInst(Ice::InstRet::create(Func, RetVal));
+      CurrentNode->appendInst(Ice::InstRet::create(Func.get(), RetVal));
     }
     InstIsTerminating = true;
     return;
@@ -2151,7 +2159,7 @@ void FunctionParser::ProcessRecord() {
       Ice::CfgNode *Block = getBranchBasicBlock(Values[0]);
       if (Block == nullptr)
         return;
-      CurrentNode->appendInst(Ice::InstBr::create(Func, Block));
+      CurrentNode->appendInst(Ice::InstBr::create(Func.get(), Block));
     } else {
       // BR: [bb#, bb#, opval]
       if (!isValidRecordSize(3, "branch"))
@@ -2174,7 +2182,7 @@ void FunctionParser::ProcessRecord() {
       if (ThenBlock == nullptr || ElseBlock == nullptr)
         return;
       CurrentNode->appendInst(
-          Ice::InstBr::create(Func, Cond, ThenBlock, ElseBlock));
+          Ice::InstBr::create(Func.get(), Cond, ThenBlock, ElseBlock));
     }
     InstIsTerminating = true;
     return;
@@ -2221,8 +2229,9 @@ void FunctionParser::ProcessRecord() {
     if (!isValidRecordSize(4 + NumCases * 4, "switch"))
       return;
     Ice::InstSwitch *Switch =
-        isIRGenDisabled ? nullptr : Ice::InstSwitch::create(Func, NumCases,
-                                                            Cond, DefaultLabel);
+        isIRGenDisabled
+            ? nullptr
+            : Ice::InstSwitch::create(Func.get(), NumCases, Cond, DefaultLabel);
     unsigned ValCaseIndex = 4; // index to beginning of case entry.
     for (unsigned CaseIndex = 0; CaseIndex < NumCases;
          ++CaseIndex, ValCaseIndex += 4) {
@@ -2253,7 +2262,7 @@ void FunctionParser::ProcessRecord() {
       return;
     if (isIRGenerationDisabled())
       return;
-    CurrentNode->appendInst(Ice::InstUnreachable::create(Func));
+    CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get()));
     InstIsTerminating = true;
     return;
   }
@@ -2285,7 +2294,8 @@ void FunctionParser::ProcessRecord() {
       return;
     }
     Ice::Variable *Dest = getNextInstVar(Ty);
-    Ice::InstPhi *Phi = Ice::InstPhi::create(Func, Values.size() >> 1, Dest);
+    Ice::InstPhi *Phi =
+        Ice::InstPhi::create(Func.get(), Values.size() >> 1, Dest);
     for (unsigned i = 1; i < Values.size(); i += 2) {
       Ice::Operand *Op =
           getRelativeOperand(NaClDecodeSignRotatedValue(Values[i]), BaseIndex);
@@ -2324,8 +2334,8 @@ void FunctionParser::ProcessRecord() {
       appendErrorInstruction(PtrTy);
       return;
     }
-    CurrentNode->appendInst(Ice::InstAlloca::create(Func, ByteCount, Alignment,
-                                                    getNextInstVar(PtrTy)));
+    CurrentNode->appendInst(Ice::InstAlloca::create(
+        Func.get(), ByteCount, Alignment, getNextInstVar(PtrTy)));
     return;
   }
   case naclbitc::FUNC_CODE_INST_LOAD: {
@@ -2349,8 +2359,8 @@ void FunctionParser::ProcessRecord() {
       appendErrorInstruction(Ty);
       return;
     }
-    CurrentNode->appendInst(
-        Ice::InstLoad::create(Func, getNextInstVar(Ty), Address, Alignment));
+    CurrentNode->appendInst(Ice::InstLoad::create(
+        Func.get(), getNextInstVar(Ty), Address, Alignment));
     return;
   }
   case naclbitc::FUNC_CODE_INST_STORE: {
@@ -2370,7 +2380,7 @@ void FunctionParser::ProcessRecord() {
     if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store"))
       return;
     CurrentNode->appendInst(
-        Ice::InstStore::create(Func, Value, Address, Alignment));
+        Ice::InstStore::create(Func.get(), Value, Address, Alignment));
     return;
   }
   case naclbitc::FUNC_CODE_INST_CALL:
@@ -2459,10 +2469,11 @@ void FunctionParser::ProcessRecord() {
                               : getNextInstVar(ReturnType);
     Ice::InstCall *Inst = nullptr;
     if (IntrinsicInfo) {
-      Inst = Ice::InstIntrinsicCall::create(Func, NumParams, Dest, Callee,
+      Inst = Ice::InstIntrinsicCall::create(Func.get(), NumParams, Dest, Callee,
                                             IntrinsicInfo->Info);
     } else {
-      Inst = Ice::InstCall::create(Func, NumParams, Dest, Callee, IsTailCall);
+      Inst = Ice::InstCall::create(Func.get(), NumParams, Dest, Callee,
+                                   IsTailCall);
     }
 
     // Add parameters.
@@ -2857,7 +2868,7 @@ bool ModuleParser::ParseBlock(unsigned BlockID) {
   case naclbitc::FUNCTION_BLOCK_ID: {
     InstallGlobalNamesAndGlobalVarInitializers();
     FunctionParser Parser(BlockID, this);
-    return Parser.ParseThisBlock();
+    return Parser.convertFunction();
   }
   default:
     return BlockParserBaseClass::ParseBlock(BlockID);