socsvn commit: r272599 - in soc2014/dpl/netmap-ipfwjit: . sys/netpfil/ipfw

dpl at FreeBSD.org dpl at FreeBSD.org
Mon Aug 18 10:23:43 UTC 2014


Author: dpl
Date: Mon Aug 18 10:23:41 2014
New Revision: 272599
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=272599

Log:
  Added all the flow control necessary to JIT compile the rules.

Modified:
  soc2014/dpl/netmap-ipfwjit/Makefile.kipfw
  soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc

Modified: soc2014/dpl/netmap-ipfwjit/Makefile.kipfw
==============================================================================
--- soc2014/dpl/netmap-ipfwjit/Makefile.kipfw	Mon Aug 18 09:40:19 2014	(r272598)
+++ soc2014/dpl/netmap-ipfwjit/Makefile.kipfw	Mon Aug 18 10:23:41 2014	(r272599)
@@ -141,7 +141,7 @@
 EFILES = $(foreach i,$(EDIRS),$(subst $(empty) , $(i)/, $(EFILES_$(i):  = )))
 
 BCFLAGS=-emit-llvm -c
-CXXFLAGS=`llvm-config-devel --cxxflags`
+CXXFLAGS= -g `llvm-config-devel --cxxflags`
 
 include_e:
 	- at echo "Building $(OBJPATH)/include_e ..."
@@ -169,7 +169,7 @@
 	$(HIDE)clang++ -o $@ $^ $(LIBS)
 
 jit.o: jit.cc ../ip_fw_rules.bc
-	clang++ $(J_CFLAGS) $(CXXFLAGS) ../sys/netpfil/ipfw/jit.cc -o ./jit.o
+	clang++ -v $(J_CFLAGS) $(CXXFLAGS) $(LIBS) ../sys/netpfil/ipfw/jit.cc -o ./jit.o
 
 clean:
 	-rm -f *.o $(DN) $(MOD)

Modified: soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc
==============================================================================
--- soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc	Mon Aug 18 09:40:19 2014	(r272598)
+++ soc2014/dpl/netmap-ipfwjit/sys/netpfil/ipfw/jit.cc	Mon Aug 18 10:23:41 2014	(r272599)
@@ -8,9 +8,14 @@
 #include <llvm/Bitcode/ReaderWriter.h>
 #include <llvm/CodeGen/MachineCodeInfo.h>
 #include <llvm/ExecutionEngine/ExecutionEngine.h>
+#include <llvm/IR/BasicBlock.h>
+#include <llvm/IR/Constants.h>
+#include <llvm/IR/Function.h>
 #include <llvm/IR/IRBuilder.h>
 #include <llvm/IR/LLVMContext.h>
 #include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+#include <llvm/IR/Value.h>
 #include <llvm/Support/MemoryBuffer.h>
 #include <llvm/Support/ErrorOr.h>
 #define _KERNEL
@@ -50,13 +55,18 @@
 	Type *int8Ty;
 	Type *int16Ty;
 	Type *int32Ty;
+	Type *int64Ty;
 	PointerType *int8PtrTy;
 
 	// Basic blocks used
-	BasicBlock *entry;
+	BasicBlock *entry, *end;
 	BasicBlock *pullup_failed;
 	BasicBlock *startrules;
-	BasicBlock *end;
+	BasicBlock *outer_for_prologue;
+	BasicBlock *inner_for_prologue;
+	BasicBlock *outer_for_epilogue;
+	BasicBlock *inner_for_epilogue;
+
 	// This BB is the next emitted rule, always.
 	BasicBlock *next;
 
@@ -70,11 +80,16 @@
 	Value *done;
 	Value *f_pos;
 	Value *retval;
+	Value *cmd;
+	Value *cmdlen;
+	Value *tablearg;
+	Value *skip_or;
+	Value *f;
 
 	// Packet matching variables.
 	Value *m;
 	Value *ip;
-	Value *ucred;
+	Value *ucred_cache;
 	Value *ucred_lookup;
 	Value *oif;
 	Value *hlen; //unsigned
@@ -127,6 +142,7 @@
 	// Not pkg-filtering related funcs.
 	Function *printfFunc;
 	Function *ipfw_find_rule;
+	Function *crfree;
 
 	// Used structs.
 	StructType *ifnetTy;
@@ -135,7 +151,7 @@
 	StructType *ip_fw_argsTy;
 	StructType *ip_fw_chainTy;
 	StructType *ip_fwTy;
-	StructType *ip_fw_insnTy;
+	StructType *ipfw_insnTy;
 	StructType *ipfw_dyn_ruleTy;
 	StructType *ipfw_insn_ifTy;
 	StructType *mbufTy;
