socsvn commit: r273264 - soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw
dpl at FreeBSD.org
dpl at FreeBSD.org
Thu Aug 28 16:19:05 UTC 2014
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());
}
More information about the svn-soc-all
mailing list