922 lines
31 KiB
C++
922 lines
31 KiB
C++
#include "JIT_Compiler.hpp"
|
|
#include <unistd.h>
|
|
#include <sys/wait.h>
|
|
#include <fcntl.h>
|
|
//using namespace std;
|
|
//using namespace llvm;
|
|
|
|
#include <llvm/Pass.h>
|
|
#include <llvm/PassAnalysisSupport.h>
|
|
#include <llvm/PassInfo.h>
|
|
#include <llvm/PassManager.h>
|
|
#include <llvm/PassRegistry.h>
|
|
#include <llvm/PassSupport.h>
|
|
#include <llvm/Analysis/CallGraphSCCPass.h>
|
|
#include <llvm/CodeGen/Passes.h>
|
|
|
|
#include "PassPrinters.hh"
|
|
|
|
#define FREE_ALLOCATED() \
|
|
free(buffer); \
|
|
free(p->y_u.J.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(PInfo)); \
|
|
break; \
|
|
case PT_Loop: \
|
|
Pass.add(new LoopPassPrinter(PInfo)); \
|
|
break; \
|
|
case PT_Function: \
|
|
Pass.add(new FunctionPassPrinter(PInfo)); \
|
|
break; \
|
|
case PT_CallGraphSCC: \
|
|
Pass.add(new CallGraphSCCPassPrinter(PInfo)); \
|
|
break; \
|
|
default: \
|
|
Pass.add(new ModulePassPrinter(PInfo)); \
|
|
break; \
|
|
}
|
|
|
|
#define TREAT_CASE_FOR(PASS) \
|
|
PInfo = PassRegistry::getPassRegistry()->getPassInfo(PASS->getPassID()); \
|
|
Kind = PASS->getPassKind(); \
|
|
ADD_PASS_ACCORDING_TO_KIND();
|
|
|
|
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 *PInfo;
|
|
PassKind Kind;
|
|
|
|
Pass.add(TLI); // First, I add on 'Pass' the Target Info of Module
|
|
Pass.add(new DataLayoutPass()); // 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 legacy::FunctionPassManager(M));
|
|
FPM->add(new DataLayoutPass());
|
|
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());
|
|
|
|
/* 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()); // 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.J.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' *
|
|
*/
|
|
ErrorOr<Module *> ModuleOrErr =
|
|
parseBitcodeFile(em.get()->getMemBufferRef(), *Context);
|
|
|
|
std::unique_ptr<Module> M;
|
|
|
|
if (std::error_code ec = ModuleOrErr.getError())
|
|
errs() << ec.message();
|
|
/* at last, get M */
|
|
M.reset(ModuleOrErr.get());
|
|
/*
|
|
* 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(*M)) {
|
|
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
|
|
|
|
llvm::Module *Mod = M.get();
|
|
/* Analyze module -- analysis predicates */
|
|
analyze_module(Mod);
|
|
/* Optimize module -- transform predicates */
|
|
optimize_module(Mod);
|
|
|
|
/* Computing size of optimized module */
|
|
{
|
|
std::error_code ErrorInfo;
|
|
/* Open file 'tmp.bc' which will be filled by optimized Module */
|
|
std::unique_ptr<tool_output_file> Out;
|
|
Out.reset(new tool_output_file("tmp.bc", ErrorInfo, llvm::sys::fs::F_None));
|
|
if (ErrorInfo) {
|
|
errs() << ErrorInfo.message() << '\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(*M);
|
|
/* '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;
|
|
|
|
llvm::CodeGenOpt::Level level;
|
|
switch(ExpEnv.codegen_struc.struc_enginebuilder.engineoptlevel) {
|
|
case 0:
|
|
level = CodeGenOpt::None;
|
|
break;
|
|
case 1:
|
|
level = CodeGenOpt::Less;
|
|
break;
|
|
case 2:
|
|
level = CodeGenOpt::Default;
|
|
break;
|
|
case 3:
|
|
level = CodeGenOpt::Aggressive;
|
|
break;
|
|
}
|
|
// codegen predicate 'relocmodel/1'
|
|
llvm::Reloc::Model relocmodel;
|
|
switch(ExpEnv.codegen_struc.struc_enginebuilder.relocmodel) {
|
|
case 0:
|
|
relocmodel = Reloc::Default;
|
|
break;
|
|
case 1:
|
|
relocmodel = Reloc::Static;
|
|
break;
|
|
case 2:
|
|
relocmodel = Reloc::PIC_;
|
|
break;
|
|
case 3:
|
|
relocmodel = Reloc::DynamicNoPIC;
|
|
break;
|
|
}
|
|
// codegen predicate 'codemodel/1'
|
|
llvm::CodeModel::Model codemodel;
|
|
switch(ExpEnv.codegen_struc.struc_enginebuilder.codemodel) {
|
|
case 0:
|
|
codemodel = CodeModel::Default;
|
|
break;
|
|
case 1:
|
|
codemodel = CodeModel::JITDefault;
|
|
break;
|
|
case 2:
|
|
codemodel = CodeModel::Small;
|
|
break;
|
|
case 3:
|
|
codemodel = CodeModel::Kernel;
|
|
break;
|
|
case 4:
|
|
codemodel = CodeModel::Medium;
|
|
break;
|
|
case 5:
|
|
codemodel = CodeModel::Large;
|
|
break;
|
|
}
|
|
// MCJIT is default from 3.6
|
|
// 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;
|
|
}
|
|
|
|
// codegen predicate 'engine_opt_level/1'
|
|
|
|
/* Creating ExecutionEngine from EngineBuilder (builder) */
|
|
ExecutionEngine *EE =
|
|
EngineBuilder(std::move(M))
|
|
.setErrorStr(&errStr)
|
|
.setOptLevel( level )
|
|
.setRelocationModel( relocmodel )
|
|
.setCodeModel( codemodel )
|
|
.setEngineKind(EngineKind::JIT)
|
|
.setTargetOptions(Options)
|
|
// check class in Kaleidoscope example.
|
|
// .setMCJITMemoryManager(std::unique_ptr<HelpingMemoryManager>(
|
|
// new HelpingMemoryManager(this)))
|
|
.setMCJITMemoryManager(std::unique_ptr<SectionMemoryManager>(new SectionMemoryManager()))
|
|
.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.J.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++; what is this?
|
|
close(Output);
|
|
remove(outputfilename);
|
|
free(p->y_u.J.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);
|
|
}
|