Beispiel #1
0
//================================================
// Lambda-Calculus ASTs
//================================================
//Lambda
llvm::Function* LambdaAST::codeGen() const
{
//    namedValues.clear();
    llvm::Function* func = proto->codeGen();

    if(!func)
        return NULL;

    // Create a new basic block to start insertion into.
    BasicBlock* entry = BasicBlock::Create(getGlobalContext(), "entry", func);

    ExprAST::builder.SetInsertPoint(entry);

    Value* returnVal = body->codeGen();

    if(returnVal)
    {
        // Finish off the function
        ExprAST::builder.CreateRet(returnVal);

        // Validate the generated code, checking for consistency.
        verifyFunction(*func);
        //        std::cout << "module: " << module << std::endl;
        // optimize the function
        passManager->run(*func);

        return func;
    }

    // Error reading Body, remove function
    func->eraseFromParent();
    return NULL;
}
MooseParsedFunction::MooseParsedFunction(const InputParameters & parameters) :
    Function(parameters),
    MooseParsedFunctionBase(parameters),
    _value(verifyFunction(getParam<std::string>("value"))),
    _function_ptr(NULL)
{
}
// DEPRECATED CONSTRUCTOR
MooseParsedFunction::MooseParsedFunction(const std::string & deprecated_name, InputParameters parameters) :
    Function(deprecated_name, parameters),
    MooseParsedFunctionBase(parameters),
    _value(verifyFunction(getParam<std::string>("value"))),
    _function_ptr(NULL)
{
}
llvm::Function* LLVMCSRMatrixTest::getCSRMatrixGetNZTestFunc()
{
    LLVMContext &ctx = context.getContext();
    IRBuilder<> &builder = context.getBuilder();
    Module *module = context.getModule();

    getFunc = module->getFunction("test_csr_matrix_get_nz");

    if (getFunc == 0)
    {
        // double csr_matrix_get_nz(const csr_matrix *mat, int row, int col);
        Type *argTypes[] = {
            ModelDataIRBuilder::getCSRSparseStructType(module)->getPointerTo(),
            Type::getInt32Ty(module->getContext()),
            Type::getInt32Ty(module->getContext())
        };

        FunctionType *funcType = FunctionType::get(
                                     Type::getDoubleTy(module->getContext()),
                                     argTypes, false);
        getFunc = Function::Create(funcType, Function::InternalLinkage,
                                   "test_csr_matrix_get_nz", module);

        // Create a new basic block to start insertion into.
        BasicBlock *BB = BasicBlock::Create(context.getContext(), "entry",
                                            getFunc);
        builder.SetInsertPoint(BB);

        std::vector<Value*> args;

        // Set names for all arguments.
        unsigned idx = 0;
        for (Function::arg_iterator ai = getFunc->arg_begin();
                ai != getFunc->arg_end(); ++ai)
        {

            args.push_back(ai);
        }

        LLVMModelDataIRBuilderTesting mdirbuilder(LLVMModelDataSymbols(), builder);

        mdirbuilder.createDispInt(args[1]);
        mdirbuilder.createDispInt(args[2]);

        CallInst *call = ModelDataIRBuilder::createCSRMatrixGetNZ(builder, args[0], args[1],
                         args[2], "nz_val");

        mdirbuilder.createDispDouble(call);

        builder.CreateRet(call);

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

        getFunc->dump();

    }

    return setFunc;
}
MooseParsedVectorFunction::MooseParsedVectorFunction(const InputParameters & parameters) :
    Function(parameters),
    MooseParsedFunctionBase(parameters),
    _vector_value(verifyFunction(std::string("{") + getParam<std::string>("value_x") + "}{" +
                                 getParam<std::string>("value_y") + "}{" +
                                 getParam<std::string>("value_z") + "}"))
{
}
Beispiel #6
0
/**
 * @brief Create llvm JIT Function and translate instructions to fill the JIT Function.
 *	Optimize the llvm IR and save the function and its entry address to map.
 *
 * @param cpu CPU core structure
 */
