This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/JIT/JIT_Compiler.cpp
2015-01-07 10:22:52 +00:00

894 lines
30 KiB
C++

#include "JIT_Compiler.hh"
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <memory>
using namespace std;
#define FREE_ALLOCATED() \
free(buffer); \
free(p->y_u.jhc.jh->cmd); \
free(outputfilename); \
free(optoutputfilename); \
free(cmd1); \
free(cmd2);
#define ADD_PASS_ACCORDING_TO_KIND() \
switch (Kind) { \
case PT_BasicBlock: \
fprintf(stderr, "Oops -- basicblock printer\n"); \
exit(1); \
case PT_Region: \
Pass.add(new RegionPassPrinter(PI)); \
break; \
case PT_Loop: \
Pass.add(new LoopPassPrinter(PI)); \
break; \
case PT_Function: \
Pass.add(new FunctionPassPrinter(PI)); \
break; \
case PT_CallGraphSCC: \
Pass.add(new CallGraphSCCPassPrinter(PI)); \
break; \
default: \
Pass.add(new ModulePassPrinter(PI)); \
break; \
}
#define TREAT_CASE_FOR(PASS) \
PI = PassRegistry::getPassRegistry()->getPassInfo(PASS->getPassID()); \
Kind = PASS->getPassKind(); \
ADD_PASS_ACCORDING_TO_KIND();
#include "PassPrinters.hh"
void JIT_Compiler::analyze_module(llvm::Module* &M)
{
PassManager Pass; // 'Pass' stores analysis passes to be applied
TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(M->getTargetTriple()));
const PassInfo *PI;
PassKind Kind;
Pass.add(TLI); // First, I add on 'Pass' the Target Info of Module
Pass.add(new DataLayoutPass(M)); // Second, I must add Target Data on 'Pass'
for (int i = 0; i < ExpEnv.analysis_struc.n; i++) {
/*
* 'ExpEnv.analysis_struc.act_an' contains sorted analysis passes *
* 'ExpEnv.analysis_struc.act_an' is filled by analysis predicates *
* What must I do? *
* 1. Pass over 'ExpEnv.analysis_struc.act_an' (by previous 'for') *
* 2. For each unity within 'ExpEnv.analysis_struc.act_an' *
* 2.1. Check its type *
* 2.2. Add analysis pass on 'Pass' accordingly the type checked *
*/
switch (ExpEnv.analysis_struc.act_an[i]) {
case e_createAAEvalPass:
TREAT_CASE_FOR(createAAEvalPass());
break;
case e_createBasicAliasAnalysisPass:
TREAT_CASE_FOR(createBasicAliasAnalysisPass());
break;
case e_createAliasAnalysisCounterPass:
TREAT_CASE_FOR(createAliasAnalysisCounterPass());
break;
case e_createGlobalsModRefPass:
TREAT_CASE_FOR(createGlobalsModRefPass());
break;
case e_createInstCountPass:
TREAT_CASE_FOR(createInstCountPass());
break;
case e_createIVUsersPass:
TREAT_CASE_FOR(createIVUsersPass());
break;
case e_createLazyValueInfoPass:
TREAT_CASE_FOR(createLazyValueInfoPass());
break;
//CHANGED FOR LLVM 3.5
case e_createLoopDependenceAnalysisPass:
TREAT_CASE_FOR(createDependenceAnalysisPass());
break;
case e_createLibCallAliasAnalysisPass:
TREAT_CASE_FOR(createLibCallAliasAnalysisPass(NULL));
break;
case e_createLintPass:
TREAT_CASE_FOR(createLintPass());
break;
case e_createMemDepPrinter:
TREAT_CASE_FOR(createMemDepPrinter());
break;
case e_createModuleDebugInfoPrinterPass:
TREAT_CASE_FOR(createModuleDebugInfoPrinterPass());
break;
case e_createNoAAPass:
TREAT_CASE_FOR(createNoAAPass());
break;
//NOT IN LLVM 3.5
//case e_createNoPathProfileInfoPass:
// TREAT_CASE_FOR(createNoPathProfileInfoPass());
// break;
//NOT IN LLVM 3.5
//case e_createNoProfileInfoPass:
// TREAT_CASE_FOR(createNoProfileInfoPass());
// break;
case e_createObjCARCAliasAnalysisPass:
TREAT_CASE_FOR(createObjCARCAliasAnalysisPass());
break;
//NOT IN LLVM 3.5
//case e_createProfileEstimatorPass:
// TREAT_CASE_FOR(createProfileEstimatorPass());
// break;
//CHANGED FOR LLVM 3.5
case e_createProfileLoaderPass:
TREAT_CASE_FOR(createSampleProfileLoaderPass());
break;
//NOT IN LLVM 3.5
//case e_createProfileVerifierPass:
// TREAT_CASE_FOR(createProfileVerifierPass());
// break;
case e_createRegionInfoPass:
TREAT_CASE_FOR(createRegionInfoPass());
break;
case e_createScalarEvolutionAliasAnalysisPass:
TREAT_CASE_FOR(createScalarEvolutionAliasAnalysisPass());
break;
case e_createTypeBasedAliasAnalysisPass:
TREAT_CASE_FOR(createTypeBasedAliasAnalysisPass());
break;
//CHANGED FOR LLVM 3.5
case e_createDbgInfoPrinterPass:
TREAT_CASE_FOR(createDebugInfoVerifierPass());
break;
case e_createCFGPrinterPass:
TREAT_CASE_FOR(createCFGPrinterPass());
break;
case e_createCFGOnlyPrinterPass:
TREAT_CASE_FOR(createCFGOnlyPrinterPass());
break;
case e_createDomPrinterPass:
TREAT_CASE_FOR(createDomPrinterPass());
break;
case e_createDomOnlyPrinterPass:
TREAT_CASE_FOR(createDomOnlyPrinterPass());
break;
case e_createPostDomPrinterPass:
TREAT_CASE_FOR(createPostDomPrinterPass());
break;
case e_createPostDomOnlyPrinterPass:
TREAT_CASE_FOR(createPostDomOnlyPrinterPass());
break;
case e_createRegionPrinterPass:
TREAT_CASE_FOR(createRegionPrinterPass());
break;
case e_createRegionOnlyPrinterPass:
TREAT_CASE_FOR(createRegionOnlyPrinterPass());
break;
//NOT IN LLVM 3.5
//case e_createPathProfileLoaderPass:
// TREAT_CASE_FOR(createPathProfileLoaderPass());
// break;
//NOT IN LLVM 3.5
//case e_createPathProfileVerifierPass:
// TREAT_CASE_FOR(createPathProfileVerifierPass());
// break;
default:;
}
}
/* if 'llvm::TimePassesIsEnabled' is 'true', llvm time passes are printed on 'shutdown_llvm()' (p_halt -- stdpreds.c) */
llvm::TimePassesIsEnabled = ExpEnv.analysis_struc.time_pass_enabled;
/* Use 'llvm::EnableStatistics()' so that llvm stats are printed on 'shutdown_llvm()' (p_halt -- stdpreds.c) */
if (ExpEnv.analysis_struc.stats_enabled) llvm::EnableStatistics();
/*
* Here, I configure resulting analysis output -- default: stderr *
* Use analysis_output_file/1 to change *
*/
if (strcmp(((char*)ExpEnv.analysis_struc.outfile), "STDERR")) { // print to file that is not stderr
int stderrcopy = dup(2); // stderr backup
if (strcmp(((char*)ExpEnv.analysis_struc.outfile), "STDOUT") == 0) { // print to stdout
dup2(1, 2); // 2 is stderr; 1 is stdout -- dup2(1,2) redirects stderr output to stdout
Pass.run(*M); // Run passes (results will be printed on stdout)
dup2(stderrcopy, 2); // Recovers stderr
}
else {
int Outputfile = open(((char*)ExpEnv.analysis_struc.outfile), O_CREAT | O_TRUNC | O_WRONLY, 0777);
// Openning Output file, whose name is on 'ExpEnv.analysis_struc.outfile'
if (Outputfile < 0) {
fprintf(stderr, "Error:: I can not write analysis passes's output on %s...\n", ((char*)ExpEnv.analysis_struc.outfile));
fprintf(stderr, " %s...\n", strerror(errno));
errno = 0;
exit(1);
}
dup2(Outputfile, 2); // 2 is stderr; Outputfile is any other file -- dup2(Outputfile,2) redirects stderr output to Outputfile
Pass.run(*M); // Run passes (results will be printed on Outputfile)
close(Outputfile);
dup2(stderrcopy, 2); // Recovers stderr
}
close(stderrcopy);
}
else // print to stderr
Pass.run(*M); // Run passes (results will be printed on stderr)
}
void JIT_Compiler::optimize_module(llvm::Module* &M)
{
if (ExpEnv.transform_struc.optlevel > -1) { /* Do I need to apply transform level? */
/* Yes, I do, so... */
/* Initializes PassManager for Function */
std::shared_ptr<FunctionPassManager> FPM;
FPM.reset(new FunctionPassManager(M));
FPM->add(new DataLayoutPass(M));
PassManagerBuilder Builder; // aid to 'FPM' and 'MPM'
/* Initializes PassManager for Function */
PassManager MPM;
TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(M->getTargetTriple()));
MPM.add(TLI);
MPM.add(new DataLayoutPass(M));
/* Populates 'Builder' */
Builder.OptLevel = ExpEnv.transform_struc.optlevel;
Builder.DisableUnitAtATime = !ExpEnv.transform_struc.unit_at_time_enabled;
//NOT IN LLVM 3.5
//Builder.DisableSimplifyLibCalls = !ExpEnv.transform_struc.simplify_libcalls_enabled;
/* inline and unrool only be enabled if 'ExpEnv.transform_struc.optlevel' > 0 */
if (ExpEnv.transform_struc.optlevel) Builder.Inliner =
createFunctionInliningPass(ExpEnv.transform_struc.opt_args.inline_threshold);
Builder.DisableUnrollLoops = (ExpEnv.transform_struc.optlevel == 0);
/***/
/***/
/* Populates 'FPM' from 'Builder' */
Builder.populateFunctionPassManager(*FPM);
/* Populates 'MPM' from 'Builder' */
Builder.populateModulePassManager(MPM);
/*
* Enabling link-time optimizations -- default is no *
* Use 'link_time_opt/1', 'link_time_opt/3', 'enable_link_time_opt/0', or 'enable_link_time_opt/2' to change *
*/
if (ExpEnv.transform_struc.link_time_opt.enabled)
Builder.populateLTOPassManager(MPM,
(bool)ExpEnv.transform_struc.link_time_opt.internalize,
(bool)ExpEnv.transform_struc.link_time_opt.runinliner);
/***/
//set_regalloc_pass(MPM);
/* Pass over all functions within Module and run passes */
FPM->doInitialization();
for (Module::iterator F = M->begin(), E = M->end(); F != E; ++F)
FPM->run(*F);
FPM->doFinalization();
/***/
MPM.run(*M); // Run passes on module
}
else {
/* No, I need to apply transform passes accordingly transform predicates but transform_level/1 */
std::vector<GlobalValue*> GVvector; // 'createGVExtractionPass' argument
PassManager Pass; // 'Pass' stores transform passes to be applied
TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(M->getTargetTriple()));
Pass.add(TLI); // First, I add on 'Pass' the Target Info of Module
Pass.add(new DataLayoutPass(M)); // Second, I must add Target Data on 'Pass'
for (int i = 0; i < ExpEnv.transform_struc.n; i++) {
/*
* 'ExpEnv.transform_struc.act_tr' contains sorted transform passes *
* 'ExpEnv.transform_struc.act_tr' is filled by transform predicates *
* What must I do? *
* 1. Pass over 'ExpEnv.transform_struc.act_tr' (by previous 'for') *
* 2. For each unity within 'ExpEnv.analysis_struc.act_an', add transform pass on 'Pass' *
*/
switch (ExpEnv.transform_struc.act_tr[i]) {
case t_createAggressiveDCEPass:
Pass.add(createAggressiveDCEPass());
break;
case t_createArgumentPromotionPass:
Pass.add(createArgumentPromotionPass((Int)ExpEnv.transform_struc.opt_args.arg_promotion_max_elements));
break;
case t_createBBVectorizePass:
Pass.add(createBBVectorizePass());
break;
case t_createBlockExtractorPass:
Pass.add(createBlockExtractorPass());
break;
//NOT IN LLVM 3.5
//case t_createBlockPlacementPass:
// Pass.add(createBlockPlacementPass());
// break;
case t_createBreakCriticalEdgesPass:
Pass.add(createBreakCriticalEdgesPass());
break;
case t_createCFGSimplificationPass:
Pass.add(createCFGSimplificationPass());
break;
case t_createCodeGenPreparePass:
Pass.add(createCodeGenPreparePass());
break;
case t_createConstantMergePass:
Pass.add(createConstantMergePass());
break;
case t_createConstantPropagationPass:
Pass.add(createConstantPropagationPass());
break;
case t_createCorrelatedValuePropagationPass:
Pass.add(createCorrelatedValuePropagationPass());
break;
case t_createDeadArgEliminationPass:
Pass.add(createDeadArgEliminationPass());
break;
case t_createDeadArgHackingPass:
Pass.add(createDeadArgHackingPass());
break;
case t_createDeadCodeEliminationPass:
Pass.add(createDeadCodeEliminationPass());
break;
case t_createDeadInstEliminationPass:
Pass.add(createDeadInstEliminationPass());
break;
case t_createDeadStoreEliminationPass:
Pass.add(createDeadStoreEliminationPass());
break;
case t_createDemoteRegisterToMemoryPass:
Pass.add(createDemoteRegisterToMemoryPass());
break;
case t_createEarlyCSEPass:
Pass.add(createEarlyCSEPass());
break;
case t_createFunctionAttrsPass:
Pass.add(createFunctionAttrsPass());
break;
case t_createFunctionInliningPass:
Pass.add(createFunctionInliningPass(ExpEnv.transform_struc.opt_args.inline_threshold));
break;
case t_createGlobalDCEPass:
Pass.add(createGlobalDCEPass());
break;
case t_createGlobalOptimizerPass:
Pass.add(createGlobalOptimizerPass());
break;
case t_createGVExtractionPass:
Pass.add(createGVExtractionPass(GVvector));
break;
case t_createGVNPass:
Pass.add(createGVNPass());
break;
case t_createIndVarSimplifyPass:
Pass.add(createIndVarSimplifyPass());
break;
case t_createInstructionCombiningPass:
Pass.add(createInstructionCombiningPass());
break;
case t_createInstructionNamerPass:
Pass.add(createInstructionNamerPass());
break;
case t_createInstructionSimplifierPass:
Pass.add(createInstructionSimplifierPass());
break;
case t_createInternalizePass:
Pass.add(createInternalizePass());
break;
case t_createIPConstantPropagationPass:
Pass.add(createIPConstantPropagationPass());
break;
case t_createIPSCCPPass:
Pass.add(createIPSCCPPass());
break;
case t_createJumpThreadingPass:
Pass.add(createJumpThreadingPass());
break;
case t_createLCSSAPass:
Pass.add(createLCSSAPass());
break;
case t_createLICMPass:
Pass.add(createLICMPass());
break;
case t_createLoopDeletionPass:
Pass.add(createLoopDeletionPass());
break;
case t_createLoopExtractorPass:
Pass.add(createLoopExtractorPass());
break;
case t_createLoopIdiomPass:
Pass.add(createLoopIdiomPass());
break;
case t_createLoopInstSimplifyPass:
Pass.add(createLoopInstSimplifyPass());
break;
case t_createLoopRotatePass:
Pass.add(createLoopRotatePass());
break;
case t_createLoopSimplifyPass:
Pass.add(createLoopSimplifyPass());
break;
case t_createLoopStrengthReducePass:
Pass.add(createLoopStrengthReducePass());
break;
case t_createLoopUnrollPass:
Pass.add(createLoopUnrollPass((Int)ExpEnv.transform_struc.opt_args.loop_unroll_threshold));
break;
case t_createLoopUnswitchPass:
Pass.add(createLoopUnswitchPass((bool)ExpEnv.transform_struc.opt_args.loop_unswitch_optimize_for_size));
break;
case t_createLowerAtomicPass:
Pass.add(createLowerAtomicPass());
break;
case t_createLowerExpectIntrinsicPass:
Pass.add(createLowerExpectIntrinsicPass());
break;
case t_createLowerInvokePass:
Pass.add(createLowerInvokePass());
break;
case t_createLowerSwitchPass:
Pass.add(createLowerSwitchPass());
break;
case t_createMemCpyOptPass:
Pass.add(createMemCpyOptPass());
break;
case t_createMergeFunctionsPass:
Pass.add(createMergeFunctionsPass());
break;
case t_createObjCARCAPElimPass:
Pass.add(createObjCARCAPElimPass());
break;
case t_createObjCARCContractPass:
Pass.add(createObjCARCContractPass());
break;
case t_createObjCARCExpandPass:
Pass.add(createObjCARCExpandPass());
break;
case t_createObjCARCOptPass:
Pass.add(createObjCARCOptPass());
break;
case t_createPartialInliningPass:
Pass.add(createPartialInliningPass());
break;
case t_createPromoteMemoryToRegisterPass:
Pass.add(createPromoteMemoryToRegisterPass());
break;
case t_createPruneEHPass:
Pass.add(createPruneEHPass());
break;
case t_createReassociatePass:
Pass.add(createReassociatePass());
break;
case t_createScalarReplAggregatesPass:
Pass.add(createScalarReplAggregatesPass((Int)ExpEnv.transform_struc.opt_args.scalar_replace_aggregates_threshold));
break;
case t_createSCCPPass:
Pass.add(createSCCPPass());
break;
//NOT IN LLVM 3.5
//case t_createSimplifyLibCallsPass:
// Pass.add(createSimplifyLibCallsPass());
// break;
case t_createSingleLoopExtractorPass:
Pass.add(createSingleLoopExtractorPass());
break;
case t_createSinkingPass:
Pass.add(createSinkingPass());
break;
case t_createStripDeadDebugInfoPass:
Pass.add(createStripDeadDebugInfoPass());
break;
case t_createStripDeadPrototypesPass:
Pass.add(createStripDeadPrototypesPass());
break;
case t_createStripDebugDeclarePass:
Pass.add(createStripDebugDeclarePass());
break;
case t_createStripNonDebugSymbolsPass:
Pass.add(createStripNonDebugSymbolsPass());
break;
case t_createStripSymbolsPass:
Pass.add(createStripSymbolsPass((bool)ExpEnv.transform_struc.opt_args.strip_symbols_pass_type));
break;
case t_createTailCallEliminationPass:
Pass.add(createTailCallEliminationPass());
break;
default:;
}
}
//set_regalloc_pass(Pass);
Pass.run(*M); // Run passes
}
}
void JIT_Compiler::set_regalloc_pass(PassManager &PM) {
// 'ExpEnv.codegen_struc.struc_enginebuilder.regallocator' contains the active register allocator to be used
switch(ExpEnv.codegen_struc.struc_enginebuilder.regallocator) {
case REG_ALLOC_BASIC:
PM.add(createBasicRegisterAllocator());
break;
case REG_ALLOC_FAST:
PM.add(createFastRegisterAllocator());
break;
case REG_ALLOC_GREEDY:
PM.add(createGreedyRegisterAllocator());
break;
case REG_ALLOC_PBQP:
PM.add(createDefaultPBQPRegisterAllocator());
break;
}
}
void* JIT_Compiler::compile_all(LLVMContext* &Context, yamop* p)
{
/* Init llvm code generation, analysis and transform passes */
InitializeNativeTarget();
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeCore(Registry);
initializeScalarOpts(Registry);
initializeVectorization(Registry);
initializeIPO(Registry);
initializeAnalysis(Registry);
initializeIPA(Registry);
initializeTransformUtils(Registry);
initializeInstCombine(Registry);
initializeInstrumentation(Registry);
initializeTarget(Registry);
sys::Process::PreventCoreFiles();
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wwrite-strings"
/* CLANG arguments */
char *clang_args[] =
{
"clang", "-fomit-frame-pointer", "-O0",
#if CUT_C
"-DCUT_C=1",
#endif
#if COROUTINING
"-DCOROUTINING=1",
#endif
#if RATIONAL_TREES
"-DRATIONAL_TREES=1",
#endif
#if DEBUG
"-DDEBUG=1",
#endif
#if DEPTH_LIMIT
"-DDEPTH_LIMIT=1",
#endif
#if YAP_DBG_PREDS
"-DYAP_DBG_PREDS=1",
#endif
#if YAP_STAT_PREDS
"-DYAP_STAT_PREDS=1",
#endif
#if TABLING
"-DTABLING=1",
#endif
#if _YAP_NOT_INSTALLED_
"-D_YAP_NOT_INSTALLED_=1",
#endif
#ifdef HAVE_CONFIG_H
"-DHAVE_CONFIG_H",
#endif
"-DYAP_JIT", "-D_NATIVE=1", "-I.", "-I./H", "-I./include", "-I./os", "-I./OPTYap", "-I./BEAM", "-I./MYDDAS", "-I./HPP", "-xc", "-c", "-", "-o", "-", "-emit-llvm", NULL
};
#pragma GCC diagnostic pop
std::string errStr;
error_code e;
/* Pipe to communicate 'echo' with 'clang' */
int pipe1[2];
int pid_echo, pid_clang ;
/* 'clang' out file */
char* outputfilename = (char*)malloc(33*sizeof(char));
sprintf(outputfilename, "%lx.bc", (CELL)p);
int Output = open(outputfilename, O_CREAT | O_RDWR, 0644);
/* Creating pipes */
if (pipe(pipe1)<0) {
perror(" ERROR!!\n ERROR") ;
exit(1);
}
/* Calls echo. */
pid_echo = fork() ;
if (pid_echo < 0) {
perror(" ERROR!!\n ERROR") ;
exit(1);
}
if (!pid_echo) {
/* Setting echo's output to 1st pipe */
dup2(pipe1[1], 1);
/* Closing pipes */
close(pipe1[0]);
close(pipe1[1]);
execlp("echo", "echo", p->y_u.jhc.jh->tcc.cmd, NULL);
}
else {
/* Calls clang. */
pid_clang = fork() ;
if (pid_clang < 0) {
perror(" ERROR!!\n ERROR") ;
exit(1);
}
if (!pid_clang) {
/* Setting clang's input from 1st pipe */
dup2(pipe1[0], 0) ;
/* Setting clang's output to Output */
dup2(Output, 1) ;
/* Closing pipes */
close(pipe1[0]);
close(pipe1[1]);
execvp(*clang_args, clang_args);
}
}
/* Closing pipes */
close(pipe1[0]);
close(pipe1[1]);
/* waiting for completion of processes */
int i;
int *status = NULL;
// 2 means two processes: 'echo' and 'clang'
for (i = 0; i < 2; i++) wait(status);
/***/
/*
* At this point, the compiled code (O0) is on 'Output' *
* I need to read it to main memory *
* for this, I'll use 'MemoryBuffer::getOpenFile' *
*/
lseek(Output, 0, SEEK_SET);
ErrorOr<std::unique_ptr<MemoryBuffer>> em = MemoryBuffer::getOpenFile(Output, outputfilename, -1);
e = em.getError();
if (e) {
errs() << "ERROR::Unable to MemoryBuffer from " << outputfilename << " -- " << e.message() << "\n";
exit(1);
}
/*
* At this point, the compiled code (O0) is on main memory *
* I need to read it to Module *
* for this, I'll use 'parseBitcodeFile' *
*/
Module *Mod = *parseBitcodeFile(em->get(), *Context);
/*
* verify module correctness *
* predicates: *
* enable_module_correctness/1 *
* verify_module_before/0 *
* verify_module_both/0 *
*/
if (ExpEnv.analysis_struc.pointtoverifymodule == BEFORE || ExpEnv.analysis_struc.pointtoverifymodule == BOTH) {
if (verifyModule(*Mod)) {
errs() << "ERROR:: Module not built correctly!\n";
exit(1);
}
}
/***/
#if YAP_DBG_PREDS
/* for debug... print module before optimizing it */
if (ExpEnv.debug_struc.pprint_llva.print_llva_before)
errs() << "Module before optimization::\n" << *Mod;
#endif
/* Analyze module -- analysis predicates */
analyze_module(Mod);
/* Optimize module -- transform predicates */
optimize_module(Mod);
/* Computing size of optimized module */
{
/* Open file 'tmp.bc' which will be filled by optimized Module */
std::shared_ptr<tool_output_file> Out;
std::string ErrorInfo;
Out.reset(new tool_output_file("tmp.bc", ErrorInfo, llvm::sys::fs::F_None));
if (!ErrorInfo.empty()) {
errs() << ErrorInfo << '\n';
exit(1);
}
/* 'createPrintModulePass(arg)' will print Module (now optimized) to on file represented by 'arg' */
PassManager Pass;
Pass.add(createPrintModulePass(Out->os()));
Pass.run(*Mod);
/* 'Out->keep()' will keep printed module to file and will close file */
Out->keep();
/* Open file 'tmp.bc' */
int Outtmp = open("tmp.bc", O_CREAT | O_RDWR, 0644);
#if YAP_STAT_PREDS
/* for statistics... compute file size and store value on 'NativeArea->area.native_size_bytes' */
NativeArea->area.native_size_bytes[p->y_u.jhc.jh->caa.naddress][NativeArea->area.nrecomp[p->y_u.jhc.jh->caa.naddress]-1] = lseek(Outtmp, 0, SEEK_END);
#endif
close(Outtmp);
remove("tmp.bc");
}
/***/
#if YAP_DBG_PREDS
/* for debug... print module after optimizing it */
if (ExpEnv.debug_struc.pprint_llva.print_llva_after)
errs() << "Module after optimization::\n" << *Mod;
#endif
/*
* verify module correctness *
* predicates: *
* enable_module_correctness/0 *
* enable_module_correctness/1 *
* verify_module_after/0 *
* verify_module_both/0 *
*/
if (ExpEnv.analysis_struc.pointtoverifymodule == AFTER || ExpEnv.analysis_struc.pointtoverifymodule == BOTH) {
if (verifyModule(*Mod)) {
errs() << "ERROR:: Module not built correctly!\n";
exit(1);
}
}
/***/
// materializeAllPermanently -- Make sure all GlobalValues in this Module are fully read
error_code materialize_error = Mod->materializeAllPermanently();
if (materialize_error.value() != 0) {
errs() <<"Error:: bitcode didn't read correctly. -- " << materialize_error.message() << "\n";
exit(1);
}
/* Creating EngineBuilder -- called 'builder' */
Function *EntryFn;
EngineBuilder builder(Mod);
builder.setErrorStr(&errStr);
builder.setJITMemoryManager(JITMemoryManager::CreateDefaultMemManager());
builder.setEngineKind(EngineKind::JIT);
// codegen predicate 'engine_opt_level/1'
switch(ExpEnv.codegen_struc.struc_enginebuilder.engineoptlevel) {
case 0:
builder.setOptLevel(CodeGenOpt::None);
break;
case 1:
builder.setOptLevel(CodeGenOpt::Less);
break;
case 2:
builder.setOptLevel(CodeGenOpt::Default);
break;
case 3:
builder.setOptLevel(CodeGenOpt::Aggressive);
break;
}
// codegen predicate 'relocmodel/1'
switch(ExpEnv.codegen_struc.struc_enginebuilder.relocmodel) {
case 0:
builder.setRelocationModel(Reloc::Default);
break;
case 1:
builder.setRelocationModel(Reloc::Static);
break;
case 2:
builder.setRelocationModel(Reloc::PIC_);
break;
case 3:
builder.setRelocationModel(Reloc::DynamicNoPIC);
break;
}
// codegen predicate 'codemodel/1'
switch(ExpEnv.codegen_struc.struc_enginebuilder.codemodel) {
case 0:
builder.setCodeModel(CodeModel::Default);
break;
case 1:
builder.setCodeModel(CodeModel::JITDefault);
break;
case 2:
builder.setCodeModel(CodeModel::Small);
break;
case 3:
builder.setCodeModel(CodeModel::Kernel);
break;
case 4:
builder.setCodeModel(CodeModel::Medium);
break;
case 5:
builder.setCodeModel(CodeModel::Large);
break;
}
// codegen predicates 'enable_mcjit/0' or 'disable_mcjit/0'
builder.setUseMCJIT((bool)ExpEnv.codegen_struc.struc_enginebuilder.usemcjit);
llvm::TargetOptions Options;
{
/* codegen predicates 'enable_framepointer_elimination/0' or 'disable_framepointer_elimination/0' */
Options.NoFramePointerElim = (bool)ExpEnv.codegen_struc.struc_targetopt.noframepointerelim;
//NOT IN LLVM 3.5
//Options.NoFramePointerElimNonLeaf = (bool)ExpEnv.codegen_struc.struc_targetopt.noframepointerelim;
/***/
// codegen predicates 'less_precise_fp_mad_option/0' or 'more_precise_fp_mad_option/0'
Options.LessPreciseFPMADOption = (bool)ExpEnv.codegen_struc.struc_targetopt.lessprecisefpmadoption;
// codegen predicates 'no_excess_fp_precision/0' or 'excess_fp_precision/0'
//NOT IN LLVM 3.5
//Options.NoExcessFPPrecision = (bool)ExpEnv.codegen_struc.struc_targetopt.noexcessfpprecision;
// codegen predicates 'unsafe_fp_math/0' or 'safe_fp_math/0'
Options.UnsafeFPMath = (bool)ExpEnv.codegen_struc.struc_targetopt.unsafefpmath;
// codegen predicates 'rounding_mode_dynamically_changed/0' or 'rounding_mode_not_changed/0'
Options.HonorSignDependentRoundingFPMathOption =
(bool)ExpEnv.codegen_struc.struc_targetopt.honorsigndependentroundingfpmathoption;
// codegen predicates 'no_use_soft_float/0' or 'use_soft_float/0'
Options.UseSoftFloat = (bool)ExpEnv.codegen_struc.struc_targetopt.usesoftfloat;
// codegen predicates 'enable_jit_exception_handling/0' or 'disable_jit_exception_handling/0'
//NOT IN LLVM 3.5
//Options.JITExceptionHandling = (bool)ExpEnv.codegen_struc.struc_targetopt.jitexceptionhandling;
// codegen predicates 'enable_jit_emit_debug_info/0' or 'disable_jit_emit_debug_info/0'
Options.JITEmitDebugInfo = (bool)ExpEnv.codegen_struc.struc_targetopt.jitemitdebuginfo;
// codegen predicates 'enable_jit_emit_debug_info_to_disk/0' or 'disable_jit_emit_debug_info_to_disk/0'
Options.JITEmitDebugInfoToDisk = (bool)ExpEnv.codegen_struc.struc_targetopt.jitemitdebuginfotodisk;
// codegen predicates 'guaranteed_tail_call_opt/0' or 'no_guaranteed_tail_call_opt/0'
Options.GuaranteedTailCallOpt = (bool)ExpEnv.codegen_struc.struc_targetopt.guaranteedtailcallopt;
// codegen predicates 'enable_tail_calls/0' or 'disable_tail_calls/0'
Options.DisableTailCalls = (bool)ExpEnv.codegen_struc.struc_targetopt.disabletailcalls;
// codegen predicates 'enable_fast_isel/0' or 'disable_fast_isel/0'
Options.EnableFastISel = (bool)ExpEnv.codegen_struc.struc_targetopt.fastisel;
}
// codegen predicates 'fp_abitype/1' or 'default_fp_abitype/0'
switch(ExpEnv.codegen_struc.struc_targetopt.floatabitype) {
case 0:
Options.FloatABIType = FloatABI::Default;
break;
case 1:
Options.FloatABIType = FloatABI::Soft;
break;
case 2:
Options.FloatABIType = FloatABI::Hard;
break;
}
builder.setTargetOptions(Options);
/***/
/* Creating ExecutionEngine from EngineBuilder (builder) */
ExecutionEngine *EE = builder.create();
if (!EE) {
if (!errStr.empty())
errs() << "Error creating Execution Engine: " << errStr << "\n";
else
errs() << "Unknown error creating Execution Engine!\n";
exit(1);
}
/***/
// 'clause' is our function -- getting it from Module
EntryFn = Mod->getFunction("clause");
if (!EntryFn) {
/*
* Theoretically, every Module is correct, but *
* for some reason, llvm can not compile some of them *
*/
close(Output);
remove(outputfilename);
free(p->y_u.jhc.jh->tcc.cmd);
free(outputfilename);
return NULL;
}
/* Here, we know that Module was be successfully compiled, so... */
// 1. execute all of the static constructors or destructors for program
EE->runStaticConstructorsDestructors(false);
global++;
close(Output);
remove(outputfilename);
free(p->y_u.jhc.jh->tcc.cmd);
free(outputfilename);
// 2. get native pointer from 'clause' (our function within Module) and return it
return EE->getPointerToFunction(EntryFn);
}
void* JIT_Compiler::compile(yamop* p) {
/* LLVMContext must be declared here, otherwise LLVM will crash on x86_64 machines */
LLVMContext *Context = new LLVMContext();
return compile_all(Context, p);
}