Esempio n. 1
0
 main_func_type jit_engine::compile(const ast::Program &prog) {
     llvm::LLVMContext &c=llvm::getGlobalContext();
     llvm::Module *m=new llvm::Module("brainfuck", c);
     brainfuck::codegen(*m, prog);
     //m->dump();
     
     std::string ErrStr;
     ExecutionEngine *TheExecutionEngine = EngineBuilder(m).setErrorStr(&ErrStr).create();
     if (!TheExecutionEngine) {
         fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
         exit(1);
     }
     Function *f_main=m->getFunction("main");
     
     // Optimize, target dependant
     if(optimization_level_>0)
     {
         FunctionPassManager OurFPM(m);
         
         // Set up the optimizer pipeline.  Start with registering info about how the
         // target lays out data structures.
         OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
         // Provide basic AliasAnalysis support for GVN.
         OurFPM.add(createBasicAliasAnalysisPass());
         // Do simple "peephole" optimizations and bit-twiddling optzns.
         OurFPM.add(createInstructionCombiningPass());
         // Reassociate expressions.
         OurFPM.add(createReassociatePass());
         // Eliminate Common SubExpressions.
         OurFPM.add(createGVNPass());
         // Simplify the control flow graph (deleting unreachable blocks, etc).
         OurFPM.add(createCFGSimplificationPass());
         //OurFPM.add(createLoopSimplifyPass());
         //OurFPM.add(createBlockPlacementPass());
         //OurFPM.add(createConstantPropagationPass());
         
         OurFPM.doInitialization();
      
         OurFPM.run(*f_main);
     }
     
     //m->dump();
     
     void *rp=TheExecutionEngine->getPointerToFunction(f_main);
     main_func_type fp=reinterpret_cast<main_func_type>(rp);
     return fp;
 }
