Commit 8e92838b by Jim Stichnoth

Subzero: Manage each Cfg as a std::unique_ptr<Cfg>.

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