@@ -148,7 +164,7 @@
 	PointerType *ip_fw_argsPtrTy;
 	PointerType *ip_fw_chainPtrTy;
 	PointerType *ip_fwPtrTy;
-	PointerType *ip_fw_insnPtrTy;
+	PointerType *ipfw_insnPtrTy;
 	PointerType *ipfw_dyn_rulePtrTy;
 	PointerType *ipfw_insn_ifPtrTy;
 	PointerType *mbufPtrTy;
@@ -193,6 +209,7 @@
 		int8Ty = Type::getInt8Ty(con);
 		int16Ty = Type::getInt16Ty(con);
 		int32Ty = Type::getInt32Ty(con);
+		int64Ty = Type::getInt64Ty(con);
 		int8PtrTy = PointerType::getUnqual(int8Ty);
 
 		// Get StrucType from bitcode.
@@ -203,7 +220,7 @@
 		ip_fw_argsTy = mod->getTypeByName("ip_fw_args");
 		ip_fw_chainTy = mod->getTypeByName("ip_fw_chain");
 		ip_fwTy = mod->getTypeByName("ip_fw");
-		ip_fw_insnTy = mod->getTypeByName("_ip_fw_insn");
+		ipfw_insnTy = mod->getTypeByName("_ipfw_insn");
 		ipfw_insn_ifTy = mod->getTypeByName("_ipfw_insn_if");
 		mbufTy = mod->getTypeByName("mbuf");
 #ifdef __FreeBSD__
@@ -220,7 +237,7 @@
 		ip_fw_argsPtrTy = PointerType::get(ip_fw_argsTy, 0);
 		ip_fw_chainPtrTy = PointerType::get(ip_fw_chainTy, 0);
 		ip_fwPtrTy = PointerType::get(ip_fwTy, 0);
-		ip_fw_insnPtrTy = PointerType::get(ip_fw_insnTy, 0);
+		ipfw_insnPtrTy = PointerType::get(ipfw_insnTy, 0);
 		ipfw_insn_ifPtrTy = PointerType::get(ipfw_insn_ifTy, 0);
 		mbufPtrTy = PointerType::get(mbufTy, 0);
 #ifdef __FreeBSD__
@@ -253,12 +270,15 @@
 		// Functions declared at bitcode.
 		printfFunc = mod->getFunction("printf");
 		ipfw_find_rule = mod->getFunction("ipfw_find_rule");
+		crfree = mod->getFunction("crfree");
 	}
 
-	// Allocate and initialize vars.
+	// Allocate and initialize LLVM vars.
 	void
 	allocaAndInit(struct ip_fw_args *args, struct ip_fw_chain *chain)
 	{
+		irb.SetInsertPoint(entry);
+		// Control flow variables.
 		match = irb.CreateAlloca(int32Ty);
 		l = irb.CreateAlloca(int32Ty);
 		done = irb.CreateAlloca(int32Ty);
@@ -267,6 +287,11 @@
 		irb.CreateStore(ConstantInt::get(int32Ty, 0), f_pos);
 		retval = irb.CreateAlloca(int32Ty);
 		irb.CreateStore(ConstantInt::get(int32Ty, 0), retval);
+		cmd = irb.CreateAlloca(ipfw_insnPtrTy);
+		tablearg = irb.CreateAlloca(int32Ty);
+		cmdlen = irb.CreateAlloca(int32Ty);
+		skip_or = irb.CreateAlloca(int32Ty);
+		f = irb.CreateAlloca(ip_fwPtrTy);
 
 		// m = args->m (idx: 0)
 		m = irb.CreateAlloca(mbufPtrTy);
@@ -277,10 +302,10 @@
 		irb.CreateStore(irb.CreateBitCast(irb.CreateInBoundsGEP(argsptr, ConstantInt::get(int32Ty, 2)), ipPtrTy), ip);
 
 #ifdef __FreeBSD__
-		ucred = irb.CreateAlloca(ucredPtrTy); // Init: NULL if type ucred.
-		irb.CreateStore(ConstantPointerNull::get(ucredPtrTy), ucred);
+		ucred_cache = irb.CreateAlloca(ucredPtrTy); // Init: NULL if type ucred.
+		irb.CreateStore(ConstantPointerNull::get(ucredPtrTy), ucred_cache);
 #else
-		ucred = irb.CreateAlloca(ucredTy);
+		ucred_cache = irb.CreateAlloca(ucredTy);
 #endif
 
 		ucred_lookup = irb.CreateAlloca(int32Ty);
@@ -352,7 +377,9 @@
 	emit_pullup_failed()
 	{
 		Value *is_verbose, *str;
-		BasicBlock *print, *ret;
+
+		BasicBlock *print = BasicBlock::Create(con, "print", func);
+		BasicBlock *ret = BasicBlock::Create(con, "ret", func);
 
 		// VNET_DECLARE(int, fw_verbose);
 		// #define	V_fw_verbose		VNET(fw_verbose)
@@ -366,6 +393,8 @@
 		is_verbose = mod->getGlobalVariable("fw_verbose");
 		str = irb.CreateGlobalString("ipfw: pullup failed\n");
 
+		irb.SetInsertPoint(pullup_failed);
+
 		// if (V_fw_verbose)
 		irb.CreateCondBr(irb.CreateICmpEQ(is_verbose, ConstantInt::get(int32Ty, 0)), ret, print);
 		// printf("ipfw: pullup failed\n");
@@ -381,8 +410,10 @@
 	void
 	emit_check_tag()
 	{
-		BasicBlock *tagged, *nottagged;
-		BasicBlock *yes, *no;
+		BasicBlock *tagged = BasicBlock::Create(con, "tagged", func);
+		BasicBlock *nottagged = BasicBlock::Create(con, "nottagged", func);
+		BasicBlock *jt = BasicBlock::Create(con, "jt", func);
+		BasicBlock *jf = BasicBlock::Create(con, "jf", func);
 
 		// if (args->rule.slot) {
 		// 	/*
@@ -404,15 +435,15 @@
 		irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4),ConstantInt::get(int32Ty, 0)}), ConstantInt::get(int32Ty, 0)), nottagged, tagged);
 		// if (args->rule.chain_id == chain->id)
 		irb.SetInsertPoint(tagged);
