+ // Generate the bitcode for the optimized module.
+ std::string RealBitcodeOutput = OutputFilename;
+
+ if (!LinkAsLibrary) RealBitcodeOutput += ".bc";
+ GenerateBitcode(Composite.get(), RealBitcodeOutput);
+
+ // If we are not linking a library, generate either a native executable
+ // or a JIT shell script, depending upon what the user wants.
+ if (!LinkAsLibrary) {
+ // If the user wants to run a post-link optimization, run it now.
+ if (!PostLinkOpts.empty()) {
+ std::vector<std::string> opts = PostLinkOpts;
+ for (std::vector<std::string>::iterator I = opts.begin(),
+ E = opts.end(); I != E; ++I) {
+ sys::Path prog(*I);
+ if (!prog.canExecute()) {
+ prog = sys::Program::FindProgramByName(*I);
+ if (prog.isEmpty())
+ PrintAndExit(std::string("Optimization program '") + *I +
+ "' is not found or not executable.");
+ }
+ // Get the program arguments
+ sys::Path tmp_output("opt_result");
+ std::string ErrMsg;
+ if (tmp_output.createTemporaryFileOnDisk(true, &ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ const char* args[4];
+ args[0] = I->c_str();
+ args[1] = RealBitcodeOutput.c_str();
+ args[2] = tmp_output.c_str();
+ args[3] = 0;
+ if (0 == sys::Program::ExecuteAndWait(prog, args, 0,0,0,0, &ErrMsg)) {
+ if (tmp_output.isBitcodeFile() || tmp_output.isBitcodeFile()) {
+ sys::Path target(RealBitcodeOutput);
+ target.eraseFromDisk();
+ if (tmp_output.renamePathOnDisk(target, &ErrMsg))
+ PrintAndExit(ErrMsg, 2);
+ } else
+ PrintAndExit("Post-link optimization output is not bitcode");
+ } else {
+ PrintAndExit(ErrMsg);
+ }
+ }
+ }
+
+ // If the user wants to generate a native executable, compile it from the
+ // bitcode file.
+ //
+ // Otherwise, create a script that will run the bitcode through the JIT.
+ if (Native) {
+ // Name of the Assembly Language output file
+ sys::Path AssemblyFile ( OutputFilename);
+ AssemblyFile.appendSuffix("s");
+
+ // Mark the output files for removal if we get an interrupt.
+ sys::RemoveFileOnSignal(AssemblyFile);
+ sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+
+ // Determine the locations of the llc and gcc programs.
+ sys::Path llc = FindExecutable("llc", argv[0]);
+ if (llc.isEmpty())
+ PrintAndExit("Failed to find llc");
+
+ sys::Path gcc = FindExecutable("gcc", argv[0]);
+ if (gcc.isEmpty())
+ PrintAndExit("Failed to find gcc");
+
+ // Generate an assembly language file for the bitcode.
+ std::string ErrMsg;
+ if (0 != GenerateAssembly(AssemblyFile.toString(), RealBitcodeOutput,
+ llc, ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ if (0 != GenerateNative(OutputFilename, AssemblyFile.toString(),
+ NativeLinkItems, gcc, envp, ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ // Remove the assembly language file.
+ AssemblyFile.eraseFromDisk();
+ } else if (NativeCBE) {
+ sys::Path CFile (OutputFilename);
+ CFile.appendSuffix("cbe.c");
+
+ // Mark the output files for removal if we get an interrupt.
+ sys::RemoveFileOnSignal(CFile);
+ sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+
+ // Determine the locations of the llc and gcc programs.
+ sys::Path llc = FindExecutable("llc", argv[0]);
+ if (llc.isEmpty())
+ PrintAndExit("Failed to find llc");
+
+ sys::Path gcc = FindExecutable("gcc", argv[0]);
+ if (gcc.isEmpty())
+ PrintAndExit("Failed to find gcc");
+
+ // Generate an assembly language file for the bitcode.
+ std::string ErrMsg;
+ if (0 != GenerateCFile(
+ CFile.toString(), RealBitcodeOutput, llc, ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ if (0 != GenerateNative(OutputFilename, CFile.toString(),
+ NativeLinkItems, gcc, envp, ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ // Remove the assembly language file.
+ CFile.eraseFromDisk();
+
+ } else {
+ EmitShellScript(argv);
+ }
+
+ // Make the script executable...
+ std::string ErrMsg;
+ if (sys::Path(OutputFilename).makeExecutableOnDisk(&ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ // Make the bitcode file readable and directly executable in LLEE as well
+ if (sys::Path(RealBitcodeOutput).makeExecutableOnDisk(&ErrMsg))
+ PrintAndExit(ErrMsg);
+
+ if (sys::Path(RealBitcodeOutput).makeReadableOnDisk(&ErrMsg))
+ PrintAndExit(ErrMsg);
+ }
+ } catch (const std::string& msg) {
+ PrintAndExit(msg,2);
+ } catch (...) {
+ PrintAndExit("Unexpected unknown exception occurred.", 2);