static void
cpu_translate_function(cpu_t *cpu)
{
	BasicBlock *bb_ret, *bb_trap, *label_entry, *bb_start;

	addr_t start_addr = cpu->f.get_pc(cpu, cpu->rf.grf);

	/* create function and fill it with std basic blocks */
	cpu->dyncom_engine->cur_func = cpu_create_function(cpu, "jitmain", &bb_ret, &bb_trap, &label_entry);

	/* TRANSLATE! */
	UPDATE_TIMING(cpu, TIMER_FE, true);
	if (cpu->dyncom_engine->flags_debug & CPU_DEBUG_SINGLESTEP) {
		bb_start = cpu_translate_singlestep(cpu, bb_ret, bb_trap);
	} else if (cpu->dyncom_engine->flags_debug & CPU_DEBUG_SINGLESTEP_BB) {
		bb_start = cpu_translate_singlestep_bb(cpu, bb_ret, bb_trap);
	} else {
		bb_start = cpu_translate_all(cpu, bb_ret, bb_trap);
	}
	UPDATE_TIMING(cpu, TIMER_FE, false);

	/* finish entry basicblock */
	BranchInst::Create(bb_start, label_entry);

	/* make sure everything is OK */
	verifyFunction(*cpu->dyncom_engine->cur_func, AbortProcessAction);

	if (cpu->dyncom_engine->flags_debug & CPU_DEBUG_PRINT_IR)
		cpu->dyncom_engine->mod->dump();

	if (cpu->dyncom_engine->flags_codegen & CPU_CODEGEN_OPTIMIZE) {
		UPDATE_TIMING(cpu, TIMER_OPT, true);
		LOG("*** Optimizing...");
		optimize(cpu);
		LOG("done.\n");
		UPDATE_TIMING(cpu, TIMER_OPT, false);
		if (cpu->dyncom_engine->flags_debug & CPU_DEBUG_PRINT_IR_OPTIMIZED)
			cpu->dyncom_engine->mod->dump();
	}

	LOG("*** Translating...");
	UPDATE_TIMING(cpu, TIMER_BE, true);
	cpu->dyncom_engine->fp[cpu->dyncom_engine->functions] = cpu->dyncom_engine->exec_engine->getPointerToFunction(cpu->dyncom_engine->cur_func);
	//cpu->dyncom_engine->fmap[start_addr] = cpu->dyncom_engine->fp[cpu->dyncom_engine->functions];
	save_addr_in_func(cpu, cpu->dyncom_engine->fp[cpu->dyncom_engine->functions]);
	LOG("Generate native code for %x\n", start_addr);
	UPDATE_TIMING(cpu, TIMER_BE, false);
	LOG("done.\n");

	cpu->dyncom_engine->functions++;/* Bug."functions" member could not be reset. */
}
Beispiel #7
0
//Let
llvm::Function* LetAST::codeGen() const
{
    namedValues.clear();

    std::vector<llvm::Type*> argument_arity;
//    argument_arity.push_back(llvm::Type::getVoidTy(llvm::getGlobalContext()));
    FunctionType *functionType = FunctionType::get(arity,argument_arity, false);
    llvm ::Function* func = llvm::Function::Create(functionType, llvm::Function::ExternalLinkage, name, module);

    if(func->getName() != name)
    {
        func->eraseFromParent();
        func = module->getFunction(name);

        if(!func->empty())
        {
            ExprAST::errorV("redefinition of function");
            return NULL;
        }
    }

    if(!func)
        return NULL;

    // Create a new basic block to start insertion into.
    BasicBlock* entry = BasicBlock::Create(getGlobalContext(), "entry", func);

    ExprAST::builder.SetInsertPoint(entry);

    Value* returnVal = body->codeGen();

    if(returnVal)
    {
        // Finish off the function
        ExprAST::builder.CreateRet(returnVal);

        // Validate the generated code, checking for consistency.
        verifyFunction(*func);
        //        std::cout << "module: " << module << std::endl;
        // optimize the function
        passManager->run(*func);

        return func;
    }

    // Error reading Body, remove function
    func->eraseFromParent();
    return NULL;
}
Beispiel #8
0
static void
cpu_translate_function(cpu_t *cpu)
{
	BasicBlock *bb_ret, *bb_trap, *label_entry, *bb_start;

	/* create function and fill it with std basic blocks */
	cpu->cur_func = cpu_create_function(cpu, "jitmain", &bb_ret, &bb_trap, &label_entry);
	cpu->func[cpu->functions] = cpu->cur_func;

	/* TRANSLATE! */
	update_timing(cpu, TIMER_FE, true);
	if (cpu->flags_debug & CPU_DEBUG_SINGLESTEP) {
		bb_start = cpu_translate_singlestep(cpu, bb_ret, bb_trap);
	} else if (cpu->flags_debug & CPU_DEBUG_SINGLESTEP_BB) {
		bb_start = cpu_translate_singlestep_bb(cpu, bb_ret, bb_trap);
	} else {
		bb_start = cpu_translate_all(cpu, bb_ret, bb_trap);
	}
	update_timing(cpu, TIMER_FE, false);

	/* finish entry basicblock */
	BranchInst::Create(bb_start, label_entry);

	/* make sure everything is OK */
	verifyFunction(*cpu->cur_func, PrintMessageAction);

	if (cpu->flags_debug & CPU_DEBUG_PRINT_IR)
		cpu->mod->dump();

	if (cpu->flags_codegen & CPU_CODEGEN_OPTIMIZE) {
		LOG("*** Optimizing...");
		optimize(cpu);
		LOG("done.\n");
		if (cpu->flags_debug & CPU_DEBUG_PRINT_IR_OPTIMIZED)
			cpu->mod->dump();
	}

	LOG("*** Translating...");
	update_timing(cpu, TIMER_BE, true);
	cpu->fp[cpu->functions] = cpu->exec_engine->getPointerToFunction(cpu->cur_func);
	update_timing(cpu, TIMER_BE, false);
	LOG("done.\n");

	cpu->functions++;
}
Beispiel #9
0
    llvm::Function * CodeGen::generateCodeDef(DefAST *ast) {
      // add def name to scope
      addScope(ast->name);

      // argument types
      vector<llvm::Type*> args(ast->args.size(), llvm::Type::getDoubleTy(context));

      // return type
      auto retType = llvm::Type::getDoubleTy(context);

      // complete function type
      llvm::FunctionType *funcType = llvm::FunctionType::get(retType, args, false);

      llvm::Function * func =
        llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, ast->name, module.get());

      unsigned i = 0;
      for (auto funcarg = func->arg_begin(); i != ast->args.size(); ++funcarg, ++i) {
        funcarg->setName(ast->args[i]);
        addScopedValue(ast->args[i], funcarg);
      }

      llvm::BasicBlock *block = llvm::BasicBlock::Create(context, "entry", func);
      Builder.SetInsertPoint(block);

      if (llvm::Value * result = generateCodeExpr(ast->body.get())) {
        Builder.CreateRet(result);

        string verifyS;
        llvm::raw_string_ostream verifyE(verifyS);
        if (verifyFunction(*func, &verifyE)) {
          func->eraseFromParent();
          error = "something wrong with function \"" + ast->name + "\": " + verifyS;
          return nullptr;
        }

        // remove the def name scope
        removeScope();
        return func;
      } else {
        func->eraseFromParent();
        error = "error creating function body: " + error;
        return nullptr;
      }
    }
