static void genCall(type_expr *t, char *fname, FILE *fp) { static int level = 0; func_t *F; int i; F = (func_t *) EiC_getInf(t); level++; fputs("\n", fp); if(Ncalls) { int k; for(k=0;k<Ncalls;++k) fprintf(fp,"\t%s%d = arg(%d,getargs(),ptr_t).p;\n", callName,callNo[k],callpos[k]); } if(nextType(t)) { t = nextType(t); genAffect(t,0,fp); if(t) while(nextType(t)) t = nextType(t); } fputs(fname,fp); fputs("(", fp); if (F && getFNp(F)) { for (i = 0; i < getFNp(F); i++) { genArg(getFPty(F,i), i, fp); if(i < getFNp(F)-1) { fputs(",\n", fp); fputs("\t\t", fp); } } fputs(");\n", fp); } else fputs(");\n", fp); level--; }
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; }
static void genMultiCall(type_expr *t, char *fname, FILE *fp) { static int level = 0; func_t *F; int i,n; type_expr *T; F = (func_t *) EiC_getInf(t); level++; fputs("\tstatic int nb = 0;\n\n",fp); fprintf(fp,"\tswitch(nb)\n"); fprintf(fp,"\t{\n"); for (n = 0;n < MULTIPLEX;++n) { adjustNum = n+1-MULTIPLEX; fprintf(fp,"\tcase %d :\n",n); if(Ncalls) { int k; for(k=0;k<Ncalls;++k) fprintf(fp,"\t%s%d = arg(%d,getargs(),ptr_t).p;\n", callName,callNo[k]+adjustNum,callpos[k]); } if (n == 0) { T = t; } else { t = T; } if(nextType(t)) { t = nextType(t); genAffect(t,0,fp); if(t) while(nextType(t)) t = nextType(t); } fputs(fname,fp); fputs("(", fp); if (F && getFNp(F)) { for (i = 0; i < getFNp(F); i++) { genArg(getFPty(F,i), i, fp); if(i < getFNp(F)-1) { fputs(",\n", fp); fputs("\t\t", fp); } } fputs(");\n", fp); } else fputs(");\n", fp); level--; fprintf(fp,"\tbreak;\n"); } fprintf(fp,"\t}\n"); fprintf(fp,"\t++nb;\n"); fprintf(fp,"\tnb %%= %d;\n",MULTIPLEX); adjustNum = 0; }