Esempio n. 2
0
void CouchRunner::runIR( CouchWorkingMemory *wm ){
  /*
  Module *theM;
  theM = ParseBitcodeFile( MemoryBuffer::getFile("out.bc"), 
			   getGlobalContext(),
			   &error );
  */

  // Loads intermediate representation source
  std::string error;
  SMDiagnostic Err;
  std::auto_ptr<Module> theM(ParseAssemblyFile( fSourceFile, Err, getGlobalContext() ));
  std::cout << "KBVM v1.0 (experimental)\nIntermediate Representation Interpreter\n";  
  std::cout << "Parsing " << fSourceFile << "\n";
  // Verifies module
  try{
    std::string VerifErr;
    if (verifyModule( *theM.get(), ReturnStatusAction, &VerifErr)) {
      errs() << fSourceFile
	     << ": assembly parsed, but does not verify as correct!\n";
      errs() << VerifErr;
      return;
    }
  }
  catch(...){
    std::cerr << "Verification of module failed!\n";
    return;
  }
  // Prepares to execute
  S_wm = wm;

  IRBuilder<>  theBuilder( getGlobalContext() );
  // Create the JIT.
  S_TheExecutionEngine = ExecutionEngine::create(theM.get());

  //ExistingModuleProvider OurModuleProvider( M );
  FunctionPassManager OurFPM( theM.get() );
      
  // Set up the optimizer pipeline.  
  // Start with registering info about how the
  // target lays out data structures.
  OurFPM.add(new TargetData(*S_TheExecutionEngine->getTargetData()));
  // Promote allocas to registers.
  OurFPM.add(createPromoteMemoryToRegisterPass());
  // Do simple "peephole" optimizations and bit-twiddling optzns.
  OurFPM.add(createInstructionCombiningPass());
  // Reassociate expressions.
  OurFPM.add(createReassociatePass());
  // Eliminate Common SubExpressions.
  OurFPM.add(createGVNPass());
  // Simplify the control flow graph (deleting unreachable blocks, etc).
  OurFPM.add(createCFGSimplificationPass());

  // Set the global so the code gen can use this.
  S_TheFPM = &OurFPM;

  // Inital setup of the agenda
  unsigned int i;
  CouchRunner::S_Agenda->reset();

  // Initial setup of the working memory
  S_TheFPM->run( *theM->getFunction("ag_forward") );

  std::string sign, val;
  Function *FFwrd = S_TheExecutionEngine->FindFunctionNamed( "ag_forward" );
  void *FFwrdPtr = S_TheExecutionEngine->getPointerToFunction(FFwrd);
  void (*FFwrdP)(const char*) = (void (*)( const char*))FFwrdPtr;
  DOMElement *elt;

  DOMNodeList *domSuggests = 
    fDom->getElementsByTagName( XMLString::transcode("suggest") );
  for( i = 0; i < domSuggests->getLength(); i++ ){
    CouchRunner::S_Agenda->push( std::string(XMLString::transcode( ((DOMText *)(domSuggests->item(i)->getFirstChild()))->getData() )), S_wm );
  }

  DOMNodeList *domVolunteers = 
    fDom->getElementsByTagName( XMLString::transcode("volunteer") );
  for( i = 0; i < domVolunteers->getLength(); i++ ){
    elt = (DOMElement *)(domVolunteers->item(i));
    sign = std::string( XMLString::transcode( ((DOMText *)(elt->getElementsByTagName(XMLString::transcode("var"))->item(0)->getFirstChild()))->getData() ) );
    val = std::string( XMLString::transcode( ((DOMText *)(elt->getElementsByTagName(XMLString::transcode("const"))->item(0)->getFirstChild()))->getData() ) );
    // TODO: update with type information
    if( std::string("true") == val ){
      S_wm->set( sign.c_str(), (int)1 );
    }
    else if( std::string("false") == val ){
      S_wm->set( sign.c_str(), (int)0 );
    }
    else if( isalpha( *(val.c_str()) ) ){
      S_wm->set( sign.c_str(), val.c_str() );
    }
    else{
      double d = strtod( val.c_str(), NULL );
      S_wm->set( sign.c_str(), d );
    }
    // Update agenda as if forwarded from execution
    FFwrdP( sign.c_str() );
  }


  std::cout << "Session Started\n" << *S_wm << *CouchRunner::S_Agenda;

  {
    // Creates the `entry' function that sets up the Agenda, which
    // also serves as continuation for the postponed calls
    std::vector<Value *> args;
    Function *Main;


    while( !CouchRunner::S_Agenda->empty() ){

      // Erase previous entry function if present
      if( NULL != (Main = theM->getFunction("entry")) ){
	Main->eraseFromParent();
      }
      // Creates code block
      Main = cast<Function>(
			    theM->getOrInsertFunction( "entry", 
						       Type::getInt32Ty(getGlobalContext()), 
						       (Type *)0)
			    );
      BasicBlock *EB = BasicBlock::Create(getGlobalContext(), 
					  "EntryBlock", Main);
      theBuilder.SetInsertPoint(EB);
      // Loops through the current agenda
      Value *res = NULL, *call;
      std::string hypo;

      // Copies agenda to current Agenda
	
      while( !CouchRunner::S_Agenda->empty() ){
	hypo = CouchRunner::S_Agenda->pop();
	if( WorkingMemory::WM_UNKNOWN == S_wm->knownp( hypo.c_str() ) ){
	  call = theBuilder.CreateCall(theM->getFunction( hypo ),
				       args.begin(),
				       args.end(), "suggest");
	  res = 
	    theBuilder.CreateIntCast( call, 
				      Type::getInt32Ty(getGlobalContext()), 
				      false, "cast_tmp" );
	}
      }
      theBuilder.CreateRet( res == NULL ? 
			    ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 2) : 
			    res );
      // Check it
      S_TheFPM->run( *Main );
      // Run it
      Function *F = S_TheExecutionEngine->FindFunctionNamed( "entry" );
      void *FPtr = S_TheExecutionEngine->getPointerToFunction(F);
      typedef int (*PFN)();
      PFN FP = reinterpret_cast<PFN>( FPtr );
      //      int (*FP)() = (int (*)())FPtr;
      printf( "Result = %d\n", FP() );
      std::cout << *S_wm << std::endl;
      std::cout << *CouchRunner::S_Agenda << std::endl;
    }  
    S_wm = NULL;
  }
}
Esempio n. 3
0
int main() {
  llvm::InitializeNativeTarget();

  // Make the module, which holds all the code.
  llvm::Module *TheModule = new llvm::Module("my cool jit", llvm::getGlobalContext());

  // Create the JIT.  This takes ownership of the module.
  std::string ErrStr;
  llvm::ExecutionEngine *TheExecutionEngine = llvm::EngineBuilder(TheModule).setErrorStr(&ErrStr).create();
  if (!TheExecutionEngine) {
    fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
    exit(1);
  }

  llvm::FunctionPassManager OurFPM(TheModule);

  // Set up the optimizer pipeline.  Start with registering info about how the
  // target lays out data structures.
  OurFPM.add(new llvm::TargetData(*TheExecutionEngine->getTargetData()));
  // Do simple "peephole" optimizations and bit-twiddling optzns.
  OurFPM.add(llvm::createInstructionCombiningPass());
  // Reassociate expressions.
  OurFPM.add(llvm::createReassociatePass());
  // Eliminate Common SubExpressions.
  OurFPM.add(llvm::createGVNPass());
  // Simplify the control flow graph (deleting unreachable blocks, etc).
  OurFPM.add(llvm::createCFGSimplificationPass());

  OurFPM.doInitialization();

  // Set the global so the code gen can use this.
  llvm::FunctionPassManager *TheFPM = &OurFPM;

  // Single argument
  std::vector<const llvm::Type*> unaryArg(1,llvm::Type::getDoubleTy(llvm::getGlobalContext()));

  // Two arguments
  std::vector<const llvm::Type*> binaryArg(2,llvm::Type::getDoubleTy(llvm::getGlobalContext()));
  
  // Two arguments in and two references
  std::vector<const llvm::Type*> genArg(4);
  genArg[0] = genArg[1] = llvm::Type::getDoubleTy(llvm::getGlobalContext());
  genArg[2] = genArg[3] = llvm::Type::getDoublePtrTy(llvm::getGlobalContext());
  
  // Unary operation
  llvm::FunctionType *unaryFun = llvm::FunctionType::get(llvm::Type::getDoubleTy(llvm::getGlobalContext()),unaryArg, false);

  // Binary operation
  llvm::FunctionType *binaryFun = llvm::FunctionType::get(llvm::Type::getDoubleTy(llvm::getGlobalContext()),binaryArg, false);

  // More generic operation, return by reference
  llvm::FunctionType *genFun = llvm::FunctionType::get(llvm::Type::getVoidTy(llvm::getGlobalContext()),genArg, false);

  // Declare sin
  llvm::Function *sin_ = llvm::Function::Create(unaryFun, llvm::Function::ExternalLinkage, "sin", TheModule);
  
  // Declare my function
  llvm::Function *myfun = llvm::Function::Create(genFun, llvm::Function::ExternalLinkage, "myfcn", TheModule);

  // Create a new basic block to start insertion into.
  llvm::BasicBlock *BB = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", myfun);
  Builder.SetInsertPoint(BB);

  // Set names for all arguments.
  llvm::Function::arg_iterator AI = myfun->arg_begin();
  AI->setName("x1");
  llvm::Value *x1 = AI;
  AI++;
  AI->setName("x2");
  llvm::Value *x2 = AI;
  AI++;
  AI->setName("r1");
  llvm::Value *r1 = AI;
  AI++;
  AI->setName("r2");
  llvm::Value *r2 = AI;
  
  llvm::Value *five = llvm::ConstantFP::get(llvm::getGlobalContext(), llvm::APFloat(5.0));
  llvm::Value *x1_plus_5 = Builder.CreateFAdd(x1, five, "x1_plus_5");
  
  // Call the sine function
  std::vector<llvm::Value*> sinarg(1,x2);
  llvm::Value* sin_x2 = Builder.CreateCall(sin_, sinarg.begin(), sinarg.end(), "callsin");
  
  // Set values
  llvm::StoreInst *what_is_this1 = Builder.CreateStore(sin_x2,r1);
  llvm::StoreInst *what_is_this2 = Builder.CreateStore(x1_plus_5,r2);

  // Finish off the function.
  Builder.CreateRetVoid();

  // Validate the generated code, checking for consistency.
  verifyFunction(*myfun);

  // Optimize the function.
  TheFPM->run(*myfun);

  // Print out all of the generated code.
  TheModule->dump();

  // JIT the function
  double x1_val = 10;
  double x2_val = 20;
  double r1_val = -1;
  double r2_val = -1;
  typedef void (*GenType)(double,double,double*,double*);
  GenType FP = GenType(intptr_t(TheExecutionEngine->getPointerToFunction(myfun)));

  FP(x1_val,x2_val,&r1_val,&r2_val);

  printf("r1 = %g\n", r1_val);
  printf("r2 = %g\n", r2_val);
  

  return 0;
}
Esempio n. 4
0
static int Execute(llvm::Module *Mod)
{
	llvm::InitializeNativeTarget();
	std::string Error;
	llvm::OwningPtr<llvm::ExecutionEngine> EE(llvm::ExecutionEngine::createJIT(Mod, &Error, 0, llvm::CodeGenOpt::Aggressive));
	if (!EE)
	{
		llvm::errs() << "unable to make execution engine: " << Error << "\n";
		return 255;
	}

	//should get a better way to resolve the name? (c++filt like)
	llvm::Function *EntryFn = Mod->getFunction("_Z4testii");
	if (!EntryFn)
	{
		llvm::errs() << "'_Z4testii' function not found in module.\n";
		return 255;
	}


	// Validate the generated code, checking for consistency.
	llvm::verifyFunction(*EntryFn);

	//now further optimize here i guess
	llvm::FunctionPassManager OurFPM(Mod);

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

	OurFPM.doInitialization();

	// Optimize the function.
	OurFPM.run(*EntryFn);

	std::vector<std::string> Args;
	Args.push_back(Mod->getModuleIdentifier());

	for(unsigned int i = 0; i < Args.size(); ++i)
	{
		printf("mod argumend[%i]: %s", i, Args[0].c_str());
	}

	void *FPtr = EE->getPointerToFunction(EntryFn);

	if(!FPtr)
	{
		llvm::errs() << "unable to get pointer to function.\n";
		return 1;
	}

//	A b;
//	b.b = 666;
//
//	void (*FP)(A) = (void (*)(A))(intptr_t)FPtr;
//
//	FP(b);


//	void (*FP)() = (void (*)())(intptr_t)FPtr;
//
//	FP();

	int (*FP)(int, int) = (int (*)(int, int))(intptr_t)FPtr;

	int c = FP(4, 30);
	printf("\n\nresult is %i\n", c);



	//cleanup
	EntryFn->eraseFromParent();

	EE->removeModule(Mod);

	delete Mod;


	return 0;
}