Beispiel #10
0
// =============================================================================
// andOOPIsGone (formerly: createProcess)
// 
// Formerly, OOP permitted the same SC_{METHOD,THREAD} functions to apply
// to each copy of a SC_MODULE. Aaaaand it's gone !
// (but OTOH we enable better optimizations)
// Creates a new C-style function that calls the old member function with the
// given sc_module. The call is then inlined.
// FIXME: assumes the method is non-virtual and that sc_module is the first
//        inherited class of the SC_MODULE
// =============================================================================
Function *TwetoPassImpl::andOOPIsGone(Function * oldProc,
				      sc_core::sc_module * initiatorMod)
{
	if (!oldProc)
		return NULL;

	// can't statically optimize if the address of the module isn't predictible
	// TODO: also handle already-static variables, which also have
	// fixed $pc-relative addresses
	if (staticopt == optlevel && !permalloc::is_from (initiatorMod))
		return NULL;

	LLVMContext & context = getGlobalContext();

	FunctionType *funType = oldProc->getFunctionType();
	Type *type = funType->getParamType(0);

	FunctionType *newProcType =
	    FunctionType::get(oldProc->getReturnType(),
			      ArrayRef < Type * >(), false);

	// Create the new function
	std::ostringstream id;
	id << proc_counter++;
	std::string name =
	    oldProc->getName().str() + std::string("_clone_") + id.str();
	Function *newProc =
	    Function::Create(newProcType, Function::ExternalLinkage, name,
			     this->llvmMod);
	assert(newProc->empty());
	newProc->addFnAttr(Attribute::InlineHint);

	// Create call to old function
	BasicBlock *bb = BasicBlock::Create(context, "entry", newProc);
	IRBuilder <> *irb = new IRBuilder <> (context);
	irb->SetInsertPoint(bb);

	Value* thisAddr = createRelocatablePointer (type, initiatorMod, irb);

	CallInst *ci = irb->CreateCall(oldProc,
				       ArrayRef < Value * >(std::vector<Value*>(1,thisAddr)));
	//bb->getInstList().insert(ci, thisAddr);
	if (ci->getType()->isVoidTy())
		irb->CreateRetVoid();
	else
		irb->CreateRet(ci);

	// The function should be valid now
	verifyFunction(*newProc);

	{			// Inline the call
		DataLayout *td = new DataLayout(this->llvmMod);
		InlineFunctionInfo i(NULL, td);
		bool success = InlineFunction(ci, i);
		assert(success);
		verifyFunction(*newProc);
	}

	// further optimize the function
	inlineBasicIO (initiatorMod, newProc);

	newProc->dump();
	return newProc;
}
Beispiel #11
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;
}
Beispiel #12
0
    bool CodeGen::wrapTopLevelBlockInMain(BlockAST *ast) {
      // add main to scope
      addScope("main");

      vector<unique_ptr<ASTNode> > * body = ast->body.get();

      // generate void main()
      llvm::FunctionType *voidType = llvm::FunctionType::get(Builder.getVoidTy(), false);
      llvm::Function *mainFunc =
        llvm::Function::Create(voidType, llvm::Function::ExternalLinkage, "main", module.get());

      // basic block for the top level block
      llvm::BasicBlock *MainBlock = llvm::BasicBlock::Create(context, "entry", mainFunc);
      Builder.SetInsertPoint(MainBlock);

      llvm::Value * lastExpr;

      for (auto it = body->begin() ; it != body->end(); ++it) {
        ASTNode * node = it->get();

        if (auto x = dynamic_cast<ValueAST*>(node)) {
          auto code = generateCodeValue(x);
          if (!code) return false;

        } else if (auto x = dynamic_cast<DefAST*>(node)) {
          generateCodeDef(x);
          Builder.SetInsertPoint(MainBlock);

        } else if (auto x = dynamic_cast<NumberExprAST*>(node)) {
          auto code = generateCodeNumber(x);
          if (!code) return false;
          lastExpr = code;

        } else if (auto x = dynamic_cast<BinaryExprAST*>(node)) {
          auto code = generateCodeBinOp(x);
          if (!code) return false;
          lastExpr = code;

        } else if (auto x = dynamic_cast<CallAST*>(node)) {
          auto code = generateCodeCall(x);
          if (!code) return false;
          lastExpr = code;

        } else {
          error = "can't handle ast";
          return false;
        }
      }

      llvm::Value *fmt = Builder.CreateGlobalStringPtr("%lg\n");

      vector<llvm::Type *> putsArgs;
      putsArgs.push_back(Builder.getInt8Ty()->getPointerTo());
      llvm::ArrayRef<llvm::Type*> argsRef(putsArgs);

      llvm::FunctionType *putsType =
        llvm::FunctionType::get(Builder.getInt32Ty(), argsRef, true);
      llvm::Constant *putsFunc = module->getOrInsertFunction("printf", putsType);

      vector<llvm::Value *> CallArgs;
      CallArgs.push_back(fmt);
      CallArgs.push_back(lastExpr);
      Builder.CreateCall(putsFunc, CallArgs);

      Builder.CreateRetVoid();

      string verifyS;
      llvm::raw_string_ostream verifyE(verifyS);
      if (verifyFunction(*mainFunc, &verifyE)) {
        mainFunc->eraseFromParent();
        error = "something wrong with auto-generated main function: " + verifyS;
        return false;
      }

      // remove the main scope
      removeScope();

      return true;
    }