-		irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4), ConstantInt::get(int32Ty, 3)}), irb.CreateInBoundsGEP(chainptr, ConstantInt::get(int32Ty, 12))), yes, no);
+		irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4), ConstantInt::get(int32Ty, 3)}), irb.CreateInBoundsGEP(chainptr, ConstantInt::get(int32Ty, 12))), jt, jf);
 
 		// f_pos = args->rule.slot;
-		irb.SetInsertPoint(yes);
+		irb.SetInsertPoint(jt);
 		irb.CreateStore(irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4),ConstantInt::get(int32Ty, 0)}), f_pos);
 		irb.CreateBr(nottagged);
 
 		// else fpos = ipfw_find_rule(chain, args->rule.rulenum, args->rule.rule_id)
-		irb.SetInsertPoint(no);
+		irb.SetInsertPoint(jf);
 		irb.CreateStore(irb.CreateCall3(ipfw_find_rule, chainptr, irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4), ConstantInt::get(int32Ty, 1)}), irb.CreateInBoundsGEP(argsptr, {ConstantInt::get(int32Ty, 4), ConstantInt::get(int32Ty, 2)})), f_pos);
 
 		// Branch to nottagged because it
@@ -425,6 +456,249 @@
 		irb.CreateBr(startrules);
 	}
 
