Date: Wed, 3 Sep 2014 10:32:20 GMT From: dpl@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r273535 - soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw Message-ID: <201409031032.s83AWKTe067369@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dpl Date: Wed Sep 3 10:32:20 2014 New Revision: 273535 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=273535 Log: No assertions, cleaned the code. 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 Wed Sep 3 10:22:49 2014 (r273534) +++ soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc Wed Sep 3 10:32:20 2014 (r273535) @@ -62,13 +62,10 @@ PointerType *Int8PtrTy; // Basic blocks used - BasicBlock *Entry, *End; - BasicBlock *Pullup_failed; - BasicBlock *Check_tag; - BasicBlock *Outer_for_prologue; - BasicBlock *Inner_for_prologue; - BasicBlock *Outer_for_epilogue; - BasicBlock *Inner_for_epilogue; + BasicBlock *Entry; + BasicBlock *End; + BasicBlock *PullupFailed; + BasicBlock *CheckTag; // JIT Compiled Vars // These are the function arguments. @@ -172,15 +169,15 @@ Module * loadBitcode(std::string name) { - auto buffer = MemoryBuffer::getFile(name); - if (buffer.getError()){ - std::cerr << "Failed to open bitcode: " << buffer.getError() << "\n"; + auto buff = MemoryBuffer::getFile(name); + if (buff.getError()){ + std::cerr << "Failed to open bitcode: " << buff.getError() << "\n"; return (NULL); } - auto modptr = parseBitcodeFile(buffer.get().get(), Con); + auto modptr = parseBitcodeFile(buff.get().get(), Con); if ((modptr.getError())){ - std::cerr << "Failed to parse bitcode: " << buffer.getError() << "\n"; + std::cerr << "Failed to parse bitcode: " << buff.getError() << "\n"; return (NULL); } return (modptr.get()); @@ -397,9 +394,10 @@ Is_ipv6, Hlen, Proto, Icmp6_type, Ip6f_mf, Offset, UlpL}); Value *Cond = Irb.CreateICmpEQ(InspectPktCall, ConstantInt::get(Int32Ty, 1)); - Irb.CreateCondBr(Cond, Pullup_failed, Check_tag); + Irb.CreateCondBr(Cond, PullupFailed, CheckTag); } + // This is equivalent to the pullup_failed tag. void emit_pullup_failed() { @@ -421,7 +419,7 @@ Is_verbose = mod->getGlobalVariable("fw_verbose"); Str = Irb.CreateGlobalString("ipfw: pullup failed\n"); - Irb.SetInsertPoint(Pullup_failed); + Irb.SetInsertPoint(PullupFailed); // if (V_fw_verbose) Value *Is_verboseL = Irb.CreateLoad(Is_verbose); @@ -449,7 +447,7 @@ Value *Comp; - Irb.SetInsertPoint(Check_tag); + Irb.SetInsertPoint(CheckTag); // if (args->rule.slot) { // /* @@ -510,6 +508,111 @@ Irb.CreateBr(rules.front()); } + public: + ipfwJIT(int rulesnumber): Irb(Con) + { + // Create the module and load the code. + mod = loadBitcode("rules.bc"); + + Func = mod->getFunction("ipfw_chk_jit"); + Func->setLinkage(GlobalValue::ExternalLinkage); + // Create static BasicBlocks. + // The entry basic block contains all the initialization + // and allocation of resources, and a basic check done + // before start emmiting the rules code. + Entry = BasicBlock::Create(Con, "Entry", Func); + End = BasicBlock::Create(Con, "End", Func); + CheckTag = BasicBlock::Create(Con, "CheckTag", Func); + PullupFailed = BasicBlock::Create(Con, "PullupFailed", Func); + + + // Get struct types, and store vars + setEnv(); + + // Start compilation + allocaAndInit(); + + // Initialize the vector. + rules = std::vector<BasicBlock *>(rulesnumber); + for (auto &i: rules){ + i = BasicBlock::Create(Con, "rule", Func); + } + + emit_check_tag(); + emit_pullup_failed(); + } + ~ipfwJIT() + { + if (mod) + delete mod; + } + + funcptr + compile() + { + InitializeNativeTarget(); + LLVMLinkInJIT(); + +// //Optimise +// PassManagerBuilder PMBuilder; +// PMBuilder.OptLevel = 1; +// PMBuilder.Inliner = createFunctionInliningPass(275); + +// // Function passes +// FunctionPassManager *PerFunctionPasses = new FunctionPassManager(mod); +// PMBuilder.populateFunctionPassManager(*PerFunctionPasses); +// PerFunctionPasses->run(*Func); +// PerFunctionPasses->doFinalization(); +// delete PerFunctionPasses; + +// printf("Done optimizing Function\n"); + +// // Module passes +// PassManager *PerModulePasses = new PassManager(); +// PMBuilder.populateModulePassManager(*PerModulePasses); +// PerModulePasses->run(*mod); +// delete PerModulePasses; + +// printf("Done optimizing Module\n"); + + // // We don't need it anymore. + // Function *vf = mod->getFunction("voidfunction"); + // vf->eraseFromParent(); + // printf("Done erasing voidfunction\n"); + + //Compile + std::string comperr = "Compilation error\n"; + std::string errstr; + + EngineBuilder EB = EngineBuilder(std::unique_ptr<Module>(mod)); + EB.setEngineKind(EngineKind::Kind::JIT); + EB.setUseMCJIT(true); + EB.setErrorStr(&comperr); + EB.setVerifyModules(true); + EB.setOptLevel(CodeGenOpt::Level::None); + + ExecutionEngine *EE = EB.create(); + if (!EE) { + fprintf(stderr, "Error: %s\n", errstr.c_str()); + exit(1); + } + + //mod->dump(); + //InspectPkt->dump(); + mod->getFunction("m_freem")->dump(); + + printf("FuncPtr: %p\n", (void *)EE->getPointerToFunction(Func)); + //printf("FuncPtr: %p\n", (void *)EE->getFunctionAddress("ipfw_chk_jit")); + err(1,"null"); + return (funcptr)EE->getFunctionAddress("ipfw_chk_jit"); + } + + void + end_rule() + { + rulenumber++; + } + void emit_outer_for_prologue() { @@ -528,7 +631,9 @@ // continue; // skip_or = 0; - Irb.SetInsertPoint(Outer_for_prologue); + // Write at the rule. + Irb.SetInsertPoint(rules[rulenumber]); + // uInt32_t tablearg = 0; Irb.CreateStore(ConstantInt::get(Int32Ty, 0), Tablearg); @@ -557,8 +662,6 @@ // skip_or = 0; Irb.SetInsertPoint(jf); Irb.CreateStore(ConstantInt::get(Int32Ty, 0), SkipOr); - - Irb.CreateBr(Inner_for_prologue); } void @@ -583,7 +686,6 @@ // continue; // } // match = 0; /* set to 1 if we succeed */ - Irb.SetInsertPoint(Inner_for_prologue); // l = f->cmd_len; Value *FL = Irb.CreateLoad(F); @@ -632,10 +734,9 @@ Irb.SetInsertPoint(firstf); // match = 0; Irb.CreateStore(ConstantInt::get(Int32Ty, 0), Match); - - Irb.CreateBr(Inner_for_epilogue); } + // We get here ar the end of switch() on opcodes. void emit_inner_for_epilogue() @@ -647,6 +748,7 @@ BasicBlock *matchzero = BasicBlock::Create(Con, "matchzero", Func); BasicBlock *matchnotzero = BasicBlock::Create(Con, "matchnotzero", Func); BasicBlock *is_or = BasicBlock::Create(Con, "is_or", Func); + BasicBlock *Continue = BasicBlock::Create(Con, "Continue", Func); Value *Comp, *AndOp; @@ -657,7 +759,7 @@ Value *Sub = Irb.CreateNSWSub(LL, CmdLenL); Irb.CreateStore(Sub, L); - // TODO -- Should ensure correctness of code. + // TODO - Should ensure correctness of code. // ipfw_insn *cmd; Add to pointer. // Note: Since LLVM can't add to a ptr, we can use GEP with casted Ptr. // cmd += cmdlen; @@ -676,8 +778,6 @@ // break; /* try next rule */ // } - Irb.SetInsertPoint(Inner_for_epilogue); - // if (cmd->len & F_NOT) Value *Len = Irb.CreateStructGEP(CmdL, 1); Value *LenL = Irb.CreateLoad(Len); @@ -702,6 +802,7 @@ Irb.SetInsertPoint(sec_cond); // if (match) + MatchL = Irb.CreateLoad(Match); Comp = Irb.CreateICmpNE(MatchL, ConstantInt::get(Int32Ty, 0)); Irb.CreateCondBr(Comp, matchnotzero, matchzero); @@ -709,28 +810,29 @@ // if (cmd->len & F_OR) AndOp = Irb.CreateAnd(LenL, ConstantInt::get(Int8Ty, F_OR)); Comp = Irb.CreateICmpNE(AndOp, ConstantInt::get(Int8Ty, 0)); - Irb.CreateCondBr(Comp, is_or, Outer_for_epilogue); + Irb.CreateCondBr(Comp, is_or, Continue); Irb.SetInsertPoint(is_or); // skip_or = 1; Irb.CreateStore(ConstantInt::get(Int32Ty, 1), SkipOr); - Irb.CreateBr(Outer_for_epilogue); + Irb.CreateBr(Continue); Irb.SetInsertPoint(matchzero); // if (!(cmd->len & F_OR)) /* not an OR block, */ // break; AndOp = Irb.CreateAnd(LenL, ConstantInt::get(Int8Ty, F_OR)); Comp = Irb.CreateICmpEQ(AndOp, ConstantInt::get(Int8Ty, 0)); - Irb.CreateCondBr(Comp, nextRule(rulenumber+1) /* break */, Outer_for_epilogue); + Irb.CreateCondBr(Comp, nextRule(rulenumber+1) /* break */, Continue); + + Irb.SetInsertPoint(Continue); } + // This code gets executed at the end of inner loop. // In this context, break means goto end, else continue loop. void emit_outer_for_epilogue() { - Irb.SetInsertPoint(Outer_for_epilogue); - // f_pos++, increment of the for loop. Value *FPosL = Irb.CreateLoad(FPos); Value *AddOp = Irb.CreateAdd(FPosL, ConstantInt::get(Int32Ty, 1)); @@ -743,6 +845,7 @@ Irb.CreateCondBr(Comp, End, nextRule(rulenumber+1)); } + void emit_end() { @@ -750,7 +853,11 @@ BasicBlock *Jt = BasicBlock::Create(Con, "jt", Func); BasicBlock *Jf = BasicBlock::Create(Con, "jf", Func); + BasicBlock *DoCache = BasicBlock::Create(Con, "cache", Func); BasicBlock *Ret = BasicBlock::Create(Con, "ret", Func); + #ifdef __FreeBSD__ + BasicBlock *CacheNN = BasicBlock::Create(Con, "cachennull", Func); + #endif Value *Comp, *AddOp; // if (done) { @@ -816,6 +923,7 @@ Value *TimeUptimeL32 = Irb.CreateTrunc(TimeUptimeL, Int32Ty); Value *Timestamp = Irb.CreateStructGEP(RuleL, 10); Irb.CreateStore(TimeUptimeL32, Timestamp); + Irb.CreateBr(DoCache); Irb.SetInsertPoint(Jf); // retval = IP_FW_DENY; @@ -823,166 +931,29 @@ Irb.CreateStore(ConstantInt::get(Int32Ty, IP_FW_DENY), Retval); Value *StrFirstElement = Irb.CreateStructGEP(Str, 0); Irb.CreateCall(PrintfFunc, StrFirstElement); + Irb.CreateBr(DoCache); + + Irb.SetInsertPoint(DoCache); #ifndef __FreeBSD__ - Irb.CreateBr(ret); + Irb.CreateBr(Ret); #endif #ifdef __FreeBSD__ - { - Irb.SetInsertPoint(End); - BasicBlock *CacheNN = BasicBlock::Create(Con, "cachennull", Func); - // if (ucred_cache != NULL) - Comp = Irb.CreateICmpNE(Ucred_cache, - ConstantPointerNull::get(UcredPtrTy)); - Irb.CreateCondBr(Comp, CacheNN, Ret); + // if (ucred_cache != NULL) + Comp = Irb.CreateICmpNE(Ucred_cache, + ConstantPointerNull::get(UcredPtrTy)); + Irb.CreateCondBr(Comp, CacheNN, Ret); - Irb.SetInsertPoint(CacheNN); - Irb.CreateBr(Ret); - } + Irb.SetInsertPoint(CacheNN); + Irb.CreateBr(Ret); #endif + //Return retval Irb.SetInsertPoint(Ret); - Irb.CreateRet(Retval); + Value *RetvalL = Irb.CreateLoad(Retval); + Irb.CreateRet(RetvalL); } - public: - ipfwJIT(int rulesnumber): Irb(Con) - { - // Create the module and load the code. - 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 - // before start emmiting the rules code. - Entry = BasicBlock::Create(Con, "Entry", Func); - End = BasicBlock::Create(Con, "End", Func); - Check_tag = BasicBlock::Create(Con, "CheckTag", Func); - // This is equivalent to the pullup_failed tag. - Pullup_failed = BasicBlock::Create(Con, "PullupFailed", Func); - //Snippets of code to be executed when iterating through the rules. - Outer_for_prologue = BasicBlock::Create(Con, "OuterForPrologue", Func); - Inner_for_prologue = BasicBlock::Create(Con, "InnerForPrologue", Func); - Inner_for_epilogue = BasicBlock::Create(Con, "InnerForEpilogue", Func); - Outer_for_epilogue = BasicBlock::Create(Con, "OuterForEpilogue", Func); - - // Get struct types, and store vars - setEnv(); - - // Start compilation - allocaAndInit(); - emit_check_tag(); - emit_pullup_failed(); - - // Snippets of code to be used for each iteration. - emit_outer_for_prologue(); - emit_inner_for_prologue(); - emit_inner_for_epilogue(); - emit_outer_for_epilogue(); - emit_end(); - } - ~ipfwJIT() - { - if (mod) - delete mod; - } - - funcptr - compile() - { - std::string errstr; - std::string comperr = "Compilation error\n"; - - // Check correctness. - verifyFunction(*Func); - verifyModule(*mod); - - InitializeNativeTarget(); - LLVMLinkInJIT(); - - //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; - - // 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(); - - //Compile - EngineBuilder EB = EngineBuilder(std::unique_ptr<Module>(mod)); - EB.setErrorStr(&comperr); - - ExecutionEngine *EE = EB.create(); - if (!EE) { - fprintf(stderr, "Error: %s\n", errstr.c_str()); - exit(1); - } - - printf("FuncPtr: %p\n", (void *)EE->getFunctionAddress("ipfw_chk_jit")); - err(1,"null"); - return (funcptr)EE->getFunctionAddress("ipfw_chk_jit"); - } - - void - end_rule() - { - rulenumber++; - } - - // Also initialized the rules vector. - void - emit_outer_for_prologue_call() - { - Irb.SetInsertPoint(rules[rulenumber]); - Irb.CreateBr(Outer_for_prologue); - } - - void - emit_inner_for_prologue_call() - { - Irb.CreateBr(Inner_for_prologue); - } - - void - emit_inner_for_epilogue_call() - { - Irb.CreateBr(Inner_for_epilogue); - } - - void - emit_outer_for_epilogue_call() - { - Irb.CreateBr(Outer_for_epilogue); - } - - void - emit_end_call() - { - Irb.CreateBr(End); - } // Rules void @@ -1069,14 +1040,14 @@ f = chain->map[f_pos]; // Rule start. - compiler.emit_outer_for_prologue_call(); + compiler.emit_outer_for_prologue(); // For each different command. for (l = f->cmd_len, cmd = f->cmd ; l > 0 ; l -= cmdlen, cmd += cmdlen) { /* check_body: */ cmdlen = F_LEN(cmd); - compiler.emit_inner_for_prologue_call(); + compiler.emit_inner_for_prologue(); switch (cmd->opcode) { case O_NOP: compiler.emit_nop(); @@ -1458,14 +1429,14 @@ default: panic("-- unknown opcode %d\n", cmd->opcode); } /* end of switch() on opcodes */ - compiler.emit_inner_for_epilogue_call(); + compiler.emit_inner_for_epilogue(); } /* end of inner loop, scan opcodes */ // Rule ends. - compiler.emit_outer_for_epilogue_call(); + compiler.emit_outer_for_epilogue(); compiler.end_rule(); } /* end of outer for, scan rules */ - compiler.emit_end_call(); + compiler.emit_end(); // Once we're done iterating through the rules, return the pointer. return (compiler.compile());
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409031032.s83AWKTe067369>
