Index: src/llvm2ice.cpp |
diff --git a/src/llvm2ice.cpp b/src/llvm2ice.cpp |
index bd86c57509c7d854ed5d432ce010dfa27e1165f2..4df78a1383a9626d7993e7eb695f5373ee6eebfe 100644 |
--- a/src/llvm2ice.cpp |
+++ b/src/llvm2ice.cpp |
@@ -203,6 +203,18 @@ GenerateBuildAtts("build-atts", |
"this executable."), |
cl::init(false)); |
+// Number of translation threads (in addition to the parser thread and |
+// the emitter thread). The special case of 0 means purely |
+// sequential, i.e. parser, translator, and emitter all within the |
+// same single thread. (This may need a slight rework if we expand to |
+// multiple parser or emitter threads.) |
+static cl::opt<uint32_t> |
+NumThreads("threads", |
+ cl::desc("Number of translation threads (0 for purely sequential)"), |
+ // TODO(stichnot): Settle on a good default. Consider |
+ // something related to std::thread::hardware_concurrency(). |
+ cl::init(0)); |
+ |
static int GetReturnValue(int Val) { |
if (AlwaysExitSuccess) |
return 0; |
@@ -288,14 +300,15 @@ int main(int argc, char **argv) { |
Flags.DisableTranslation = DisableTranslation; |
Flags.FunctionSections = FunctionSections; |
Flags.DataSections = DataSections; |
- Flags.UseIntegratedAssembler = UseIntegratedAssembler; |
Flags.UseELFWriter = UseELFWriter; |
+ Flags.UseIntegratedAssembler = UseIntegratedAssembler; |
Flags.UseSandboxing = UseSandboxing; |
Flags.PhiEdgeSplit = EnablePhiEdgeSplit; |
Flags.DecorateAsm = DecorateAsm; |
Flags.DumpStats = DumpStats; |
Flags.AllowUninitializedGlobals = AllowUninitializedGlobals; |
Flags.TimeEachFunction = TimeEachFunction; |
+ Flags.NumTranslationThreads = NumThreads; |
Flags.DefaultGlobalPrefix = DefaultGlobalPrefix; |
Flags.DefaultFunctionPrefix = DefaultFunctionPrefix; |
Flags.TimingFocusOn = TimingFocusOn; |
@@ -351,11 +364,14 @@ int main(int argc, char **argv) { |
Ctx.getObjectWriter()->writeInitialELFHeader(); |
} |
- int ErrorStatus = 0; |
+ Ctx.startWorkerThreads(); |
+ |
+ std::unique_ptr<Ice::Translator> Translator; |
if (BuildOnRead) { |
- Ice::PNaClTranslator Translator(&Ctx, Flags); |
- Translator.translate(IRFilename); |
- ErrorStatus = Translator.getErrorStatus(); |
+ std::unique_ptr<Ice::PNaClTranslator> PTranslator( |
+ new Ice::PNaClTranslator(&Ctx, Flags)); |
+ PTranslator->translate(IRFilename); |
+ Translator.reset(PTranslator.release()); |
} else if (ALLOW_LLVM_IR) { |
// Parse the input LLVM IR file into a module. |
SMDiagnostic Err; |
@@ -370,14 +386,24 @@ int main(int argc, char **argv) { |
return GetReturnValue(1); |
} |
- Ice::Converter Converter(Mod, &Ctx, Flags); |
- Converter.convertToIce(); |
- ErrorStatus = Converter.getErrorStatus(); |
+ std::unique_ptr<Ice::Converter> Converter( |
+ new Ice::Converter(Mod, &Ctx, Flags)); |
+ Converter->convertToIce(); |
+ Translator.reset(Converter.release()); |
} else { |
*Ls << "Error: Build doesn't allow LLVM IR, " |
<< "--build-on-read=0 not allowed\n"; |
return GetReturnValue(1); |
} |
+ |
+ Ctx.waitForWorkerThreads(); |
+ Translator->emitConstants(); |
+ // Error status is the combination of the bitcode parser's error |
jvoung (off chromium)
2015/01/23 22:56:37
Seems like this could be a bit confusing but "tran
Jim Stichnoth
2015/01/25 07:29:39
Good point. Originally, each function tracked its
|
+ // status and the translation error status. |
+ std::error_code ErrorStatus = Translator->getErrorStatus(); |
+ if (!ErrorStatus) |
+ ErrorStatus = Ctx.getErrorStatus(); |
+ |
if (UseELFWriter) { |
Ice::TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx); |
Ctx.getObjectWriter()->writeNonUserSections(); |
@@ -390,5 +416,5 @@ int main(int argc, char **argv) { |
} |
const bool FinalStats = true; |
Ctx.dumpStats("_FINAL_", FinalStats); |
- return GetReturnValue(ErrorStatus); |
+ return GetReturnValue(ErrorStatus.value()); |
} |