+	void
+	emit_outer_for_prologue()
+	{
+		BasicBlock *jt = BasicBlock::Create(con, "jt", func);
+		BasicBlock *jf = BasicBlock::Create(con, "jf", func);
+		Value *set_disable = mod->getGlobalVariable("set_disable");
+
+		// All this variables are already allocated.
+		// ipfw_insn *cmd;
+		// uint32_t tablearg = 0;
+		// int l, cmdlen, skip_or; /* skip rest of OR block */
+		// struct ip_fw *f;
+		// f = chain->map[f_pos];
+		// if (V_set_disable & (1 << f->set) )
+		// 	continue;
+		// skip_or = 0;
+
+		irb.SetInsertPoint(outer_for_prologue);
+		// uint32_t tablearg = 0;
+		irb.CreateStore(ConstantInt::get(int32Ty, 0), tablearg);
+
+		// f = chain->map[f_pos];
+		irb.CreateStore(irb.CreateInBoundsGEP(chainptr, {ConstantInt::get(int32Ty, 5), f_pos}), f);
+
+		// if (V_set_disable & (1 << f->set) )
+		irb.CreateCondBr(irb.CreateICmpNE(irb.CreateAnd(set_disable, irb.CreateShl(ConstantInt::get(int32Ty, 1), irb.CreateInBoundsGEP(f, ConstantInt::get(int32Ty, 5)))), ConstantInt::get(int32Ty, 0)), jt, jf);
+
+		irb.SetInsertPoint(jt);
+		//		continue;
+		irb.CreateBr(next);
+
+		// skip_or = 0;
+		irb.SetInsertPoint(jf);
+		irb.CreateStore(ConstantInt::get(int32Ty, 0), skip_or);
+
+		irb.CreateBr(inner_for_prologue);
+	}
+
+	void
+	emit_inner_for_prologue()
+	{
+		BasicBlock *firstt = BasicBlock::Create(con, "firstt", func);
+		BasicBlock *firstf = BasicBlock::Create(con, "firstf", func);
+		BasicBlock *secondt = BasicBlock::Create(con, "secondt", func);
+		BasicBlock *secondf = BasicBlock::Create(con, "secondf", func);
+
+		// The first to are the intializers of the for loop.
+		//	l = f->cmd_len;
+		//	cmd = f->cmd;
+		//
+		// 	int match;
+		// 	cmdlen = F_LEN(cmd);
+		// 	if (skip_or) {		/* skip this instruction */
+		// 		if ((cmd->len & F_OR) == 0)
+		// 			skip_or = 0;	/* next one is good */
+		// 		continue;
+		// 	}
+		// 	match = 0; /* set to 1 if we succeed */
+		irb.SetInsertPoint(inner_for_prologue);
+
+		// l = f->cmd_len;
+		// XXX - ask David about types. int l; uint16_t cmd_len;
+		irb.CreateStore(irb.CreateInBoundsGEP(f, ConstantInt::get(int32Ty, 3)), l);
+		// cmd = f->cmd;
+		irb.CreateStore(irb.CreateInBoundsGEP(f, ConstantInt::get(int32Ty, 11)), cmd);
+		// int match;
+		// match is already allocated.
+
+		// cmdlen = ((cmd)->len & F_LEN_MASK);
+		irb.CreateStore(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, ConstantInt::get(int32Ty, 1)), ConstantInt::get(int8Ty, F_LEN_MASK)), cmdlen);
+
+		// if (skip_or)
+		irb.CreateCondBr(irb.CreateICmpNE(skip_or, ConstantInt::get(int32Ty, 0)), firstt, firstf);
+
+		irb.SetInsertPoint(firstt);
+		// if ((cmd->len & F_OR) == 0)
+		irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, ConstantInt::get(int32Ty, 1)), ConstantInt::get(int8Ty, F_OR)), ConstantInt::get(int8Ty, 0)), secondt, secondf);
+
+		irb.SetInsertPoint(secondt);
+		// skip_or = 0;
+		irb.CreateStore(ConstantInt::get(int32Ty, 0), skip_or);
+		irb.CreateBr(secondf);
+
+		irb.SetInsertPoint(secondf);
+		// continue;
+		irb.CreateBr(next);
+
+		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()
+	{
+		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;
+		irb.CreateStore(irb.CreateNSWSub(l, cmdlen), l);
+		irb.CreateStore(irb.CreateAdd(cmd, cmdlen), cmd);
+
+		// if (cmd->len & F_NOT)
+		// 	match = !match;
+		//
+		// if (match) {
+		// 	if (cmd->len & F_OR)
+		// 		skip_or = 1;
+		// } else {
+		// 	if (!(cmd->len & F_OR)) /* not an OR block, */
+		// 		break;		/* try next rule    */
+		// }
+
+		irb.SetInsertPoint(inner_for_epilogue);
+
+		// if (cmd->len & F_NOT)
+		irb.CreateCondBr(irb.CreateICmpNE(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, ConstantInt::get(int32Ty, 1)), ConstantInt::get(int8Ty, F_NOT)), ConstantInt::get(int32Ty, 0)), jt, sec_cond);
+
+		irb.SetInsertPoint(jt);
+		// match = !match;
+		irb.CreateStore(irb.CreateNot(match), match);
+		irb.CreateBr(sec_cond);
+
+		irb.SetInsertPoint(sec_cond);
+		// if (match)
+		irb.CreateCondBr(irb.CreateICmpNE(match, ConstantInt::get(int32Ty, 0)), matchnotzero, matchzero);
+
+		irb.SetInsertPoint(matchnotzero);
+		// if (cmd->len & F_OR)
+		irb.CreateCondBr(irb.CreateICmpNE(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, ConstantInt::get(int32Ty, 1)), ConstantInt::get(int8Ty, F_OR)), ConstantInt::get(int32Ty, 0)), is_or, outer_for_epilogue);
+
+		irb.SetInsertPoint(is_or);
+		// skip_or = 1;
+		irb.CreateStore(ConstantInt::get(int32Ty, 1), skip_or);
+		irb.CreateBr(outer_for_epilogue);
+
+		irb.SetInsertPoint(matchzero);
+		// if (!(cmd->len & F_OR)) /* not an OR block, */
+		//     break;
+		irb.CreateCondBr(irb.CreateICmpNE(irb.CreateNot(irb.CreateAnd(irb.CreateInBoundsGEP(cmd, ConstantInt::get(int32Ty, 1)), ConstantInt::get(int8Ty, F_OR))), ConstantInt::get(int32Ty, 0)), next /* break */, outer_for_epilogue);
+	}
+
+	// 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()
+	{
+		// f_pos++, increment of the for loop.
+		irb.CreateStore(irb.CreateAdd(f_pos, ConstantInt::get(int32Ty, 1)), f_pos);
+
+		// if (done)
+		//		break;
+		irb.CreateCondBr(irb.CreateICmpNE(done, ConstantInt::get(int32Ty, 0)), end, next);
+
+	}
+
+	void
+	emit_end()
+	{
+		Value *rule, *timestamp, *str;
+
+		BasicBlock *jt = BasicBlock::Create(con, "jt", func);
+		BasicBlock *jf = BasicBlock::Create(con, "jf", func);
+		BasicBlock *ret = BasicBlock::Create(con, "ret", func);
+
+		// if (done) {
+		//		struct ip_fw *rule = chain->map[f_pos];
+		//		/* Update statistics */
+		//		(rule)->pcnt++;
+		//		(rule)->bcnt += pktlen;
+		//		(rule)->timestamp = time_uptime;
+		// } else {
+		//		retval = IP_FW_DENY;
+		//		printf("ipfw: ouch!, skip past end of rules, denying packet\n");
+		// }
+		//
+		// #ifdef __FreeBSD__
+		// 	if (ucred_cache != NULL)
+		// 		crfree(ucred_cache);
+		// #endif
+		//
+		// return (retval);
+
+		irb.SetInsertPoint(end);
+		// We need to get the timestamp variable.
+		timestamp = mod->getGlobalVariable("timestamp");
+		str = irb.CreateGlobalString("ipfw: ouch!, skip past end of rules, denying packet\n");
+
+		// if (done)
+		irb.CreateCondBr(irb.CreateICmpNE(done, ConstantInt::get(int32Ty, 0)), jt, jf);
+
+		irb.SetInsertPoint(jt);
+		// struct ip_fw *rule = chain->map[f_pos];
+		rule = irb.CreateAlloca(ip_fwPtrTy);
+		irb.CreateStore(irb.CreateInBoundsGEP(chainptr, {ConstantInt::get(int32Ty, 5), f_pos}), rule);
+
+		// uint64_t pcnt;
+		// (rule)->pcnt++;
+		irb.CreateStore(irb.CreateInBoundsGEP(rule, ConstantInt::get(int32Ty,8)), irb.CreateAdd(irb.CreateInBoundsGEP(rule, ConstantInt::get(int32Ty, 8)), ConstantInt::get(int64Ty, 1)));
+		// uint64_t bnct;
+		// (rule)->bcnt += pktlen;
+		irb.CreateStore(irb.CreateInBoundsGEP(rule, ConstantInt::get(int32Ty, 9)), irb.CreateAdd(irb.CreateInBoundsGEP(rule, ConstantInt::get(int32Ty, 9)), pktlen));
+
+		// (rule)->timestamp = time_uptime;
+		// uint32_t timestamp;
+		irb.CreateStore(irb.CreateInBoundsGEP(rule, ConstantInt::get(int32Ty, 10)), timestamp);
+
+		irb.SetInsertPoint(jf);
+		//	retval = IP_FW_DENY;
+		//	printf("ipfw: ouch!, skip past end of rules, denying packet\n");
+		irb.CreateStore(ConstantInt::get(int32Ty, IP_FW_DENY), retval);
+		irb.CreateCall(printfFunc, str);
+#ifndef __FreeBSD__
+		irb.CreateBr(ret);
+#endif
+
+#ifdef __FreeBSD__
+		{
+			irb.SetInsertPoint(end);
+			BasicBlock *cache_nnull;
+			// 	if (ucred_cache != NULL)
+			irb.CreateCondBr(irb.CreateICmpNE(ucred_cache, ConstantPointerNull::get(ucredPtrTy)), cache_nnull, ret);
+
+			irb.SetInsertPoint(cache_nnull);
+			// 		crfree(ucred_cache);
+			irb.CreateCall(crfree, ucred_cache);
+			irb.CreateBr(ret);
+		}
+#endif
+
+		irb.SetInsertPoint(ret);
+		irb.CreateRet(retval);
+	}
+
 	public:
 	ipfwJIT(struct ip_fw_args *args, struct ip_fw_chain *chain): irb(con)
 	{
@@ -446,15 +720,26 @@
 		// This will be executed at the end of ipfw_chk_jit().
 		end = BasicBlock::Create(con, "end", 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);
+		inner_for_epilogue = BasicBlock::Create(con, "inner_for_epilogue", func);
+		outer_for_epilogue = BasicBlock::Create(con, "outer_for_epilogue", func);
+
 		// Get struct types, and store vars
-		irb.SetInsertPoint(entry);
 		setEnv();
 		allocaAndInit(args, chain);
 
 		emit_check_tag();
-
-		irb.SetInsertPoint(pullup_failed);
 		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()
 	{
@@ -477,60 +762,41 @@
 
 	// Call the function that fills in some vars.
 	void
-	emit_lookpkt()
+	emit_lookpkt_call()
 	{
 		// If it returns one, goto pullup_failed.
 		// Else, goto starrules.
 		irb.CreateCondBr(irb.CreateICmpEQ(irb.CreateCall(inspect_pkt, {argsptr, ip, m, src_ip, dst_ip, src_port, dst_port, etype, ext_hd, iplen, pktlen, is_ipv4, is_ipv6, hlen, proto, icmp6_type, ip6f_mf, offset, ulp}), ConstantInt::get(int32Ty, 1)), pullup_failed, startrules);
-		return;
 	}
 
-	// We get here ar the end of switch() on opcodes.
-	// XXX
 	void
-	emit_end_switch()
+	emit_outer_for_prologue_call()
 	{
-		// /* if we get here with l=0, then match is irrelevant. */
-		// if (cmd->len & F_NOT)
-		// 	match = !match;
+		irb.CreateBr(outer_for_prologue);
+	}
 
-		// if (match) {
-		// 	if (cmd->len & F_OR)
-		// 		skip_or = 1;
-		// } else {
-		// 	if (!(cmd->len & F_OR)) /* not an OR block, */
-		// 		break;		/* try next rule    */
-		// }
+	void
+	emit_inner_for_prologue_call()
+	{
+		irb.CreateBr(inner_for_prologue);
 	}
 
-	// This code gets executed at the end of inner loop.
-	// In this context, break means goto end, else continue loop.
 	void
-	emit_end_opcodes()
+	emit_inner_for_epilogue_call()
 	{
-		// if (done)
-		//	break;
-		irb.CreateCondBr(irb.CreateCmpNE(done, ConstantInt::get(int32Ty, 0)), end, next);
+		irb.CreateBr(inner_for_epilogue);
 	}
 
-	// This will emit some code executed at the end.
-	// And set up basic blocks, if necessary.
-	// XXX
 	void
-	emit_end()
+	emit_outer_for_epilogue_call()
 	{
-		// if (done) {
-		//		struct ip_fw *rule = chain->map[f_pos];
-		//		/* Update statistics */
-		//		(rule)->pcnt++;
-		//		(rule)->bcnt += pktlen;
-		//		(rule)->timestamp = time_uptime;
-		// } else {
-		//		retval = IP_FW_DENY;
-		//		printf("ipfw: ouch!, skip past end of rules, denying packet\n");
-		// }
+		irb.CreateBr(outer_for_epilogue);
+	}
 
-		irb.SetInsertPoint(end);
+	void
+	emit_end_call()
+	{
+		irb.CreateBr(end);
 	}
 
 	// Rules
@@ -567,13 +833,13 @@
 extern "C" funcptr
 compile_code(struct ip_fw_args *args, struct ip_fw_chain *chain)
 {
-	ipfwJIT comp(args, chain);
+	ipfwJIT compiler(args, chain);
 
 	int res;
 	int f_pos = 0;
 
-	// Fill up needed variables type.
-	comp.emit_lookpkt();
+	// Fill up needed local variables.
+	compiler.emit_lookpkt_call();
 
 	// Iterate through the rules.
 	int pktlen = args->m->m_pkthdr.len;
@@ -587,208 +853,211 @@
 
 		f = chain->map[f_pos];
 
+		compiler.emit_outer_for_prologue_call();
+
 		// 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();
 			switch (cmd->opcode) {
 			case O_NOP:
-				comp.emit_nop();
+				compiler.emit_nop();
 				break;
 
 			case O_FORWARD_MAC:
-				comp.emit_forward_mac(cmd->opcode);
+				compiler.emit_forward_mac(cmd->opcode);
 				break;
 
 			case O_GID:
 			case O_UID:
 			case O_JAIL:
-				comp.emit_jail();
+				compiler.emit_jail();
 				break;
 
 			case O_RECV:
-				comp.emit_recv();
+				compiler.emit_recv();
 				break;
 
 /* XXX
 			case O_XMIT:
-				comp.emit_xmit();
+				compiler.emit_xmit();
 				break;
 
 			case O_VIA:
-				comp.emit_via();
+				compiler.emit_via();
 				break;
 
 			case O_MACADDR2:
-				comp.emit_macaddr2();
+				compiler.emit_macaddr2();
 				break;
 
 			case O_MAC_TYPE:
-				comp.emit_mac_type();
+				compiler.emit_mac_type();
 				break;
 
 			case O_FRAG:
-				comp.emit_frag();
+				compiler.emit_frag();
 				break;
 
 			case O_IN:
-				comp.emit_in();
+				compiler.emit_in();
 				break;
 
 			case O_LAYER2:
-				comp.emit_layer2();
+				compiler.emit_layer2();
 				break;
 
 			case O_DIVERTED:
-				comp.emit_diverted();
+				compiler.emit_diverted();
 				break;
 
 			case O_PROTO:
-				comp.emit_proto();
+				compiler.emit_proto();
 				break;
 
 			case O_IP_SRC:
-				comp.emit_ip_src();
+				compiler.emit_ip_src();
 				break;
 
 			case O_IP_SRC_LOOKUP:
 			case O_IP_DST_LOOKUP:
-				comp.emit_ip_dst_lookup();
+				compiler.emit_ip_dst_lookup();
 				break;
 
 			case O_IP_SRC_MASK:
 			case O_IP_DST_MASK:
-				comp.emit_ip_dst_mask();
+				compiler.emit_ip_dst_mask();
 				break;
 
 			case O_IP_SRC_ME:
-				comp.emit_ip_src_me();
+				compiler.emit_ip_src_me();
 #ifdef INET6
 				/* FALLTHROUGH */
 /* XXX
 			case O_IP6_SRC_ME:
-				comp.emit_ip6_src_me();
+				compiler.emit_ip6_src_me();
 #endif
 				break;
 
 			case O_IP_DST_SET:
 			case O_IP_SRC_SET:
-				comp.emit_ip_src_set();
+				compiler.emit_ip_src_set();
 				break;
 
 			case O_IP_DST:
-				comp.emit_ip_dst();
+				compiler.emit_ip_dst();
 				break;
 
 			case O_IP_DST_ME:
-				comp.emit_ip_dst_me();
+				compiler.emit_ip_dst_me();
 				
 #ifdef INET6
 				/* FALLTHROUGH */
 /* XXX
 			case O_IP6_DST_ME:
-				comp.emit_ip6_dst_me();
+				compiler.emit_ip6_dst_me();
 #endif
 				break;
 
 
 			case O_IP_SRCPORT:
 			case O_IP_DSTPORT:
-				comp.emit_ip_dstport();
+				compiler.emit_ip_dstport();
 				break;
 
 			case O_ICMPTYPE:
-				comp.emit_icmptype();
+				compiler.emit_icmptype();
 				break;
 
 #ifdef INET6
 			case O_ICMP6TYPE:
-				comp.emit_icmp6type();
+				compiler.emit_icmp6type();
 				break;
 #endif /* INET6 */
 /*
 			case O_IPOPT:
-				comp.emit_ipopt();
+				compiler.emit_ipopt();
 				break;
 
 			case O_IPVER:
-				comp.emit_ipver();
+				compiler.emit_ipver();
 				break;
 
 			case O_IPID:
 			case O_IPLEN:
 			case O_IPTTL:
-				comp.emit_ipttl();
+				compiler.emit_ipttl();
 				break;
 
 			case O_IPPRECEDENCE:
-				comp.emit_ipprecedence();
+				compiler.emit_ipprecedence();
 				break;
 
 			case O_IPTOS:
-				comp.emit_iptos();
+				compiler.emit_iptos();
 				break;
 
 			case O_DSCP:
-				comp.emit_dscp();
+				compiler.emit_dscp();
 				break;
 
 			case O_TCPDATALEN:
-				comp.emit_tcpdatalen();
+				compiler.emit_tcpdatalen();
 				break;
 
 			case O_TCPFLAGS:
-				comp.emit_tcpflags();
+				compiler.emit_tcpflags();
 				break;
 
 			case O_TCPOPTS:
-				comp.emit_tcpopts();
+				compiler.emit_tcpopts();
 				break;
 
 			case O_TCPSEQ:
-				comp.emit_tcpseq();
+				compiler.emit_tcpseq();
 				break;
 
 			case O_TCPACK:
-				comp.emit_tcpack();
+				compiler.emit_tcpack();
 				break;
 
 			case O_TCPWIN:
-				comp.emit_tcpwin();
+				compiler.emit_tcpwin();
 				break;
 
 			case O_ESTAB:
-				comp.emit_estab();
+				compiler.emit_estab();
 				break;
 
 			case O_ALTQ:
-				comp.emit_altq();
+				compiler.emit_altq();
 				break;
 
 			case O_LOG:
-				comp.emit_log();
+				compiler.emit_log();
 				break;
 
 			case O_PROB:
-				comp.emit_prob();
+				compiler.emit_prob();
 				break;
 
 			case O_VERREVPATH:
-				comp.emit_verrevpath();
+				compiler.emit_verrevpath();
 				break;
 
 			case O_VERSRCREACH:
-				comp.emit_versrcreach();
+				compiler.emit_versrcreach();
 				break;
 
 			case O_ANTISPOOF:
-				comp.emit_antispoof();
+				compiler.emit_antispoof();
 				break;
 
 			case O_IPSEC:
 #ifdef IPSEC
-				comp.emit_ipsec();
+				compiler.emit_ipsec();
 #endif
 				/* otherwise no match */
 /* XXX
@@ -796,50 +1065,50 @@
 
 #ifdef INET6
 			case O_IP6_SRC:
-				comp.emit_ip6_src();
+				compiler.emit_ip6_src();
 				break;
 
 			case O_IP6_DST:
-				comp.emit_ip6_dst();
+				compiler.emit_ip6_dst();
 				break;
 
 			case O_IP6_SRC_MASK:
 			case O_IP6_DST_MASK:
-				comp.emit_ip6_dst_mask();
+				compiler.emit_ip6_dst_mask();
 				break;
 
 			case O_FLOW6ID:
-				comp.emit_flow6id();
+				compiler.emit_flow6id();
 				break;
 
 			case O_EXT_HDR:
-				comp.emit_ext_hdr();
+				compiler.emit_ext_hdr();
 				break;
 
 			case O_IP6:
-				comp.emit_ip6();
+				compiler.emit_ip6();
 				break;
 #endif
 
 			case O_IP4:
-				comp.emit_ip4();
+				compiler.emit_ip4();
 				break;
 
 			case O_TAG: 
-				comp.emit_tag();
+				compiler.emit_tag();
 				break;
 
 			case O_FIB: /* try match the specified fib */
 /* XXX
-				comp.emit_fib();
+				compiler.emit_fib();
 				break;
 
 			case O_SOCKARG:
-				comp.emit_sockarg();
+				compiler.emit_sockarg();
 				break;
 
 			case O_TAGGED:
-				comp.emit_tagged();
+				compiler.emit_tagged();
 				break;
 				
 			/*
@@ -886,101 +1155,101 @@
 /* XXX
 			case O_LIMIT:
 			case O_KEEP_STATE:
-				comp.emit_keep_state();
+				compiler.emit_keep_state();
 				break;
 
 			case O_PROBE_STATE:
 			case O_CHECK_STATE:
-				comp.emit_check_state();
+				compiler.emit_check_state();
 				break;
 
 			case O_ACCEPT:
-				comp.emit_accept();
+				compiler.emit_accept();
 				break;
 
 			case O_PIPE:
 			case O_QUEUE:
-				comp.emit_queue();
+				compiler.emit_queue();
 				break;
 
 			case O_DIVERT:
 			case O_TEE:
-				comp.emit_tee();
+				compiler.emit_tee();
 				break;
 
 			case O_COUNT:
-				comp.emit_count();
+				compiler.emit_count();
 				break;
 
 			case O_SKIPTO:
-				comp.emit_skipto();
+				compiler.emit_skipto();
 			    continue;
 			    break;	/* NOTREACHED */
 
 /* XXX
 			case O_CALLRETURN:
-				comp.emit_callreturn();
+				compiler.emit_callreturn();
 				continue;
 				break;	/* NOTREACHED */
 /* XXX
 
 			case O_REJECT:
-				comp.emit_reject();
+				compiler.emit_reject();
 				/* FALLTHROUGH */
 /* XXX
 #ifdef INET6
 			case O_UNREACH6:
-				comp.emit_unreach6();
+				compiler.emit_unreach6();
 				/* FALLTHROUGH */
 /* XXX
 #endif
 			case O_DENY:
-				comp.emit_deny();
+				compiler.emit_deny();
 				break;
 
 			case O_FORWARD_IP:
-				comp.emit_forward_ip();
+				compiler.emit_forward_ip();
 				break;
 
 #ifdef INET6
 			case O_FORWARD_IP6:
-				comp.emit_forward_ip6();
+				compiler.emit_forward_ip6();
 				break;
 #endif
 
 			case O_NETGRAPH:
 			case O_NGTEE:
-				comp.emit_ngtee();
+				compiler.emit_ngtee();

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-soc-all mailing list