// =============================================================================
// createProcess
// 
// Create a new function that contains a call to the old function.
// We inline the call in order to clone the old function's implementation.
// =============================================================================
Function *TLMBasicPassImpl::createProcess(Function *oldProc, 
                                      sc_core::sc_module *initiatorMod) {
    
    LLVMContext &context = getGlobalContext();
    IntegerType *intType;
    if (this->is64Bit) {
        intType = Type::getInt64Ty(context);
    } else {
        intType = Type::getInt32Ty(context);
    }
    
    // Retrieve a pointer to the initiator module 
    ConstantInt *initiatorModVal = 
    ConstantInt::getSigned(intType,reinterpret_cast<intptr_t>(initiatorMod));
    FunctionType *funType = oldProc->getFunctionType();  
    Type *type = funType->getParamType(0);
    IntToPtrInst *thisAddr = 
    new IntToPtrInst(initiatorModVal, type, "");
    
    // Compute the type of the new function
    FunctionType *oldProcType = oldProc->getFunctionType();
    Value **argsBegin = new Value*[1];
    Value **argsEnd = argsBegin;
    *argsEnd++ = thisAddr;
    const unsigned argsSize = argsEnd-argsBegin;
    Value **args = argsBegin;
    assert(oldProcType->getNumParams()==argsSize);
    assert(!oldProc->isDeclaration());
    std::vector<Type*> argTypes;
    for (unsigned i = 0; i!=argsSize; ++i)
            argTypes.push_back(oldProcType->getParamType(i));
    FunctionType *newProcType =
    FunctionType::get(oldProc->getReturnType(), ArrayRef<Type*>(argTypes), false);
    
    // Create the new function
    std::ostringstream id;
    id << proc_counter++;
    std::string name = oldProc->getName().str()+std::string("_clone_")+id.str();
    Function *newProc = 
    Function::Create(newProcType, Function::ExternalLinkage, name, this->llvmMod);
    assert(newProc->empty());
    newProc->addFnAttr(Attributes::InlineHint);
    
    { // Set name of newfunc arguments and complete args
        Function::arg_iterator nai = newProc->arg_begin();
        Function::arg_iterator oai = oldProc->arg_begin();
        for (unsigned i = 0; i!=argsSize; ++i, ++oai) {
                nai->setName(oai->getName());
                args[i] = nai;
                ++nai;
        }
        assert(nai==newProc->arg_end());
        assert(oai==oldProc->arg_end());
    }
    
    // Create call to old function
    BasicBlock *bb = BasicBlock::Create(context, "entry", newProc);
    IRBuilder<> *irb = new IRBuilder<>(context);
    irb->SetInsertPoint(bb);
    CallInst *ci = irb->CreateCall(oldProc, ArrayRef<Value*>(argsBegin, argsEnd));
    bb->getInstList().insert(ci, thisAddr);
    if (ci->getType()->isVoidTy())
        irb->CreateRetVoid();
    else
        irb->CreateRet(ci);

    // The function should be valid now
    verifyFunction(*newProc);
    
    { // Inline the call
        DataLayout *td = new DataLayout(this->llvmMod);
        InlineFunctionInfo i(NULL, td);
        bool success = InlineFunction(ci, i);
        assert(success);
        verifyFunction(*newProc);
    }    
    
    //newProc->dump();
    return newProc;
}
// =============================================================================
// replaceCallsInProcess
// 
// Replace indirect calls to write() or read() by direct calls 
// in the given process.
// =============================================================================
void TLMBasicPassImpl::replaceCallsInProcess(sc_core::sc_module *initiatorMod,
                                         sc_core::sc_process_b *proc) {
    
    // Get associate function
    std::string fctName = proc->func_process;
	std::string modType = typeid(*initiatorMod).name();
	std::string mainFctName = "_ZN" + modType + 
    utostr(fctName.size()) + fctName + "Ev";
	Function *oldProcf = this->llvmMod->getFunction(mainFctName);
    if (oldProcf==NULL)
        return;
    
    // We do not modifie the original function
    // Instead, we create a clone.
    Function *procf = createProcess(oldProcf, initiatorMod);
    void *funPtr = this->engine->getPointerToFunction(procf); 
    sc_core::SC_ENTRY_FUNC_OPT scfun = 
    reinterpret_cast<sc_core::SC_ENTRY_FUNC_OPT>(funPtr);
    proc->m_semantics_p = scfun;
    std::string procfName = procf->getName();
    MSG("      Replace in the process's function : "+procfName+"\n");
    
    std::ostringstream oss;
    sc_core::sc_module *targetMod;
    std::vector<CallInfo*> *work = new std::vector<CallInfo*>;
    
    inst_iterator ii;
    for (ii = inst_begin(procf); ii!=inst_end(procf); ii++) {
        Instruction &i = *ii;
        CallSite cs(&i);
        if (cs.getInstruction()) {
            // Candidate for a replacement
            Function *oldfun = cs.getCalledFunction();
            if (oldfun!=NULL && !oldfun->isDeclaration()) {
                std::string name = oldfun->getName();
                // === Write ===
                if (!strcmp(name.c_str(), wFunName.c_str())) {
                    
                    CallInfo *info = new CallInfo();
                    info->oldcall = dyn_cast<CallInst>(cs.getInstruction());
                    MSG("       Checking adress : ");
                    // Retrieve the adress argument by executing 
                    // the appropriated piece of code
                    SCJit *scjit = new SCJit(this->llvmMod, this->elab);
                    Process *irProc = this->elab->getProcess(proc);
                    scjit->setCurrentProcess(irProc);                    
                    bool jitErr = false;
                    info->addrArg = cs.getArgument(1);
                    int value = 
                    scjit->jitInt(procf, info->oldcall, info->addrArg, &jitErr);
                    if(jitErr) {
                        std::cout << "       cannot get the address value!" 
                          << std::endl;
                    } else {
                    oss.str("");  oss << std::hex << value;
                    MSG("0x"+oss.str()+"\n");
                    basic::addr_t a = static_cast<basic::addr_t>(value);            
                    
                    // Checking address alignment
                    if(value % sizeof(basic::data_t)) {
                        std::cerr << "  unaligned write : " <<
                        std::hex << value << std::endl;
                        abort();
                    }

                    // Retreive the target module using the address
                    targetMod =  getTargetModule(initiatorMod, a);
                                    
                    // Save informations to build a new call later
                    FunctionType *writeFunType = 
                        this->basicWriteFun->getFunctionType();  
                    info->targetType = writeFunType->getParamType(0);
                    LLVMContext &context = getGlobalContext();
                    IntegerType *intType;
                    if (this->is64Bit) {
                        intType = Type::getInt64Ty(context);
                    } else {
                        intType = Type::getInt32Ty(context);
                    }
                    info->targetModVal = ConstantInt::getSigned(intType,
                                        reinterpret_cast<intptr_t>(targetMod));
                    info->dataArg = cs.getArgument(2);
                    work->push_back(info);
                    }
   
                } else
                    
                // === Read ===
                if (!strcmp(name.c_str(), rFunName.c_str())) {
                    
                    // Not yet supported
                                        
                }
            }  
        }
    
    }
        
    // Before
    //procf->dump();
    
    // Replace calls
    std::vector<CallInfo*>::iterator it;
    for (it = work->begin(); it!=work->end(); ++it) {
        CallInfo *i = *it;
        
        LLVMContext &context = getGlobalContext();
        FunctionType *writeFunType = 
        this->writeFun->getFunctionType();
        IntegerType *i64 = Type::getInt64Ty(context);
        // Get a pointer to the target module
        basic::target_module_base *tmb = 
        dynamic_cast<basic::target_module_base*>(targetMod);
        Value *ptr = 
        ConstantInt::getSigned(i64, reinterpret_cast<intptr_t>(tmb));
        IntToPtrInst *modPtr = new IntToPtrInst(ptr, 
                                                writeFunType->getParamType(0),
                                                "myitp", i->oldcall);
        // Get a the address value
        LoadInst *addr = new LoadInst(i->addrArg, "", i->oldcall);
        
        // Create the new call
        Value *args[] = {modPtr, addr, i->dataArg};
        i->newcall = CallInst::Create(this->writeFun, ArrayRef<Value*>(args, 3));
        
        // Replace the old call
        BasicBlock::iterator it(i->oldcall);
        ReplaceInstWithInst(i->oldcall->getParent()->getInstList(), it, i->newcall);
        i->oldcall->replaceAllUsesWith(i->newcall);
        
        // Inline the new call
        DataLayout *td = new DataLayout(this->llvmMod);
        InlineFunctionInfo ifi(NULL, td);
        bool success = InlineFunction(i->newcall, ifi);
        if(!success) {
            MSG("       The call cannot be inlined (it's not an error :D)");
        }
        
        MSG("       Call optimized (^_-)\n");
        callOptCounter++;
    }
    
    //std::cout << "==================================\n";
    // Run preloaded passes on the function to propagate constants
    funPassManager->run(*procf);
    // After
    //procf->dump();        
    // Check if the function is corrupt
    verifyFunction(*procf);
    this->engine->recompileAndRelinkFunction(procf);
}
Beispiel #15
0
bool CompiledCondition::compile(){
	InitializeNativeTarget();
	// Assume we're on main thread...
	LLVMContext &context = getGlobalContext();

	// Initialize module
	Module* module = new Module("Compiled function", context);

	// Create exection engine
	ExecutionEngine* engine = EngineBuilder(module).create();

	/********** Generate code **********/

	//Get a type for representing an integer pointer
	//Maybe this should be unsigned integer pointer type...
	PointerType* integerPointerType = PointerType::get(IntegerType::get(module->getContext(), 32), 0);

	//Create function type, for our function, int*, int* -> bool
	vector<const Type*> paramType;
	paramType.push_back(integerPointerType);
	paramType.push_back(integerPointerType);
	FunctionType* functionType = FunctionType::get(IntegerType::get(module->getContext(), 8), paramType, false);

	//Declare new function
	Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "evaluate", module);
	//Use C calling convention
	function->setCallingConv(CallingConv::C);	//TODO: Read documentation and reconsider this

	//Get arguments from function
	Function::arg_iterator args = function->arg_begin();
	Value* marking = args++;
	Value* valuation = args++;
	marking->setName("marking");
	valuation->setName("valuation");

	//Create function block
	BasicBlock* functionBlock = BasicBlock::Create(module->getContext(), "functionBlock", function, 0);

	//Generate code
	CodeGenerationContext codeGenContext(marking, valuation, functionBlock, context);
	Value* result = _cond->codegen(codeGenContext);

	//Zero extend the result, e.g. make it a 8 bit bool
	CastInst* retval = new ZExtInst(result, IntegerType::get(module->getContext(), 8), "retval", functionBlock);

	//Create a return instruction
	ReturnInst::Create(module->getContext(), retval, functionBlock);

	/********** Optimize and Compile **********/

	// Create function pass manager, to optimize query
	FunctionPassManager optimizer(module);
	optimizer.add(new TargetData(*engine->getTargetData()));
	optimizer.add(createBasicAliasAnalysisPass());
	optimizer.add(createInstructionCombiningPass());
	optimizer.add(createReassociatePass());
	optimizer.add(createGVNPass());
	optimizer.add(createCFGSimplificationPass());
	optimizer.doInitialization();

	// Verify function, errors written to stderr
	if(verifyFunction(*function))
		return false;

	// Optimize function
	optimizer.run(*function);

	// Compile the function
	_nativeFunction = (bool(*)(const MarkVal*, const VarVal*))engine->getPointerToFunction(function);

	return _nativeFunction != NULL;
}