Example #1
0
ExecutionEngine *MCJITHelper::compileModule(Module *M) {
  if (M == OpenModule)
    closeCurrentModule();

  std::string ErrStr;
  ExecutionEngine *NewEngine = EngineBuilder(M)
                                            .setErrorStr(&ErrStr)
                                            .setMCJITMemoryManager(new HelpingMemoryManager(this))
                                            .create();
  if (!NewEngine) {
    fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
    exit(1);
  }

  // Create a function pass manager for this engine
  FunctionPassManager *FPM = new FunctionPassManager(M);

  // Set up the optimizer pipeline.  Start with registering info about how the
  // target lays out data structures.
  FPM->add(new DataLayout(*NewEngine->getDataLayout()));
  // Provide basic AliasAnalysis support for GVN.
  FPM->add(createBasicAliasAnalysisPass());
  // Promote allocas to registers.
  FPM->add(createPromoteMemoryToRegisterPass());
  // Do simple "peephole" optimizations and bit-twiddling optzns.
  FPM->add(createInstructionCombiningPass());
  // Reassociate expressions.
  FPM->add(createReassociatePass());
  // Eliminate Common SubExpressions.
  FPM->add(createGVNPass());
  // Simplify the control flow graph (deleting unreachable blocks, etc).
  FPM->add(createCFGSimplificationPass());
  FPM->doInitialization();

  // For each function in the module
  Module::iterator it;
  Module::iterator end = M->end();
  for (it = M->begin(); it != end; ++it) {
    // Run the FPM on this function
    FPM->run(*it);
  }

  // We don't need this anymore
  delete FPM;

  // Store this engine
  EngineMap[M] = NewEngine;
  NewEngine->finalizeObject();

  return NewEngine;
}
Example #2
0
LLVMExecutionEngineRef
mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb)
{
  std::string Error;

  force_pass_linking ();

#ifdef TARGET_ARM
  LLVMInitializeARMTarget ();
  LLVMInitializeARMTargetInfo ();
  LLVMInitializeARMTargetMC ();
#else
  LLVMInitializeX86Target ();
  LLVMInitializeX86TargetInfo ();
  LLVMInitializeX86TargetMC ();
#endif

  mono_mm = new MonoJITMemoryManager ();
  mono_mm->alloc_cb = alloc_cb;
  mono_mm->dlsym_cb = dlsym_cb;

  //JITExceptionHandling = true;
  // PrettyStackTrace installs signal handlers which trip up libgc
  DisablePrettyStackTrace = true;

  /*
   * The Default code model doesn't seem to work on amd64,
   * test_0_fields_with_big_offsets (among others) crashes, because LLVM tries to call
   * memset using a normal pcrel code which is in 32bit memory, while memset isn't.
   */

  TargetOptions opts;
  opts.JITExceptionHandling = 1;

  EngineBuilder b (unwrap (MP));
#ifdef TARGET_AMD64
  ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setCodeModel (CodeModel::Large).setAllocateGVsWithCode (true).create ();
#else
  ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).create ();
#endif
  g_assert (EE);

#if 0
  ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default, true, Reloc::Default, CodeModel::Large);
  if (!EE) {
	  errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n";
	  g_assert_not_reached ();
  }
