Date: Thu, 28 Aug 2014 16:19:04 GMT From: dpl@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r273264 - soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw Message-ID: <201408281619.s7SGJ47P085645@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dpl Date: Thu Aug 28 16:19:04 2014 New Revision: 273264 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=273264 Log: Updated the code to LLVM 3.6, added the compilation boilerplate, and storage of rules in a nice vector, so that we can jump from one place to another. Modified: soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc Modified: soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc ============================================================================== --- soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc Thu Aug 28 15:05:42 2014 (r273263) +++ soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc Thu Aug 28 16:19:04 2014 (r273264) @@ -3,8 +3,7 @@ #include <string> #include <vector> -#include <llvm/ADT/OwningPtr.h> -#include <llvm/ADT/ArrayRef.h> +#include <llvm/Analysis/Passes.h> #include <llvm/Bitcode/ReaderWriter.h> #include <llvm/CodeGen/MachineCodeInfo.h> #include <llvm/ExecutionEngine/ExecutionEngine.h> @@ -17,9 +16,12 @@ #include <llvm/IR/Type.h> #include <llvm/IR/Value.h> #include <llvm/IR/Verifier.h> +#include <llvm/PassManager.h> #include <llvm/Support/MemoryBuffer.h> #include <llvm/Support/ErrorOr.h> #include <llvm/Support/TargetSelect.h> +#include <llvm/Transforms/IPO.h> +#include <llvm/Transforms/IPO/PassManagerBuilder.h> #define _KERNEL extern "C" { @@ -46,11 +48,10 @@ Module *mod; Function *func; LLVMContext con; - OwningPtr<MemoryBuffer> buffer; IRBuilder<> irb; // We'll store the BasicBlock objects for each rule here. - int rulenumber = 1; + int rulenumber = 0; std::vector<BasicBlock *> rules; // Vars Types @@ -69,9 +70,6 @@ BasicBlock *outer_for_epilogue; BasicBlock *inner_for_epilogue; - // This BB is the next emitted rule, always. - BasicBlock *next; - // JIT Compiled Vars // These are the function arguments. Value *args; @@ -174,22 +172,29 @@ // Load the bc for JIT compilation. Module * - loadbc(std::string name) + loadBitcode(std::string name) { - error_code ec = MemoryBuffer::getFile(name, buffer); - if (ec) { - std::cerr << "Failed to open bitcode: " << ec.message() << "\n"; + auto buffer = MemoryBuffer::getFile(name); + if (buffer.getError()){ + std::cerr << "Failed to open bitcode: " << buffer.getError() << "\n"; return (NULL); } - ErrorOr<Module*> ptr = parseBitcodeFile(buffer.get(), con); - if ((ec = ptr.getError())) - { - std::cerr << "Failed to parse bitcode: " << ec.message() << "\n"; + auto modptr = parseBitcodeFile(buffer.get().get(), con); + if ((modptr.getError())){ + std::cerr << "Failed to parse bitcode: " << buffer.getError() << "\n"; return (NULL); } - mod = ptr.get(); - return (mod); + return (modptr.get()); + } + + BasicBlock* + nextRule(int num) + { + if (num >= rules.size()) + return (end); + else + return (rules[num]); } // Create the needed variables to perform pkt filtering. @@ -408,6 +413,7 @@ // if (V_fw_verbose) irb.CreateCondBr(irb.CreateICmpEQ(is_verbose, ConstantInt::get(int32Ty, 0)), ret, print); + // printf("ipfw: pullup failed\n"); irb.SetInsertPoint(print); irb.CreateCall(printfFunc, str); @@ -466,7 +472,8 @@ // else f_pos = 0; // Since f_pos is initialized by default as 0, we only br. irb.SetInsertPoint(nottagged); - irb.CreateBr(rules[rulenumber]); + // Jump to first rule. + irb.CreateBr(rules.front()); } void @@ -499,7 +506,7 @@ irb.SetInsertPoint(jt); // continue; - irb.CreateBr(next); + irb.CreateBr(nextRule(rulenumber+1)); // skip_or = 0; irb.SetInsertPoint(jf); @@ -555,7 +562,7 @@ irb.SetInsertPoint(secondf); // continue; - irb.CreateBr(next); + irb.CreateBr(nextRule(rulenumber+1)); irb.SetInsertPoint(firstf); // match = 0; @@ -568,15 +575,13 @@ void emit_inner_for_epilogue() { - BasicBlock *matchnz = BasicBlock::Create(con, "jt", func); - BasicBlock *matchz = BasicBlock::Create(con, "jt", func); + BasicBlock *matchnz = BasicBlock::Create(con, "matchnz", func); + BasicBlock *matchz = BasicBlock::Create(con, "matchz", func); BasicBlock *jt = BasicBlock::Create(con, "jt", func); - BasicBlock *jf = BasicBlock::Create(con, "jf", func); BasicBlock *sec_cond = BasicBlock::Create(con, "sec_cond", func); BasicBlock *matchzero = BasicBlock::Create(con, "matchzero", func); BasicBlock *matchnotzero = BasicBlock::Create(con, "matchnotzero", func); BasicBlock *is_or = BasicBlock::Create(con, "is_or", func); - BasicBlock *is_not_or = BasicBlock::Create(con, "is_not_or", func); // This are the increments of the for loop. // l -= cmdlen, cmd += cmdlen; @@ -628,7 +633,7 @@ irb.SetInsertPoint(matchzero); // if (!(cmd->len & F_OR)) /* not an OR block, */ // break; - irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, {ConstantInt::get(int32Ty, 0), ConstantInt::get(int32Ty, 1)}), ConstantInt::get(int8Ty, F_OR)), ConstantInt::get(int32Ty, 0)), next /* break */, outer_for_epilogue); + irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, {ConstantInt::get(int32Ty, 0), ConstantInt::get(int32Ty, 1)}), ConstantInt::get(int8Ty, F_OR)), ConstantInt::get(int32Ty, 0)), nextRule(rulenumber+1) /* break */, outer_for_epilogue); } // This code gets executed at the end of inner loop. @@ -643,7 +648,7 @@ // if (done) // break; - irb.CreateCondBr(irb.CreateICmpNE(done, ConstantInt::get(int32Ty, 0)), end, next); + irb.CreateCondBr(irb.CreateICmpNE(done, ConstantInt::get(int32Ty, 0)), end, nextRule(rulenumber+1)); } void @@ -734,11 +739,18 @@ ipfwJIT(int rulesnumber): irb(con) { // Create the module and load the code. - mod = loadbc("ip_fw_rules.bc"); + mod = loadBitcode("ip_fw_rules.bc"); func = mod->getFunction("ipfw_chk_jit"); func->setLinkage(GlobalValue::ExternalLinkage); + // Initialize the vector. + rules = std::vector<BasicBlock *>(rulesnumber); + for (auto &i: rules){ + i = BasicBlock::Create(con, "rule", func); + } + + // Create static BasicBlocks. // The entry basic block contains all the initialization // and allocation of resources, and a basic check done @@ -746,15 +758,8 @@ entry = BasicBlock::Create(con, "entry", func); check_tag = BasicBlock::Create(con, "check_tag", func); end = BasicBlock::Create(con, "end", func); - - // Initialize the vector. - rules = std::vector<BasicBlock *>(rulesnumber + 1); - rules[rulenumber] = BasicBlock::Create(con, "rule", func); - start_rule(); - // This is equivalent to the pullup_failed tag. pullup_failed = BasicBlock::Create(con, "pullup_failed", func); - //Snippets of code to be executed when iterating through the rules. outer_for_prologue = BasicBlock::Create(con, "outer_for_prologue", func); inner_for_prologue = BasicBlock::Create(con, "inner_for_prologue", func); @@ -775,12 +780,6 @@ emit_inner_for_epilogue(); emit_outer_for_epilogue(); emit_end(); - - verifyFunction(*func); - - - verifyModule(*mod); - mod->dump(); } ~ipfwJIT() { @@ -788,33 +787,60 @@ delete mod; } - void - optimize() + funcptr + compile() { + // Check correctness. + verifyFunction(*func); + verifyModule(*mod); + + //Optimise + PassManagerBuilder PMBuilder; + PMBuilder.OptLevel = 0; + PMBuilder.Inliner = createFunctionInliningPass(275); + + // Function passes + FunctionPassManager *PerFunctionPasses = new FunctionPassManager(mod); + PMBuilder.populateFunctionPassManager(*PerFunctionPasses); + PerFunctionPasses->run(*func); + PerFunctionPasses->doFinalization(); + delete PerFunctionPasses; + + //printf("\n\n\n\n"); + //mod->getFunction("ipfw_chk_jit")->dump(); + + // Module passes + PassManager *PerModulePasses = new PassManager(); + PMBuilder.populateModulePassManager(*PerModulePasses); + PerModulePasses->run(*mod); + delete PerModulePasses; + // We don't need it anymore. Function *vf = mod->getFunction("voidfunction"); vf->eraseFromParent(); - } - // Returns the pointer to the compiled function. - funcptr - getFuncPtr() - { - return ((funcptr)NULL); - } + //Compile + std::string errstr; + std::string comperr = "Compilation error\n"; + + EngineBuilder EB = EngineBuilder(std::unique_ptr<Module>(mod)); + EB.setEngineKind(EngineKind::Kind::JIT); + EB.setErrorStr(&comperr); + + ExecutionEngine *EE = EB.create(); + if (!EE) { + fprintf(stderr, "Error: %s\n", errstr.c_str()); + exit(1); + } - void - start_rule() - { - // This will be the first BasicBlock to store our emmited code. - rules[rulenumber] = BasicBlock::Create(con, "rule", func); - next = rules[rulenumber+1] = BasicBlock::Create(con, "rule", func); + printf("Function ptr: %p\n", (void *)EE->getFunctionAddress("ipfw_chk_jit")); + err(1,"null"); + return (funcptr)EE->getFunctionAddress("ipfw_chk_jit"); } void end_rule() { - // We're on the next rule now. rulenumber++; } @@ -851,32 +877,59 @@ } // Rules - int + void emit_nop() { irb.CreateStore(ConstantInt::get(int32Ty, 1), match); - return (0); } - int + void emit_forward_mac(u_int8_t opcode) { printf("Compilation error:\n"); printf("ipfwjitter: opcode %d unimplemented\n", opcode); printf("Compilation continues.\n"); - return (0); } - int + void emit_jail() { - return (0); + // /* + // * We only check offset == 0 && proto != 0, + // * as this ensures that we have a + // * packet with the ports info. + // */ + // if (offset != 0) + // return; + // if (proto == IPPROTO_TCP || + // proto == IPPROTO_UDP) + // *match = check_uidgid( + // (ipfw_insn_u32 *)cmd, + // args, &ucred_lookup, + // #ifdef __FreeBSD__ + // //(struct bsd_ucred **)&ucred_cache); + // (struct ucred **)&ucred_cache); + // #else + // (void *)&ucred_cache); + // #endif + } - int + void emit_recv() { - return (0); + // XXX Check correctness. + //*match = iface_match(m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd, chain, tablearg); + Value *rcvif = irb.CreateStructGEP(irb.CreateStructGEP(irb.CreateLoad(m), 5), 0); + Value *cmdc = irb.CreateBitCast(cmd, ipfw_insn_ifPtrTy); + irb.CreateStore(irb.CreateCall4(iface_match, rcvif, cmdc, chain, tablearg), match); + } + + void + emit_xmit() + { + // XXX Check correctness. + //*match = iface_match(oif, (ipfw_insn_if *)cmd, chain, tablearg); } }; @@ -890,6 +943,9 @@ InitializeNativeTarget(); LLVMLinkInJIT(); + if (chain->n_rules == 0) + return (NULL); + ipfwJIT compiler(chain->n_rules); // Iterate through the rules. @@ -905,7 +961,6 @@ f = chain->map[f_pos]; // Rule start. - compiler.start_rule(); compiler.emit_outer_for_prologue_call(); // For each different command. @@ -933,11 +988,11 @@ compiler.emit_recv(); break; -/* XXX case O_XMIT: compiler.emit_xmit(); break; +/* XXX case O_VIA: compiler.emit_via(); break; @@ -1295,7 +1350,7 @@ default: panic("-- unknown opcode %d\n", cmd->opcode); } /* end of switch() on opcodes */ - compiler.emit_inner_for_prologue_call(); + compiler.emit_inner_for_epilogue_call(); } /* end of inner loop, scan opcodes */ // Rule ends. compiler.emit_outer_for_epilogue_call(); @@ -1305,6 +1360,5 @@ compiler.emit_end_call(); // Once we're done iterating through the rules, return the pointer. - compiler.optimize(); - return (compiler.getFuncPtr()); + return (compiler.compile()); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201408281619.s7SGJ47P085645>