#endif

  EE->InstallExceptionTableRegister (exception_cb);
  mono_event_listener = new MonoJITEventListener (emitted_cb);
  EE->RegisterJITEventListener (mono_event_listener);

  fpm = new FunctionPassManager (unwrap (MP));

  fpm->add(new DataLayout(*EE->getDataLayout()));

  PassRegistry &Registry = *PassRegistry::getPassRegistry();
  initializeCore(Registry);
  initializeScalarOpts(Registry);
  //initializeIPO(Registry);
  initializeAnalysis(Registry);
  initializeIPA(Registry);
  initializeTransformUtils(Registry);
  initializeInstCombine(Registry);
  //initializeInstrumentation(Registry);
  initializeTarget(Registry);

  llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "");

  if (PassList.size() > 0) {
	  /* Use the passes specified by the env variable */
	  /* Only the passes in force_pass_linking () can be used */
	  for (unsigned i = 0; i < PassList.size(); ++i) {
		  const PassInfo *PassInf = PassList[i];
		  Pass *P = 0;

		  if (PassInf->getNormalCtor())
			  P = PassInf->getNormalCtor()();
		  fpm->add (P);
	  }
  } else {
	  /* Use the same passes used by 'opt' by default, without the ipo passes */
	  const char *opts = "-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify";
	  char **args;
	  int i;

	  args = g_strsplit (opts, " ", 1000);
	  for (i = 0; args [i]; i++)
		  ;
	  llvm::cl::ParseCommandLineOptions (i, args, "");
	  g_strfreev (args);

	  for (unsigned i = 0; i < PassList.size(); ++i) {
		  const PassInfo *PassInf = PassList[i];
		  Pass *P = 0;

		  if (PassInf->getNormalCtor())
			  P = PassInf->getNormalCtor()();
		  g_assert (P->getPassKind () == llvm::PT_Function || P->getPassKind () == llvm::PT_Loop);
		  fpm->add (P);
	  }

	  /*
	  fpm->add(createInstructionCombiningPass());
	  fpm->add(createReassociatePass());
	  fpm->add(createGVNPass());
	  fpm->add(createCFGSimplificationPass());
	  */
  }

  return wrap(EE);
}
Example #3
0
MonoEERef
mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
{
  std::string Error;
  MonoEE *mono_ee;

  init_llvm ();

  mono_ee = new MonoEE ();

  MonoJITMemoryManager *mono_mm = new MonoJITMemoryManager ();
  mono_mm->alloc_cb = alloc_cb;
  mono_mm->dlsym_cb = dlsym_cb;
  mono_mm->exception_cb = exception_cb;
  mono_ee->mm = mono_mm;

  /*
   * The Default code model doesn't seem to work on amd64,
   * test_0_fields_with_big_offsets (among others) crashes, because LLVM tries to call
   * memset using a normal pcrel code which is in 32bit memory, while memset isn't.
   */

  TargetOptions opts;
  opts.JITExceptionHandling = 1;

  StringRef cpu_name = sys::getHostCPUName ();

  // EngineBuilder no longer has a copy assignment operator (?)
  std::unique_ptr<Module> Owner(unwrap(MP));
  EngineBuilder b (std::move(Owner));
  ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).setMCPU (cpu_name).create ();

  g_assert (EE);
  mono_ee->EE = EE;

  MonoJITEventListener *listener = new MonoJITEventListener (emitted_cb);
  EE->RegisterJITEventListener (listener);
  mono_ee->listener = listener;

  FunctionPassManager *fpm = new FunctionPassManager (unwrap (MP));
  mono_ee->fpm = fpm;

  fpm->add(new DataLayoutPass(*EE->getDataLayout()));

  if (PassList.size() > 0) {
	  /* Use the passes specified by the env variable */
	  /* Only the passes in force_pass_linking () can be used */
	  for (unsigned i = 0; i < PassList.size(); ++i) {
		  const PassInfo *PassInf = PassList[i];
		  Pass *P = 0;

		  if (PassInf->getNormalCtor())
			  P = PassInf->getNormalCtor()();
		  fpm->add (P);
	  }
  } else {
	  /* Use the same passes used by 'opt' by default, without the ipo passes */
	  const char *opts = "-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg";
	  char **args;
	  int i;

	  args = g_strsplit (opts, " ", 1000);
	  for (i = 0; args [i]; i++)
		  ;
	  llvm::cl::ParseCommandLineOptions (i, args, "");
	  g_strfreev (args);

	  for (unsigned i = 0; i < PassList.size(); ++i) {
		  const PassInfo *PassInf = PassList[i];
		  Pass *P = 0;

		  if (PassInf->getNormalCtor())
			  P = PassInf->getNormalCtor()();
		  g_assert (P->getPassKind () == llvm::PT_Function || P->getPassKind () == llvm::PT_Loop);
		  fpm->add (P);
	  }

	  /*
	  fpm->add(createInstructionCombiningPass());
	  fpm->add(createReassociatePass());
	  fpm->add(createGVNPass());
	  fpm->add(createCFGSimplificationPass());
	  */
  }

  *ee = wrap (EE);

  return mono_ee;
}
Example #4
0
int main(int argc, char **argv, char **envp) {
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);
  llvm_shutdown_obj Y;

  InitializeAllTargets();
  InitializeAllTargetInfos();
  InitializeAllTargetDCs();
  InitializeAllTargetMCs();
  InitializeAllAsmParsers();
  InitializeAllDisassemblers();

  cl::ParseCommandLineOptions(argc, argv, "Function disassembler\n");

  ToolName = argv[0];

  std::unique_ptr<MemoryBuffer> FileBuf;
  if (error_code ec = MemoryBuffer::getFile(InputFilename, FileBuf)) {
    errs() << ToolName << ": '" << InputFilename << "': "
           << ec.message() << ".\n";
    return 1;
  }

  ErrorOr<Binary *> BinaryOrErr = createBinary(
    MemoryBuffer::getMemBufferCopy(FileBuf->getBuffer()));
  if (error_code ec = BinaryOrErr.getError()) {
    errs() << ToolName << ": '" << InputFilename << "': "
           << ec.message() << ".\n";
    return 1;
  }
  std::unique_ptr<Binary> binary(BinaryOrErr.get());

  ObjectFile *Obj;
  if (!(Obj = dyn_cast<ObjectFile>(binary.get())))
    errs() << ToolName << ": '" << InputFilename << "': "
           << "Unrecognized file type.\n";

  const Target *TheTarget = getTarget(Obj);

  std::unique_ptr<const MCRegisterInfo> MRI(
    TheTarget->createMCRegInfo(TripleName));
  if (!MRI) {
    errs() << "error: no register info for target " << TripleName << "\n";
    return 1;
  }

  // Set up disassembler.
  std::unique_ptr<const MCAsmInfo> MAI(
    TheTarget->createMCAsmInfo(*MRI, TripleName));
  if (!MAI) {
    errs() << "error: no assembly info for target " << TripleName << "\n";
    return 1;
  }

  std::unique_ptr<const MCSubtargetInfo> STI(
    TheTarget->createMCSubtargetInfo(TripleName, "", ""));
  if (!STI) {
    errs() << "error: no subtarget info for target " << TripleName << "\n";
    return 1;
  }

  std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
  if (!MII) {
    errs() << "error: no instruction info for target " << TripleName << "\n";
    return 1;
  }

  std::unique_ptr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI));
  if (!DisAsm) {
    errs() << "error: no disassembler for target " << TripleName << "\n";
    return 1;
  }

  std::unique_ptr<MCInstPrinter> MIP(
    TheTarget->createMCInstPrinter(0, *MAI, *MII, *MRI, *STI));
  if (!MIP) {
    errs() << "error: no instprinter for target " << TripleName << "\n";
    return 1;
  }

  std::unique_ptr<const MCInstrAnalysis>
    MIA(TheTarget->createMCInstrAnalysis(MII.get()));

  std::unique_ptr<MCObjectDisassembler> OD(
    new MCObjectDisassembler(*Obj, *DisAsm, *MIA));
  std::unique_ptr<MCModule> MCM(OD->buildEmptyModule());

  if (!MCM)
    return 1;

  TransOpt::Level TOLvl;
  switch (TransOptLevel) {
  default:
    errs() << ToolName << ": invalid optimization level.\n";
    return 1;
  case 0: TOLvl = TransOpt::None; break;
  case 1: TOLvl = TransOpt::Less; break;
  case 2: TOLvl = TransOpt::Default; break;
  case 3: TOLvl = TransOpt::Aggressive; break;
  }

  std::unique_ptr<DCRegisterSema> DRS(
      TheTarget->createDCRegisterSema(TripleName, *MRI, *MII));
  if (!DRS) {
    errs() << "error: no dc register sema for target " << TripleName << "\n";
    return 1;
  }
  std::unique_ptr<DCInstrSema> DIS(
      TheTarget->createDCInstrSema(TripleName, *DRS, *MRI, *MII));
  if (!DIS) {
    errs() << "error: no dc instruction sema for target " << TripleName << "\n";
    return 1;
  }

  std::unique_ptr<DCTranslator> DT(new DCTranslator(getGlobalContext(), TOLvl,
                                                    *DIS, *DRS, *MIP,
                                                    *MCM, OD.get(),
                                                    AnnotateIROutput));

  // Now run it !

  Module *Mod = DT->getModule();

  std::string ErrorMsg;

  EngineBuilder Builder(Mod);
  Builder.setErrorStr(&ErrorMsg);
  Builder.setOptLevel(CodeGenOpt::Aggressive);
  Builder.setEngineKind(EngineKind::JIT);
  Builder.setAllocateGVsWithCode(false);

  ExecutionEngine *EE = Builder.create();
  if (!EE) {
    errs() << "error: Unable to create ExecutionEngine: " << ErrorMsg << "\n";
    return -1;
  }

  const DataLayout *DL = EE->getDataLayout();
  const StructLayout *SL = DL->getStructLayout(DRS->getRegSetType());

  uint8_t *RegSet = new uint8_t[SL->getSizeInBytes()];
  const unsigned StackSize = 8192;
  uint8_t *StackPtr = new uint8_t[StackSize];

  std::vector<GenericValue> Args;
  GenericValue GV;
  GV.PointerVal = RegSet; Args.push_back(GV);
  GV.PointerVal = StackPtr; Args.push_back(GV);
  GV.IntVal = APInt(32, StackSize); Args.push_back(GV);
  GV.IntVal = APInt(32, argc - 2); Args.push_back(GV);
  GV.PointerVal = argv + 2; Args.push_back(GV);

  EE->runFunction(DT->getInitRegSetFunction(), Args);

  Args.clear();
  GV.PointerVal = RegSet; Args.push_back(GV);

  unsigned PCSize, PCOffset;
  DRS->getRegOffsetInRegSet(DL, MRI->getProgramCounter(), PCSize, PCOffset);

  __dc_DT = DT.get();
  __dc_EE = EE;

  uint64_t CurPC = DT->getEntrypoint();
  while (CurPC != ~0ULL) {
    Function *Fn = DT->getFunctionAt(CurPC);
    DEBUG(dbgs() << "Executing function " << Fn->getName() << "\n");
    EE->runFunction(Fn, Args);
    CurPC = loadRegFromSet(RegSet, PCOffset, PCSize);
  }

  // Dump the IR we found.
  if (DumpIR)
    Mod->dump();

  GV = EE->runFunction(DT->getFiniRegSetFunction(), Args);
  return GV.IntVal.getZExtValue();
}
Example #5
0
ExecutionEngine *MCJITHelper::compileModule(Module *M) {
    assert(EngineMap.find(M) == EngineMap.end());

    if (M == CurrentModule)
        closeCurrentModule();

    std::string ErrStr;
    ExecutionEngine *EE = EngineBuilder(M)
                          .setErrorStr(&ErrStr)
                          .setMCJITMemoryManager(new HelpingMemoryManager(this))
                          .create();
    if (!EE) {
        fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
        exit(1);
    }

    if (UseObjectCache)
        EE->setObjectCache(&OurObjectCache);
    // Get the ModuleID so we can identify IR input files
    const std::string ModuleID = M->getModuleIdentifier();

    // If we've flagged this as an IR file, it doesn't need function passes run.
    if (0 != ModuleID.compare(0, 3, "IR:")) {
        FunctionPassManager *FPM = 0;

        // Create a FPM for this module
        FPM = new FunctionPassManager(M);

        // Set up the optimizer pipeline.  Start with registering info about how the
        // target lays out data structures.
        FPM->add(new DataLayout(*EE->getDataLayout()));
        // Provide basic AliasAnalysis support for GVN.
        FPM->add(createBasicAliasAnalysisPass());
        // Promote allocas to registers.
        FPM->add(createPromoteMemoryToRegisterPass());
        // Do simple "peephole" optimizations and bit-twiddling optzns.
        FPM->add(createInstructionCombiningPass());
        // Reassociate expressions.
        FPM->add(createReassociatePass());
        // Eliminate Common SubExpressions.
        FPM->add(createGVNPass());
        // Simplify the control flow graph (deleting unreachable blocks, etc).
        FPM->add(createCFGSimplificationPass());

        FPM->doInitialization();

        // For each function in the module
        Module::iterator it;
        Module::iterator end = M->end();
        for (it = M->begin(); it != end; ++it) {
            // Run the FPM on this function
            FPM->run(*it);
        }

        delete FPM;
    }

    EE->finalizeObject();

    // Store this engine
    EngineMap[M] = EE;

    return EE;
}
Example #6
0
void *MCJITHelper::getPointerToFunction(Function* F) {
  // See if an existing instance of MCJIT has this function.
  EngineVector::iterator begin = Engines.begin();
  EngineVector::iterator end = Engines.end();
  EngineVector::iterator it;
  for (it = begin; it != end; ++it) {
    void *P = (*it)->getPointerToFunction(F);
    if (P)
      return P;
  }

  // If we didn't find the function, see if we can generate it.
  if (OpenModule) {
    std::string ErrStr;
    ExecutionEngine *NewEngine = EngineBuilder(OpenModule)
                                              .setErrorStr(&ErrStr)
                                              .setMCJITMemoryManager(new HelpingMemoryManager(this))
                                              .create();
    if (!NewEngine) {
      fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
      exit(1);
    }

    // Create a function pass manager for this engine
    FunctionPassManager *FPM = new FunctionPassManager(OpenModule);

    // Set up the optimizer pipeline.  Start with registering info about how the
    // target lays out data structures.
    FPM->add(new DataLayout(*NewEngine->getDataLayout()));
    // Provide basic AliasAnalysis support for GVN.
    FPM->add(createBasicAliasAnalysisPass());
    // Promote allocas to registers.
    FPM->add(createPromoteMemoryToRegisterPass());
    // Do simple "peephole" optimizations and bit-twiddling optzns.
    FPM->add(createInstructionCombiningPass());
    // Reassociate expressions.
    FPM->add(createReassociatePass());
    // Eliminate Common SubExpressions.
    FPM->add(createGVNPass());
    // Simplify the control flow graph (deleting unreachable blocks, etc).
    FPM->add(createCFGSimplificationPass());
    FPM->doInitialization();

    // For each function in the module
    Module::iterator it;
    Module::iterator end = OpenModule->end();
    for (it = OpenModule->begin(); it != end; ++it) {
      // Run the FPM on this function
      FPM->run(*it);
    }

    // We don't need this anymore
    delete FPM;

    OpenModule = NULL;
    Engines.push_back(NewEngine);
    NewEngine->finalizeObject();
    return NewEngine->getPointerToFunction(F);
  }
  return NULL;
}