xref: /aosp_15_r20/external/libpcap/optimize.c (revision 8b26181f966a6af5cf6981a6f474313de533bb28)
1*8b26181fSAndroid Build Coastguard Worker /*
2*8b26181fSAndroid Build Coastguard Worker  * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
3*8b26181fSAndroid Build Coastguard Worker  *	The Regents of the University of California.  All rights reserved.
4*8b26181fSAndroid Build Coastguard Worker  *
5*8b26181fSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*8b26181fSAndroid Build Coastguard Worker  * modification, are permitted provided that: (1) source code distributions
7*8b26181fSAndroid Build Coastguard Worker  * retain the above copyright notice and this paragraph in its entirety, (2)
8*8b26181fSAndroid Build Coastguard Worker  * distributions including binary code include the above copyright notice and
9*8b26181fSAndroid Build Coastguard Worker  * this paragraph in its entirety in the documentation or other materials
10*8b26181fSAndroid Build Coastguard Worker  * provided with the distribution, and (3) all advertising materials mentioning
11*8b26181fSAndroid Build Coastguard Worker  * features or use of this software display the following acknowledgement:
12*8b26181fSAndroid Build Coastguard Worker  * ``This product includes software developed by the University of California,
13*8b26181fSAndroid Build Coastguard Worker  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*8b26181fSAndroid Build Coastguard Worker  * the University nor the names of its contributors may be used to endorse
15*8b26181fSAndroid Build Coastguard Worker  * or promote products derived from this software without specific prior
16*8b26181fSAndroid Build Coastguard Worker  * written permission.
17*8b26181fSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*8b26181fSAndroid Build Coastguard Worker  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*8b26181fSAndroid Build Coastguard Worker  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*8b26181fSAndroid Build Coastguard Worker  *
21*8b26181fSAndroid Build Coastguard Worker  *  Optimization module for BPF code intermediate representation.
22*8b26181fSAndroid Build Coastguard Worker  */
23*8b26181fSAndroid Build Coastguard Worker 
24*8b26181fSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
25*8b26181fSAndroid Build Coastguard Worker #include <config.h>
26*8b26181fSAndroid Build Coastguard Worker #endif
27*8b26181fSAndroid Build Coastguard Worker 
28*8b26181fSAndroid Build Coastguard Worker #include <pcap-types.h>
29*8b26181fSAndroid Build Coastguard Worker 
30*8b26181fSAndroid Build Coastguard Worker #include <stdio.h>
31*8b26181fSAndroid Build Coastguard Worker #include <stdlib.h>
32*8b26181fSAndroid Build Coastguard Worker #include <memory.h>
33*8b26181fSAndroid Build Coastguard Worker #include <setjmp.h>
34*8b26181fSAndroid Build Coastguard Worker #include <string.h>
35*8b26181fSAndroid Build Coastguard Worker #include <limits.h> /* for SIZE_MAX */
36*8b26181fSAndroid Build Coastguard Worker #include <errno.h>
37*8b26181fSAndroid Build Coastguard Worker 
38*8b26181fSAndroid Build Coastguard Worker #include "pcap-int.h"
39*8b26181fSAndroid Build Coastguard Worker 
40*8b26181fSAndroid Build Coastguard Worker #include "gencode.h"
41*8b26181fSAndroid Build Coastguard Worker #include "optimize.h"
42*8b26181fSAndroid Build Coastguard Worker #include "diag-control.h"
43*8b26181fSAndroid Build Coastguard Worker 
44*8b26181fSAndroid Build Coastguard Worker #ifdef HAVE_OS_PROTO_H
45*8b26181fSAndroid Build Coastguard Worker #include "os-proto.h"
46*8b26181fSAndroid Build Coastguard Worker #endif
47*8b26181fSAndroid Build Coastguard Worker 
48*8b26181fSAndroid Build Coastguard Worker #ifdef BDEBUG
49*8b26181fSAndroid Build Coastguard Worker /*
50*8b26181fSAndroid Build Coastguard Worker  * The internal "debug printout" flag for the filter expression optimizer.
51*8b26181fSAndroid Build Coastguard Worker  * The code to print that stuff is present only if BDEBUG is defined, so
52*8b26181fSAndroid Build Coastguard Worker  * the flag, and the routine to set it, are defined only if BDEBUG is
53*8b26181fSAndroid Build Coastguard Worker  * defined.
54*8b26181fSAndroid Build Coastguard Worker  */
55*8b26181fSAndroid Build Coastguard Worker static int pcap_optimizer_debug;
56*8b26181fSAndroid Build Coastguard Worker 
57*8b26181fSAndroid Build Coastguard Worker /*
58*8b26181fSAndroid Build Coastguard Worker  * Routine to set that flag.
59*8b26181fSAndroid Build Coastguard Worker  *
60*8b26181fSAndroid Build Coastguard Worker  * This is intended for libpcap developers, not for general use.
61*8b26181fSAndroid Build Coastguard Worker  * If you want to set these in a program, you'll have to declare this
62*8b26181fSAndroid Build Coastguard Worker  * routine yourself, with the appropriate DLL import attribute on Windows;
63*8b26181fSAndroid Build Coastguard Worker  * it's not declared in any header file, and won't be declared in any
64*8b26181fSAndroid Build Coastguard Worker  * header file provided by libpcap.
65*8b26181fSAndroid Build Coastguard Worker  */
66*8b26181fSAndroid Build Coastguard Worker PCAP_API void pcap_set_optimizer_debug(int value);
67*8b26181fSAndroid Build Coastguard Worker 
68*8b26181fSAndroid Build Coastguard Worker PCAP_API_DEF void
pcap_set_optimizer_debug(int value)69*8b26181fSAndroid Build Coastguard Worker pcap_set_optimizer_debug(int value)
70*8b26181fSAndroid Build Coastguard Worker {
71*8b26181fSAndroid Build Coastguard Worker 	pcap_optimizer_debug = value;
72*8b26181fSAndroid Build Coastguard Worker }
73*8b26181fSAndroid Build Coastguard Worker 
74*8b26181fSAndroid Build Coastguard Worker /*
75*8b26181fSAndroid Build Coastguard Worker  * The internal "print dot graph" flag for the filter expression optimizer.
76*8b26181fSAndroid Build Coastguard Worker  * The code to print that stuff is present only if BDEBUG is defined, so
77*8b26181fSAndroid Build Coastguard Worker  * the flag, and the routine to set it, are defined only if BDEBUG is
78*8b26181fSAndroid Build Coastguard Worker  * defined.
79*8b26181fSAndroid Build Coastguard Worker  */
80*8b26181fSAndroid Build Coastguard Worker static int pcap_print_dot_graph;
81*8b26181fSAndroid Build Coastguard Worker 
82*8b26181fSAndroid Build Coastguard Worker /*
83*8b26181fSAndroid Build Coastguard Worker  * Routine to set that flag.
84*8b26181fSAndroid Build Coastguard Worker  *
85*8b26181fSAndroid Build Coastguard Worker  * This is intended for libpcap developers, not for general use.
86*8b26181fSAndroid Build Coastguard Worker  * If you want to set these in a program, you'll have to declare this
87*8b26181fSAndroid Build Coastguard Worker  * routine yourself, with the appropriate DLL import attribute on Windows;
88*8b26181fSAndroid Build Coastguard Worker  * it's not declared in any header file, and won't be declared in any
89*8b26181fSAndroid Build Coastguard Worker  * header file provided by libpcap.
90*8b26181fSAndroid Build Coastguard Worker  */
91*8b26181fSAndroid Build Coastguard Worker PCAP_API void pcap_set_print_dot_graph(int value);
92*8b26181fSAndroid Build Coastguard Worker 
93*8b26181fSAndroid Build Coastguard Worker PCAP_API_DEF void
pcap_set_print_dot_graph(int value)94*8b26181fSAndroid Build Coastguard Worker pcap_set_print_dot_graph(int value)
95*8b26181fSAndroid Build Coastguard Worker {
96*8b26181fSAndroid Build Coastguard Worker 	pcap_print_dot_graph = value;
97*8b26181fSAndroid Build Coastguard Worker }
98*8b26181fSAndroid Build Coastguard Worker 
99*8b26181fSAndroid Build Coastguard Worker #endif
100*8b26181fSAndroid Build Coastguard Worker 
101*8b26181fSAndroid Build Coastguard Worker /*
102*8b26181fSAndroid Build Coastguard Worker  * lowest_set_bit().
103*8b26181fSAndroid Build Coastguard Worker  *
104*8b26181fSAndroid Build Coastguard Worker  * Takes a 32-bit integer as an argument.
105*8b26181fSAndroid Build Coastguard Worker  *
106*8b26181fSAndroid Build Coastguard Worker  * If handed a non-zero value, returns the index of the lowest set bit,
107*8b26181fSAndroid Build Coastguard Worker  * counting upwards from zero.
108*8b26181fSAndroid Build Coastguard Worker  *
109*8b26181fSAndroid Build Coastguard Worker  * If handed zero, the results are platform- and compiler-dependent.
110*8b26181fSAndroid Build Coastguard Worker  * Keep it out of the light, don't give it any water, don't feed it
111*8b26181fSAndroid Build Coastguard Worker  * after midnight, and don't pass zero to it.
112*8b26181fSAndroid Build Coastguard Worker  *
113*8b26181fSAndroid Build Coastguard Worker  * This is the same as the count of trailing zeroes in the word.
114*8b26181fSAndroid Build Coastguard Worker  */
115*8b26181fSAndroid Build Coastguard Worker #if PCAP_IS_AT_LEAST_GNUC_VERSION(3,4)
116*8b26181fSAndroid Build Coastguard Worker   /*
117*8b26181fSAndroid Build Coastguard Worker    * GCC 3.4 and later; we have __builtin_ctz().
118*8b26181fSAndroid Build Coastguard Worker    */
119*8b26181fSAndroid Build Coastguard Worker   #define lowest_set_bit(mask) ((u_int)__builtin_ctz(mask))
120*8b26181fSAndroid Build Coastguard Worker #elif defined(_MSC_VER)
121*8b26181fSAndroid Build Coastguard Worker   /*
122*8b26181fSAndroid Build Coastguard Worker    * Visual Studio; we support only 2005 and later, so use
123*8b26181fSAndroid Build Coastguard Worker    * _BitScanForward().
124*8b26181fSAndroid Build Coastguard Worker    */
125*8b26181fSAndroid Build Coastguard Worker #include <intrin.h>
126*8b26181fSAndroid Build Coastguard Worker 
127*8b26181fSAndroid Build Coastguard Worker #ifndef __clang__
128*8b26181fSAndroid Build Coastguard Worker #pragma intrinsic(_BitScanForward)
129*8b26181fSAndroid Build Coastguard Worker #endif
130*8b26181fSAndroid Build Coastguard Worker 
131*8b26181fSAndroid Build Coastguard Worker static __forceinline u_int
lowest_set_bit(int mask)132*8b26181fSAndroid Build Coastguard Worker lowest_set_bit(int mask)
133*8b26181fSAndroid Build Coastguard Worker {
134*8b26181fSAndroid Build Coastguard Worker 	unsigned long bit;
135*8b26181fSAndroid Build Coastguard Worker 
136*8b26181fSAndroid Build Coastguard Worker 	/*
137*8b26181fSAndroid Build Coastguard Worker 	 * Don't sign-extend mask if long is longer than int.
138*8b26181fSAndroid Build Coastguard Worker 	 * (It's currently not, in MSVC, even on 64-bit platforms, but....)
139*8b26181fSAndroid Build Coastguard Worker 	 */
140*8b26181fSAndroid Build Coastguard Worker 	if (_BitScanForward(&bit, (unsigned int)mask) == 0)
141*8b26181fSAndroid Build Coastguard Worker 		abort();	/* mask is zero */
142*8b26181fSAndroid Build Coastguard Worker 	return (u_int)bit;
143*8b26181fSAndroid Build Coastguard Worker }
144*8b26181fSAndroid Build Coastguard Worker #elif defined(MSDOS) && defined(__DJGPP__)
145*8b26181fSAndroid Build Coastguard Worker   /*
146*8b26181fSAndroid Build Coastguard Worker    * MS-DOS with DJGPP, which declares ffs() in <string.h>, which
147*8b26181fSAndroid Build Coastguard Worker    * we've already included.
148*8b26181fSAndroid Build Coastguard Worker    */
149*8b26181fSAndroid Build Coastguard Worker   #define lowest_set_bit(mask)	((u_int)(ffs((mask)) - 1))
150*8b26181fSAndroid Build Coastguard Worker #elif (defined(MSDOS) && defined(__WATCOMC__)) || defined(STRINGS_H_DECLARES_FFS)
151*8b26181fSAndroid Build Coastguard Worker   /*
152*8b26181fSAndroid Build Coastguard Worker    * MS-DOS with Watcom C, which has <strings.h> and declares ffs() there,
153*8b26181fSAndroid Build Coastguard Worker    * or some other platform (UN*X conforming to a sufficient recent version
154*8b26181fSAndroid Build Coastguard Worker    * of the Single UNIX Specification).
155*8b26181fSAndroid Build Coastguard Worker    */
156*8b26181fSAndroid Build Coastguard Worker   #include <strings.h>
157*8b26181fSAndroid Build Coastguard Worker   #define lowest_set_bit(mask)	(u_int)((ffs((mask)) - 1))
158*8b26181fSAndroid Build Coastguard Worker #else
159*8b26181fSAndroid Build Coastguard Worker /*
160*8b26181fSAndroid Build Coastguard Worker  * None of the above.
161*8b26181fSAndroid Build Coastguard Worker  * Use a perfect-hash-function-based function.
162*8b26181fSAndroid Build Coastguard Worker  */
163*8b26181fSAndroid Build Coastguard Worker static u_int
lowest_set_bit(int mask)164*8b26181fSAndroid Build Coastguard Worker lowest_set_bit(int mask)
165*8b26181fSAndroid Build Coastguard Worker {
166*8b26181fSAndroid Build Coastguard Worker 	unsigned int v = (unsigned int)mask;
167*8b26181fSAndroid Build Coastguard Worker 
168*8b26181fSAndroid Build Coastguard Worker 	static const u_int MultiplyDeBruijnBitPosition[32] = {
169*8b26181fSAndroid Build Coastguard Worker 		0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
170*8b26181fSAndroid Build Coastguard Worker 		31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
171*8b26181fSAndroid Build Coastguard Worker 	};
172*8b26181fSAndroid Build Coastguard Worker 
173*8b26181fSAndroid Build Coastguard Worker 	/*
174*8b26181fSAndroid Build Coastguard Worker 	 * We strip off all but the lowermost set bit (v & ~v),
175*8b26181fSAndroid Build Coastguard Worker 	 * and perform a minimal perfect hash on it to look up the
176*8b26181fSAndroid Build Coastguard Worker 	 * number of low-order zero bits in a table.
177*8b26181fSAndroid Build Coastguard Worker 	 *
178*8b26181fSAndroid Build Coastguard Worker 	 * See:
179*8b26181fSAndroid Build Coastguard Worker 	 *
180*8b26181fSAndroid Build Coastguard Worker 	 *	http://7ooo.mooo.com/text/ComputingTrailingZerosHOWTO.pdf
181*8b26181fSAndroid Build Coastguard Worker 	 *
182*8b26181fSAndroid Build Coastguard Worker 	 *	http://supertech.csail.mit.edu/papers/debruijn.pdf
183*8b26181fSAndroid Build Coastguard Worker 	 */
184*8b26181fSAndroid Build Coastguard Worker 	return (MultiplyDeBruijnBitPosition[((v & -v) * 0x077CB531U) >> 27]);
185*8b26181fSAndroid Build Coastguard Worker }
186*8b26181fSAndroid Build Coastguard Worker #endif
187*8b26181fSAndroid Build Coastguard Worker 
188*8b26181fSAndroid Build Coastguard Worker /*
189*8b26181fSAndroid Build Coastguard Worker  * Represents a deleted instruction.
190*8b26181fSAndroid Build Coastguard Worker  */
191*8b26181fSAndroid Build Coastguard Worker #define NOP -1
192*8b26181fSAndroid Build Coastguard Worker 
193*8b26181fSAndroid Build Coastguard Worker /*
194*8b26181fSAndroid Build Coastguard Worker  * Register numbers for use-def values.
195*8b26181fSAndroid Build Coastguard Worker  * 0 through BPF_MEMWORDS-1 represent the corresponding scratch memory
196*8b26181fSAndroid Build Coastguard Worker  * location.  A_ATOM is the accumulator and X_ATOM is the index
197*8b26181fSAndroid Build Coastguard Worker  * register.
198*8b26181fSAndroid Build Coastguard Worker  */
199*8b26181fSAndroid Build Coastguard Worker #define A_ATOM BPF_MEMWORDS
200*8b26181fSAndroid Build Coastguard Worker #define X_ATOM (BPF_MEMWORDS+1)
201*8b26181fSAndroid Build Coastguard Worker 
202*8b26181fSAndroid Build Coastguard Worker /*
203*8b26181fSAndroid Build Coastguard Worker  * This define is used to represent *both* the accumulator and
204*8b26181fSAndroid Build Coastguard Worker  * x register in use-def computations.
205*8b26181fSAndroid Build Coastguard Worker  * Currently, the use-def code assumes only one definition per instruction.
206*8b26181fSAndroid Build Coastguard Worker  */
207*8b26181fSAndroid Build Coastguard Worker #define AX_ATOM N_ATOMS
208*8b26181fSAndroid Build Coastguard Worker 
209*8b26181fSAndroid Build Coastguard Worker /*
210*8b26181fSAndroid Build Coastguard Worker  * These data structures are used in a Cocke and Shwarz style
211*8b26181fSAndroid Build Coastguard Worker  * value numbering scheme.  Since the flowgraph is acyclic,
212*8b26181fSAndroid Build Coastguard Worker  * exit values can be propagated from a node's predecessors
213*8b26181fSAndroid Build Coastguard Worker  * provided it is uniquely defined.
214*8b26181fSAndroid Build Coastguard Worker  */
215*8b26181fSAndroid Build Coastguard Worker struct valnode {
216*8b26181fSAndroid Build Coastguard Worker 	int code;
217*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 v0, v1;
218*8b26181fSAndroid Build Coastguard Worker 	int val;		/* the value number */
219*8b26181fSAndroid Build Coastguard Worker 	struct valnode *next;
220*8b26181fSAndroid Build Coastguard Worker };
221*8b26181fSAndroid Build Coastguard Worker 
222*8b26181fSAndroid Build Coastguard Worker /* Integer constants mapped with the load immediate opcode. */
223*8b26181fSAndroid Build Coastguard Worker #define K(i) F(opt_state, BPF_LD|BPF_IMM|BPF_W, i, 0U)
224*8b26181fSAndroid Build Coastguard Worker 
225*8b26181fSAndroid Build Coastguard Worker struct vmapinfo {
226*8b26181fSAndroid Build Coastguard Worker 	int is_const;
227*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 const_val;
228*8b26181fSAndroid Build Coastguard Worker };
229*8b26181fSAndroid Build Coastguard Worker 
230*8b26181fSAndroid Build Coastguard Worker typedef struct {
231*8b26181fSAndroid Build Coastguard Worker 	/*
232*8b26181fSAndroid Build Coastguard Worker 	 * Place to longjmp to on an error.
233*8b26181fSAndroid Build Coastguard Worker 	 */
234*8b26181fSAndroid Build Coastguard Worker 	jmp_buf top_ctx;
235*8b26181fSAndroid Build Coastguard Worker 
236*8b26181fSAndroid Build Coastguard Worker 	/*
237*8b26181fSAndroid Build Coastguard Worker 	 * The buffer into which to put error message.
238*8b26181fSAndroid Build Coastguard Worker 	 */
239*8b26181fSAndroid Build Coastguard Worker 	char *errbuf;
240*8b26181fSAndroid Build Coastguard Worker 
241*8b26181fSAndroid Build Coastguard Worker 	/*
242*8b26181fSAndroid Build Coastguard Worker 	 * A flag to indicate that further optimization is needed.
243*8b26181fSAndroid Build Coastguard Worker 	 * Iterative passes are continued until a given pass yields no
244*8b26181fSAndroid Build Coastguard Worker 	 * code simplification or branch movement.
245*8b26181fSAndroid Build Coastguard Worker 	 */
246*8b26181fSAndroid Build Coastguard Worker 	int done;
247*8b26181fSAndroid Build Coastguard Worker 
248*8b26181fSAndroid Build Coastguard Worker 	/*
249*8b26181fSAndroid Build Coastguard Worker 	 * XXX - detect loops that do nothing but repeated AND/OR pullups
250*8b26181fSAndroid Build Coastguard Worker 	 * and edge moves.
251*8b26181fSAndroid Build Coastguard Worker 	 * If 100 passes in a row do nothing but that, treat that as a
252*8b26181fSAndroid Build Coastguard Worker 	 * sign that we're in a loop that just shuffles in a cycle in
253*8b26181fSAndroid Build Coastguard Worker 	 * which each pass just shuffles the code and we eventually
254*8b26181fSAndroid Build Coastguard Worker 	 * get back to the original configuration.
255*8b26181fSAndroid Build Coastguard Worker 	 *
256*8b26181fSAndroid Build Coastguard Worker 	 * XXX - we need a non-heuristic way of detecting, or preventing,
257*8b26181fSAndroid Build Coastguard Worker 	 * such a cycle.
258*8b26181fSAndroid Build Coastguard Worker 	 */
259*8b26181fSAndroid Build Coastguard Worker 	int non_branch_movement_performed;
260*8b26181fSAndroid Build Coastguard Worker 
261*8b26181fSAndroid Build Coastguard Worker 	u_int n_blocks;		/* number of blocks in the CFG; guaranteed to be > 0, as it's a RET instruction at a minimum */
262*8b26181fSAndroid Build Coastguard Worker 	struct block **blocks;
263*8b26181fSAndroid Build Coastguard Worker 	u_int n_edges;		/* twice n_blocks, so guaranteed to be > 0 */
264*8b26181fSAndroid Build Coastguard Worker 	struct edge **edges;
265*8b26181fSAndroid Build Coastguard Worker 
266*8b26181fSAndroid Build Coastguard Worker 	/*
267*8b26181fSAndroid Build Coastguard Worker 	 * A bit vector set representation of the dominators.
268*8b26181fSAndroid Build Coastguard Worker 	 * We round up the set size to the next power of two.
269*8b26181fSAndroid Build Coastguard Worker 	 */
270*8b26181fSAndroid Build Coastguard Worker 	u_int nodewords;	/* number of 32-bit words for a bit vector of "number of nodes" bits; guaranteed to be > 0 */
271*8b26181fSAndroid Build Coastguard Worker 	u_int edgewords;	/* number of 32-bit words for a bit vector of "number of edges" bits; guaranteed to be > 0 */
272*8b26181fSAndroid Build Coastguard Worker 	struct block **levels;
273*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 *space;
274*8b26181fSAndroid Build Coastguard Worker 
275*8b26181fSAndroid Build Coastguard Worker #define BITS_PER_WORD (8*sizeof(bpf_u_int32))
276*8b26181fSAndroid Build Coastguard Worker /*
277*8b26181fSAndroid Build Coastguard Worker  * True if a is in uset {p}
278*8b26181fSAndroid Build Coastguard Worker  */
279*8b26181fSAndroid Build Coastguard Worker #define SET_MEMBER(p, a) \
280*8b26181fSAndroid Build Coastguard Worker ((p)[(unsigned)(a) / BITS_PER_WORD] & ((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD)))
281*8b26181fSAndroid Build Coastguard Worker 
282*8b26181fSAndroid Build Coastguard Worker /*
283*8b26181fSAndroid Build Coastguard Worker  * Add 'a' to uset p.
284*8b26181fSAndroid Build Coastguard Worker  */
285*8b26181fSAndroid Build Coastguard Worker #define SET_INSERT(p, a) \
286*8b26181fSAndroid Build Coastguard Worker (p)[(unsigned)(a) / BITS_PER_WORD] |= ((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD))
287*8b26181fSAndroid Build Coastguard Worker 
288*8b26181fSAndroid Build Coastguard Worker /*
289*8b26181fSAndroid Build Coastguard Worker  * Delete 'a' from uset p.
290*8b26181fSAndroid Build Coastguard Worker  */
291*8b26181fSAndroid Build Coastguard Worker #define SET_DELETE(p, a) \
292*8b26181fSAndroid Build Coastguard Worker (p)[(unsigned)(a) / BITS_PER_WORD] &= ~((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD))
293*8b26181fSAndroid Build Coastguard Worker 
294*8b26181fSAndroid Build Coastguard Worker /*
295*8b26181fSAndroid Build Coastguard Worker  * a := a intersect b
296*8b26181fSAndroid Build Coastguard Worker  * n must be guaranteed to be > 0
297*8b26181fSAndroid Build Coastguard Worker  */
298*8b26181fSAndroid Build Coastguard Worker #define SET_INTERSECT(a, b, n)\
299*8b26181fSAndroid Build Coastguard Worker {\
300*8b26181fSAndroid Build Coastguard Worker 	register bpf_u_int32 *_x = a, *_y = b;\
301*8b26181fSAndroid Build Coastguard Worker 	register u_int _n = n;\
302*8b26181fSAndroid Build Coastguard Worker 	do *_x++ &= *_y++; while (--_n != 0);\
303*8b26181fSAndroid Build Coastguard Worker }
304*8b26181fSAndroid Build Coastguard Worker 
305*8b26181fSAndroid Build Coastguard Worker /*
306*8b26181fSAndroid Build Coastguard Worker  * a := a - b
307*8b26181fSAndroid Build Coastguard Worker  * n must be guaranteed to be > 0
308*8b26181fSAndroid Build Coastguard Worker  */
309*8b26181fSAndroid Build Coastguard Worker #define SET_SUBTRACT(a, b, n)\
310*8b26181fSAndroid Build Coastguard Worker {\
311*8b26181fSAndroid Build Coastguard Worker 	register bpf_u_int32 *_x = a, *_y = b;\
312*8b26181fSAndroid Build Coastguard Worker 	register u_int _n = n;\
313*8b26181fSAndroid Build Coastguard Worker 	do *_x++ &=~ *_y++; while (--_n != 0);\
314*8b26181fSAndroid Build Coastguard Worker }
315*8b26181fSAndroid Build Coastguard Worker 
316*8b26181fSAndroid Build Coastguard Worker /*
317*8b26181fSAndroid Build Coastguard Worker  * a := a union b
318*8b26181fSAndroid Build Coastguard Worker  * n must be guaranteed to be > 0
319*8b26181fSAndroid Build Coastguard Worker  */
320*8b26181fSAndroid Build Coastguard Worker #define SET_UNION(a, b, n)\
321*8b26181fSAndroid Build Coastguard Worker {\
322*8b26181fSAndroid Build Coastguard Worker 	register bpf_u_int32 *_x = a, *_y = b;\
323*8b26181fSAndroid Build Coastguard Worker 	register u_int _n = n;\
324*8b26181fSAndroid Build Coastguard Worker 	do *_x++ |= *_y++; while (--_n != 0);\
325*8b26181fSAndroid Build Coastguard Worker }
326*8b26181fSAndroid Build Coastguard Worker 
327*8b26181fSAndroid Build Coastguard Worker 	uset all_dom_sets;
328*8b26181fSAndroid Build Coastguard Worker 	uset all_closure_sets;
329*8b26181fSAndroid Build Coastguard Worker 	uset all_edge_sets;
330*8b26181fSAndroid Build Coastguard Worker 
331*8b26181fSAndroid Build Coastguard Worker #define MODULUS 213
332*8b26181fSAndroid Build Coastguard Worker 	struct valnode *hashtbl[MODULUS];
333*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 curval;
334*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 maxval;
335*8b26181fSAndroid Build Coastguard Worker 
336*8b26181fSAndroid Build Coastguard Worker 	struct vmapinfo *vmap;
337*8b26181fSAndroid Build Coastguard Worker 	struct valnode *vnode_base;
338*8b26181fSAndroid Build Coastguard Worker 	struct valnode *next_vnode;
339*8b26181fSAndroid Build Coastguard Worker } opt_state_t;
340*8b26181fSAndroid Build Coastguard Worker 
341*8b26181fSAndroid Build Coastguard Worker typedef struct {
342*8b26181fSAndroid Build Coastguard Worker 	/*
343*8b26181fSAndroid Build Coastguard Worker 	 * Place to longjmp to on an error.
344*8b26181fSAndroid Build Coastguard Worker 	 */
345*8b26181fSAndroid Build Coastguard Worker 	jmp_buf top_ctx;
346*8b26181fSAndroid Build Coastguard Worker 
347*8b26181fSAndroid Build Coastguard Worker 	/*
348*8b26181fSAndroid Build Coastguard Worker 	 * The buffer into which to put error message.
349*8b26181fSAndroid Build Coastguard Worker 	 */
350*8b26181fSAndroid Build Coastguard Worker 	char *errbuf;
351*8b26181fSAndroid Build Coastguard Worker 
352*8b26181fSAndroid Build Coastguard Worker 	/*
353*8b26181fSAndroid Build Coastguard Worker 	 * Some pointers used to convert the basic block form of the code,
354*8b26181fSAndroid Build Coastguard Worker 	 * into the array form that BPF requires.  'fstart' will point to
355*8b26181fSAndroid Build Coastguard Worker 	 * the malloc'd array while 'ftail' is used during the recursive
356*8b26181fSAndroid Build Coastguard Worker 	 * traversal.
357*8b26181fSAndroid Build Coastguard Worker 	 */
358*8b26181fSAndroid Build Coastguard Worker 	struct bpf_insn *fstart;
359*8b26181fSAndroid Build Coastguard Worker 	struct bpf_insn *ftail;
360*8b26181fSAndroid Build Coastguard Worker } conv_state_t;
361*8b26181fSAndroid Build Coastguard Worker 
362*8b26181fSAndroid Build Coastguard Worker static void opt_init(opt_state_t *, struct icode *);
363*8b26181fSAndroid Build Coastguard Worker static void opt_cleanup(opt_state_t *);
364*8b26181fSAndroid Build Coastguard Worker static void PCAP_NORETURN opt_error(opt_state_t *, const char *, ...)
365*8b26181fSAndroid Build Coastguard Worker     PCAP_PRINTFLIKE(2, 3);
366*8b26181fSAndroid Build Coastguard Worker 
367*8b26181fSAndroid Build Coastguard Worker static void intern_blocks(opt_state_t *, struct icode *);
368*8b26181fSAndroid Build Coastguard Worker 
369*8b26181fSAndroid Build Coastguard Worker static void find_inedges(opt_state_t *, struct block *);
370*8b26181fSAndroid Build Coastguard Worker #ifdef BDEBUG
371*8b26181fSAndroid Build Coastguard Worker static void opt_dump(opt_state_t *, struct icode *);
372*8b26181fSAndroid Build Coastguard Worker #endif
373*8b26181fSAndroid Build Coastguard Worker 
374*8b26181fSAndroid Build Coastguard Worker #ifndef MAX
375*8b26181fSAndroid Build Coastguard Worker #define MAX(a,b) ((a)>(b)?(a):(b))
376*8b26181fSAndroid Build Coastguard Worker #endif
377*8b26181fSAndroid Build Coastguard Worker 
378*8b26181fSAndroid Build Coastguard Worker static void
find_levels_r(opt_state_t * opt_state,struct icode * ic,struct block * b)379*8b26181fSAndroid Build Coastguard Worker find_levels_r(opt_state_t *opt_state, struct icode *ic, struct block *b)
380*8b26181fSAndroid Build Coastguard Worker {
381*8b26181fSAndroid Build Coastguard Worker 	int level;
382*8b26181fSAndroid Build Coastguard Worker 
383*8b26181fSAndroid Build Coastguard Worker 	if (isMarked(ic, b))
384*8b26181fSAndroid Build Coastguard Worker 		return;
385*8b26181fSAndroid Build Coastguard Worker 
386*8b26181fSAndroid Build Coastguard Worker 	Mark(ic, b);
387*8b26181fSAndroid Build Coastguard Worker 	b->link = 0;
388*8b26181fSAndroid Build Coastguard Worker 
389*8b26181fSAndroid Build Coastguard Worker 	if (JT(b)) {
390*8b26181fSAndroid Build Coastguard Worker 		find_levels_r(opt_state, ic, JT(b));
391*8b26181fSAndroid Build Coastguard Worker 		find_levels_r(opt_state, ic, JF(b));
392*8b26181fSAndroid Build Coastguard Worker 		level = MAX(JT(b)->level, JF(b)->level) + 1;
393*8b26181fSAndroid Build Coastguard Worker 	} else
394*8b26181fSAndroid Build Coastguard Worker 		level = 0;
395*8b26181fSAndroid Build Coastguard Worker 	b->level = level;
396*8b26181fSAndroid Build Coastguard Worker 	b->link = opt_state->levels[level];
397*8b26181fSAndroid Build Coastguard Worker 	opt_state->levels[level] = b;
398*8b26181fSAndroid Build Coastguard Worker }
399*8b26181fSAndroid Build Coastguard Worker 
400*8b26181fSAndroid Build Coastguard Worker /*
401*8b26181fSAndroid Build Coastguard Worker  * Level graph.  The levels go from 0 at the leaves to
402*8b26181fSAndroid Build Coastguard Worker  * N_LEVELS at the root.  The opt_state->levels[] array points to the
403*8b26181fSAndroid Build Coastguard Worker  * first node of the level list, whose elements are linked
404*8b26181fSAndroid Build Coastguard Worker  * with the 'link' field of the struct block.
405*8b26181fSAndroid Build Coastguard Worker  */
406*8b26181fSAndroid Build Coastguard Worker static void
find_levels(opt_state_t * opt_state,struct icode * ic)407*8b26181fSAndroid Build Coastguard Worker find_levels(opt_state_t *opt_state, struct icode *ic)
408*8b26181fSAndroid Build Coastguard Worker {
409*8b26181fSAndroid Build Coastguard Worker 	memset((char *)opt_state->levels, 0, opt_state->n_blocks * sizeof(*opt_state->levels));
410*8b26181fSAndroid Build Coastguard Worker 	unMarkAll(ic);
411*8b26181fSAndroid Build Coastguard Worker 	find_levels_r(opt_state, ic, ic->root);
412*8b26181fSAndroid Build Coastguard Worker }
413*8b26181fSAndroid Build Coastguard Worker 
414*8b26181fSAndroid Build Coastguard Worker /*
415*8b26181fSAndroid Build Coastguard Worker  * Find dominator relationships.
416*8b26181fSAndroid Build Coastguard Worker  * Assumes graph has been leveled.
417*8b26181fSAndroid Build Coastguard Worker  */
418*8b26181fSAndroid Build Coastguard Worker static void
find_dom(opt_state_t * opt_state,struct block * root)419*8b26181fSAndroid Build Coastguard Worker find_dom(opt_state_t *opt_state, struct block *root)
420*8b26181fSAndroid Build Coastguard Worker {
421*8b26181fSAndroid Build Coastguard Worker 	u_int i;
422*8b26181fSAndroid Build Coastguard Worker 	int level;
423*8b26181fSAndroid Build Coastguard Worker 	struct block *b;
424*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 *x;
425*8b26181fSAndroid Build Coastguard Worker 
426*8b26181fSAndroid Build Coastguard Worker 	/*
427*8b26181fSAndroid Build Coastguard Worker 	 * Initialize sets to contain all nodes.
428*8b26181fSAndroid Build Coastguard Worker 	 */
429*8b26181fSAndroid Build Coastguard Worker 	x = opt_state->all_dom_sets;
430*8b26181fSAndroid Build Coastguard Worker 	/*
431*8b26181fSAndroid Build Coastguard Worker 	 * In opt_init(), we've made sure the product doesn't overflow.
432*8b26181fSAndroid Build Coastguard Worker 	 */
433*8b26181fSAndroid Build Coastguard Worker 	i = opt_state->n_blocks * opt_state->nodewords;
434*8b26181fSAndroid Build Coastguard Worker 	while (i != 0) {
435*8b26181fSAndroid Build Coastguard Worker 		--i;
436*8b26181fSAndroid Build Coastguard Worker 		*x++ = 0xFFFFFFFFU;
437*8b26181fSAndroid Build Coastguard Worker 	}
438*8b26181fSAndroid Build Coastguard Worker 	/* Root starts off empty. */
439*8b26181fSAndroid Build Coastguard Worker 	for (i = opt_state->nodewords; i != 0;) {
440*8b26181fSAndroid Build Coastguard Worker 		--i;
441*8b26181fSAndroid Build Coastguard Worker 		root->dom[i] = 0;
442*8b26181fSAndroid Build Coastguard Worker 	}
443*8b26181fSAndroid Build Coastguard Worker 
444*8b26181fSAndroid Build Coastguard Worker 	/* root->level is the highest level no found. */
445*8b26181fSAndroid Build Coastguard Worker 	for (level = root->level; level >= 0; --level) {
446*8b26181fSAndroid Build Coastguard Worker 		for (b = opt_state->levels[level]; b; b = b->link) {
447*8b26181fSAndroid Build Coastguard Worker 			SET_INSERT(b->dom, b->id);
448*8b26181fSAndroid Build Coastguard Worker 			if (JT(b) == 0)
449*8b26181fSAndroid Build Coastguard Worker 				continue;
450*8b26181fSAndroid Build Coastguard Worker 			SET_INTERSECT(JT(b)->dom, b->dom, opt_state->nodewords);
451*8b26181fSAndroid Build Coastguard Worker 			SET_INTERSECT(JF(b)->dom, b->dom, opt_state->nodewords);
452*8b26181fSAndroid Build Coastguard Worker 		}
453*8b26181fSAndroid Build Coastguard Worker 	}
454*8b26181fSAndroid Build Coastguard Worker }
455*8b26181fSAndroid Build Coastguard Worker 
456*8b26181fSAndroid Build Coastguard Worker static void
propedom(opt_state_t * opt_state,struct edge * ep)457*8b26181fSAndroid Build Coastguard Worker propedom(opt_state_t *opt_state, struct edge *ep)
458*8b26181fSAndroid Build Coastguard Worker {
459*8b26181fSAndroid Build Coastguard Worker 	SET_INSERT(ep->edom, ep->id);
460*8b26181fSAndroid Build Coastguard Worker 	if (ep->succ) {
461*8b26181fSAndroid Build Coastguard Worker 		SET_INTERSECT(ep->succ->et.edom, ep->edom, opt_state->edgewords);
462*8b26181fSAndroid Build Coastguard Worker 		SET_INTERSECT(ep->succ->ef.edom, ep->edom, opt_state->edgewords);
463*8b26181fSAndroid Build Coastguard Worker 	}
464*8b26181fSAndroid Build Coastguard Worker }
465*8b26181fSAndroid Build Coastguard Worker 
466*8b26181fSAndroid Build Coastguard Worker /*
467*8b26181fSAndroid Build Coastguard Worker  * Compute edge dominators.
468*8b26181fSAndroid Build Coastguard Worker  * Assumes graph has been leveled and predecessors established.
469*8b26181fSAndroid Build Coastguard Worker  */
470*8b26181fSAndroid Build Coastguard Worker static void
find_edom(opt_state_t * opt_state,struct block * root)471*8b26181fSAndroid Build Coastguard Worker find_edom(opt_state_t *opt_state, struct block *root)
472*8b26181fSAndroid Build Coastguard Worker {
473*8b26181fSAndroid Build Coastguard Worker 	u_int i;
474*8b26181fSAndroid Build Coastguard Worker 	uset x;
475*8b26181fSAndroid Build Coastguard Worker 	int level;
476*8b26181fSAndroid Build Coastguard Worker 	struct block *b;
477*8b26181fSAndroid Build Coastguard Worker 
478*8b26181fSAndroid Build Coastguard Worker 	x = opt_state->all_edge_sets;
479*8b26181fSAndroid Build Coastguard Worker 	/*
480*8b26181fSAndroid Build Coastguard Worker 	 * In opt_init(), we've made sure the product doesn't overflow.
481*8b26181fSAndroid Build Coastguard Worker 	 */
482*8b26181fSAndroid Build Coastguard Worker 	for (i = opt_state->n_edges * opt_state->edgewords; i != 0; ) {
483*8b26181fSAndroid Build Coastguard Worker 		--i;
484*8b26181fSAndroid Build Coastguard Worker 		x[i] = 0xFFFFFFFFU;
485*8b26181fSAndroid Build Coastguard Worker 	}
486*8b26181fSAndroid Build Coastguard Worker 
487*8b26181fSAndroid Build Coastguard Worker 	/* root->level is the highest level no found. */
488*8b26181fSAndroid Build Coastguard Worker 	memset(root->et.edom, 0, opt_state->edgewords * sizeof(*(uset)0));
489*8b26181fSAndroid Build Coastguard Worker 	memset(root->ef.edom, 0, opt_state->edgewords * sizeof(*(uset)0));
490*8b26181fSAndroid Build Coastguard Worker 	for (level = root->level; level >= 0; --level) {
491*8b26181fSAndroid Build Coastguard Worker 		for (b = opt_state->levels[level]; b != 0; b = b->link) {
492*8b26181fSAndroid Build Coastguard Worker 			propedom(opt_state, &b->et);
493*8b26181fSAndroid Build Coastguard Worker 			propedom(opt_state, &b->ef);
494*8b26181fSAndroid Build Coastguard Worker 		}
495*8b26181fSAndroid Build Coastguard Worker 	}
496*8b26181fSAndroid Build Coastguard Worker }
497*8b26181fSAndroid Build Coastguard Worker 
498*8b26181fSAndroid Build Coastguard Worker /*
499*8b26181fSAndroid Build Coastguard Worker  * Find the backwards transitive closure of the flow graph.  These sets
500*8b26181fSAndroid Build Coastguard Worker  * are backwards in the sense that we find the set of nodes that reach
501*8b26181fSAndroid Build Coastguard Worker  * a given node, not the set of nodes that can be reached by a node.
502*8b26181fSAndroid Build Coastguard Worker  *
503*8b26181fSAndroid Build Coastguard Worker  * Assumes graph has been leveled.
504*8b26181fSAndroid Build Coastguard Worker  */
505*8b26181fSAndroid Build Coastguard Worker static void
find_closure(opt_state_t * opt_state,struct block * root)506*8b26181fSAndroid Build Coastguard Worker find_closure(opt_state_t *opt_state, struct block *root)
507*8b26181fSAndroid Build Coastguard Worker {
508*8b26181fSAndroid Build Coastguard Worker 	int level;
509*8b26181fSAndroid Build Coastguard Worker 	struct block *b;
510*8b26181fSAndroid Build Coastguard Worker 
511*8b26181fSAndroid Build Coastguard Worker 	/*
512*8b26181fSAndroid Build Coastguard Worker 	 * Initialize sets to contain no nodes.
513*8b26181fSAndroid Build Coastguard Worker 	 */
514*8b26181fSAndroid Build Coastguard Worker 	memset((char *)opt_state->all_closure_sets, 0,
515*8b26181fSAndroid Build Coastguard Worker 	      opt_state->n_blocks * opt_state->nodewords * sizeof(*opt_state->all_closure_sets));
516*8b26181fSAndroid Build Coastguard Worker 
517*8b26181fSAndroid Build Coastguard Worker 	/* root->level is the highest level no found. */
518*8b26181fSAndroid Build Coastguard Worker 	for (level = root->level; level >= 0; --level) {
519*8b26181fSAndroid Build Coastguard Worker 		for (b = opt_state->levels[level]; b; b = b->link) {
520*8b26181fSAndroid Build Coastguard Worker 			SET_INSERT(b->closure, b->id);
521*8b26181fSAndroid Build Coastguard Worker 			if (JT(b) == 0)
522*8b26181fSAndroid Build Coastguard Worker 				continue;
523*8b26181fSAndroid Build Coastguard Worker 			SET_UNION(JT(b)->closure, b->closure, opt_state->nodewords);
524*8b26181fSAndroid Build Coastguard Worker 			SET_UNION(JF(b)->closure, b->closure, opt_state->nodewords);
525*8b26181fSAndroid Build Coastguard Worker 		}
526*8b26181fSAndroid Build Coastguard Worker 	}
527*8b26181fSAndroid Build Coastguard Worker }
528*8b26181fSAndroid Build Coastguard Worker 
529*8b26181fSAndroid Build Coastguard Worker /*
530*8b26181fSAndroid Build Coastguard Worker  * Return the register number that is used by s.
531*8b26181fSAndroid Build Coastguard Worker  *
532*8b26181fSAndroid Build Coastguard Worker  * Returns ATOM_A if A is used, ATOM_X if X is used, AX_ATOM if both A and X
533*8b26181fSAndroid Build Coastguard Worker  * are used, the scratch memory location's number if a scratch memory
534*8b26181fSAndroid Build Coastguard Worker  * location is used (e.g., 0 for M[0]), or -1 if none of those are used.
535*8b26181fSAndroid Build Coastguard Worker  *
536*8b26181fSAndroid Build Coastguard Worker  * The implementation should probably change to an array access.
537*8b26181fSAndroid Build Coastguard Worker  */
538*8b26181fSAndroid Build Coastguard Worker static int
atomuse(struct stmt * s)539*8b26181fSAndroid Build Coastguard Worker atomuse(struct stmt *s)
540*8b26181fSAndroid Build Coastguard Worker {
541*8b26181fSAndroid Build Coastguard Worker 	register int c = s->code;
542*8b26181fSAndroid Build Coastguard Worker 
543*8b26181fSAndroid Build Coastguard Worker 	if (c == NOP)
544*8b26181fSAndroid Build Coastguard Worker 		return -1;
545*8b26181fSAndroid Build Coastguard Worker 
546*8b26181fSAndroid Build Coastguard Worker 	switch (BPF_CLASS(c)) {
547*8b26181fSAndroid Build Coastguard Worker 
548*8b26181fSAndroid Build Coastguard Worker 	case BPF_RET:
549*8b26181fSAndroid Build Coastguard Worker 		return (BPF_RVAL(c) == BPF_A) ? A_ATOM :
550*8b26181fSAndroid Build Coastguard Worker 			(BPF_RVAL(c) == BPF_X) ? X_ATOM : -1;
551*8b26181fSAndroid Build Coastguard Worker 
552*8b26181fSAndroid Build Coastguard Worker 	case BPF_LD:
553*8b26181fSAndroid Build Coastguard Worker 	case BPF_LDX:
554*8b26181fSAndroid Build Coastguard Worker 		/*
555*8b26181fSAndroid Build Coastguard Worker 		 * As there are fewer than 2^31 memory locations,
556*8b26181fSAndroid Build Coastguard Worker 		 * s->k should be convertible to int without problems.
557*8b26181fSAndroid Build Coastguard Worker 		 */
558*8b26181fSAndroid Build Coastguard Worker 		return (BPF_MODE(c) == BPF_IND) ? X_ATOM :
559*8b26181fSAndroid Build Coastguard Worker 			(BPF_MODE(c) == BPF_MEM) ? (int)s->k : -1;
560*8b26181fSAndroid Build Coastguard Worker 
561*8b26181fSAndroid Build Coastguard Worker 	case BPF_ST:
562*8b26181fSAndroid Build Coastguard Worker 		return A_ATOM;
563*8b26181fSAndroid Build Coastguard Worker 
564*8b26181fSAndroid Build Coastguard Worker 	case BPF_STX:
565*8b26181fSAndroid Build Coastguard Worker 		return X_ATOM;
566*8b26181fSAndroid Build Coastguard Worker 
567*8b26181fSAndroid Build Coastguard Worker 	case BPF_JMP:
568*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU:
569*8b26181fSAndroid Build Coastguard Worker 		if (BPF_SRC(c) == BPF_X)
570*8b26181fSAndroid Build Coastguard Worker 			return AX_ATOM;
571*8b26181fSAndroid Build Coastguard Worker 		return A_ATOM;
572*8b26181fSAndroid Build Coastguard Worker 
573*8b26181fSAndroid Build Coastguard Worker 	case BPF_MISC:
574*8b26181fSAndroid Build Coastguard Worker 		return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM;
575*8b26181fSAndroid Build Coastguard Worker 	}
576*8b26181fSAndroid Build Coastguard Worker 	abort();
577*8b26181fSAndroid Build Coastguard Worker 	/* NOTREACHED */
578*8b26181fSAndroid Build Coastguard Worker }
579*8b26181fSAndroid Build Coastguard Worker 
580*8b26181fSAndroid Build Coastguard Worker /*
581*8b26181fSAndroid Build Coastguard Worker  * Return the register number that is defined by 's'.  We assume that
582*8b26181fSAndroid Build Coastguard Worker  * a single stmt cannot define more than one register.  If no register
583*8b26181fSAndroid Build Coastguard Worker  * is defined, return -1.
584*8b26181fSAndroid Build Coastguard Worker  *
585*8b26181fSAndroid Build Coastguard Worker  * The implementation should probably change to an array access.
586*8b26181fSAndroid Build Coastguard Worker  */
587*8b26181fSAndroid Build Coastguard Worker static int
atomdef(struct stmt * s)588*8b26181fSAndroid Build Coastguard Worker atomdef(struct stmt *s)
589*8b26181fSAndroid Build Coastguard Worker {
590*8b26181fSAndroid Build Coastguard Worker 	if (s->code == NOP)
591*8b26181fSAndroid Build Coastguard Worker 		return -1;
592*8b26181fSAndroid Build Coastguard Worker 
593*8b26181fSAndroid Build Coastguard Worker 	switch (BPF_CLASS(s->code)) {
594*8b26181fSAndroid Build Coastguard Worker 
595*8b26181fSAndroid Build Coastguard Worker 	case BPF_LD:
596*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU:
597*8b26181fSAndroid Build Coastguard Worker 		return A_ATOM;
598*8b26181fSAndroid Build Coastguard Worker 
599*8b26181fSAndroid Build Coastguard Worker 	case BPF_LDX:
600*8b26181fSAndroid Build Coastguard Worker 		return X_ATOM;
601*8b26181fSAndroid Build Coastguard Worker 
602*8b26181fSAndroid Build Coastguard Worker 	case BPF_ST:
603*8b26181fSAndroid Build Coastguard Worker 	case BPF_STX:
604*8b26181fSAndroid Build Coastguard Worker 		return s->k;
605*8b26181fSAndroid Build Coastguard Worker 
606*8b26181fSAndroid Build Coastguard Worker 	case BPF_MISC:
607*8b26181fSAndroid Build Coastguard Worker 		return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM;
608*8b26181fSAndroid Build Coastguard Worker 	}
609*8b26181fSAndroid Build Coastguard Worker 	return -1;
610*8b26181fSAndroid Build Coastguard Worker }
611*8b26181fSAndroid Build Coastguard Worker 
612*8b26181fSAndroid Build Coastguard Worker /*
613*8b26181fSAndroid Build Coastguard Worker  * Compute the sets of registers used, defined, and killed by 'b'.
614*8b26181fSAndroid Build Coastguard Worker  *
615*8b26181fSAndroid Build Coastguard Worker  * "Used" means that a statement in 'b' uses the register before any
616*8b26181fSAndroid Build Coastguard Worker  * statement in 'b' defines it, i.e. it uses the value left in
617*8b26181fSAndroid Build Coastguard Worker  * that register by a predecessor block of this block.
618*8b26181fSAndroid Build Coastguard Worker  * "Defined" means that a statement in 'b' defines it.
619*8b26181fSAndroid Build Coastguard Worker  * "Killed" means that a statement in 'b' defines it before any
620*8b26181fSAndroid Build Coastguard Worker  * statement in 'b' uses it, i.e. it kills the value left in that
621*8b26181fSAndroid Build Coastguard Worker  * register by a predecessor block of this block.
622*8b26181fSAndroid Build Coastguard Worker  */
623*8b26181fSAndroid Build Coastguard Worker static void
compute_local_ud(struct block * b)624*8b26181fSAndroid Build Coastguard Worker compute_local_ud(struct block *b)
625*8b26181fSAndroid Build Coastguard Worker {
626*8b26181fSAndroid Build Coastguard Worker 	struct slist *s;
627*8b26181fSAndroid Build Coastguard Worker 	atomset def = 0, use = 0, killed = 0;
628*8b26181fSAndroid Build Coastguard Worker 	int atom;
629*8b26181fSAndroid Build Coastguard Worker 
630*8b26181fSAndroid Build Coastguard Worker 	for (s = b->stmts; s; s = s->next) {
631*8b26181fSAndroid Build Coastguard Worker 		if (s->s.code == NOP)
632*8b26181fSAndroid Build Coastguard Worker 			continue;
633*8b26181fSAndroid Build Coastguard Worker 		atom = atomuse(&s->s);
634*8b26181fSAndroid Build Coastguard Worker 		if (atom >= 0) {
635*8b26181fSAndroid Build Coastguard Worker 			if (atom == AX_ATOM) {
636*8b26181fSAndroid Build Coastguard Worker 				if (!ATOMELEM(def, X_ATOM))
637*8b26181fSAndroid Build Coastguard Worker 					use |= ATOMMASK(X_ATOM);
638*8b26181fSAndroid Build Coastguard Worker 				if (!ATOMELEM(def, A_ATOM))
639*8b26181fSAndroid Build Coastguard Worker 					use |= ATOMMASK(A_ATOM);
640*8b26181fSAndroid Build Coastguard Worker 			}
641*8b26181fSAndroid Build Coastguard Worker 			else if (atom < N_ATOMS) {
642*8b26181fSAndroid Build Coastguard Worker 				if (!ATOMELEM(def, atom))
643*8b26181fSAndroid Build Coastguard Worker 					use |= ATOMMASK(atom);
644*8b26181fSAndroid Build Coastguard Worker 			}
645*8b26181fSAndroid Build Coastguard Worker 			else
646*8b26181fSAndroid Build Coastguard Worker 				abort();
647*8b26181fSAndroid Build Coastguard Worker 		}
648*8b26181fSAndroid Build Coastguard Worker 		atom = atomdef(&s->s);
649*8b26181fSAndroid Build Coastguard Worker 		if (atom >= 0) {
650*8b26181fSAndroid Build Coastguard Worker 			if (!ATOMELEM(use, atom))
651*8b26181fSAndroid Build Coastguard Worker 				killed |= ATOMMASK(atom);
652*8b26181fSAndroid Build Coastguard Worker 			def |= ATOMMASK(atom);
653*8b26181fSAndroid Build Coastguard Worker 		}
654*8b26181fSAndroid Build Coastguard Worker 	}
655*8b26181fSAndroid Build Coastguard Worker 	if (BPF_CLASS(b->s.code) == BPF_JMP) {
656*8b26181fSAndroid Build Coastguard Worker 		/*
657*8b26181fSAndroid Build Coastguard Worker 		 * XXX - what about RET?
658*8b26181fSAndroid Build Coastguard Worker 		 */
659*8b26181fSAndroid Build Coastguard Worker 		atom = atomuse(&b->s);
660*8b26181fSAndroid Build Coastguard Worker 		if (atom >= 0) {
661*8b26181fSAndroid Build Coastguard Worker 			if (atom == AX_ATOM) {
662*8b26181fSAndroid Build Coastguard Worker 				if (!ATOMELEM(def, X_ATOM))
663*8b26181fSAndroid Build Coastguard Worker 					use |= ATOMMASK(X_ATOM);
664*8b26181fSAndroid Build Coastguard Worker 				if (!ATOMELEM(def, A_ATOM))
665*8b26181fSAndroid Build Coastguard Worker 					use |= ATOMMASK(A_ATOM);
666*8b26181fSAndroid Build Coastguard Worker 			}
667*8b26181fSAndroid Build Coastguard Worker 			else if (atom < N_ATOMS) {
668*8b26181fSAndroid Build Coastguard Worker 				if (!ATOMELEM(def, atom))
669*8b26181fSAndroid Build Coastguard Worker 					use |= ATOMMASK(atom);
670*8b26181fSAndroid Build Coastguard Worker 			}
671*8b26181fSAndroid Build Coastguard Worker 			else
672*8b26181fSAndroid Build Coastguard Worker 				abort();
673*8b26181fSAndroid Build Coastguard Worker 		}
674*8b26181fSAndroid Build Coastguard Worker 	}
675*8b26181fSAndroid Build Coastguard Worker 
676*8b26181fSAndroid Build Coastguard Worker 	b->def = def;
677*8b26181fSAndroid Build Coastguard Worker 	b->kill = killed;
678*8b26181fSAndroid Build Coastguard Worker 	b->in_use = use;
679*8b26181fSAndroid Build Coastguard Worker }
680*8b26181fSAndroid Build Coastguard Worker 
681*8b26181fSAndroid Build Coastguard Worker /*
682*8b26181fSAndroid Build Coastguard Worker  * Assume graph is already leveled.
683*8b26181fSAndroid Build Coastguard Worker  */
684*8b26181fSAndroid Build Coastguard Worker static void
find_ud(opt_state_t * opt_state,struct block * root)685*8b26181fSAndroid Build Coastguard Worker find_ud(opt_state_t *opt_state, struct block *root)
686*8b26181fSAndroid Build Coastguard Worker {
687*8b26181fSAndroid Build Coastguard Worker 	int i, maxlevel;
688*8b26181fSAndroid Build Coastguard Worker 	struct block *p;
689*8b26181fSAndroid Build Coastguard Worker 
690*8b26181fSAndroid Build Coastguard Worker 	/*
691*8b26181fSAndroid Build Coastguard Worker 	 * root->level is the highest level no found;
692*8b26181fSAndroid Build Coastguard Worker 	 * count down from there.
693*8b26181fSAndroid Build Coastguard Worker 	 */
694*8b26181fSAndroid Build Coastguard Worker 	maxlevel = root->level;
695*8b26181fSAndroid Build Coastguard Worker 	for (i = maxlevel; i >= 0; --i)
696*8b26181fSAndroid Build Coastguard Worker 		for (p = opt_state->levels[i]; p; p = p->link) {
697*8b26181fSAndroid Build Coastguard Worker 			compute_local_ud(p);
698*8b26181fSAndroid Build Coastguard Worker 			p->out_use = 0;
699*8b26181fSAndroid Build Coastguard Worker 		}
700*8b26181fSAndroid Build Coastguard Worker 
701*8b26181fSAndroid Build Coastguard Worker 	for (i = 1; i <= maxlevel; ++i) {
702*8b26181fSAndroid Build Coastguard Worker 		for (p = opt_state->levels[i]; p; p = p->link) {
703*8b26181fSAndroid Build Coastguard Worker 			p->out_use |= JT(p)->in_use | JF(p)->in_use;
704*8b26181fSAndroid Build Coastguard Worker 			p->in_use |= p->out_use &~ p->kill;
705*8b26181fSAndroid Build Coastguard Worker 		}
706*8b26181fSAndroid Build Coastguard Worker 	}
707*8b26181fSAndroid Build Coastguard Worker }
708*8b26181fSAndroid Build Coastguard Worker static void
init_val(opt_state_t * opt_state)709*8b26181fSAndroid Build Coastguard Worker init_val(opt_state_t *opt_state)
710*8b26181fSAndroid Build Coastguard Worker {
711*8b26181fSAndroid Build Coastguard Worker 	opt_state->curval = 0;
712*8b26181fSAndroid Build Coastguard Worker 	opt_state->next_vnode = opt_state->vnode_base;
713*8b26181fSAndroid Build Coastguard Worker 	memset((char *)opt_state->vmap, 0, opt_state->maxval * sizeof(*opt_state->vmap));
714*8b26181fSAndroid Build Coastguard Worker 	memset((char *)opt_state->hashtbl, 0, sizeof opt_state->hashtbl);
715*8b26181fSAndroid Build Coastguard Worker }
716*8b26181fSAndroid Build Coastguard Worker 
717*8b26181fSAndroid Build Coastguard Worker /*
718*8b26181fSAndroid Build Coastguard Worker  * Because we really don't have an IR, this stuff is a little messy.
719*8b26181fSAndroid Build Coastguard Worker  *
720*8b26181fSAndroid Build Coastguard Worker  * This routine looks in the table of existing value number for a value
721*8b26181fSAndroid Build Coastguard Worker  * with generated from an operation with the specified opcode and
722*8b26181fSAndroid Build Coastguard Worker  * the specified values.  If it finds it, it returns its value number,
723*8b26181fSAndroid Build Coastguard Worker  * otherwise it makes a new entry in the table and returns the
724*8b26181fSAndroid Build Coastguard Worker  * value number of that entry.
725*8b26181fSAndroid Build Coastguard Worker  */
726*8b26181fSAndroid Build Coastguard Worker static bpf_u_int32
F(opt_state_t * opt_state,int code,bpf_u_int32 v0,bpf_u_int32 v1)727*8b26181fSAndroid Build Coastguard Worker F(opt_state_t *opt_state, int code, bpf_u_int32 v0, bpf_u_int32 v1)
728*8b26181fSAndroid Build Coastguard Worker {
729*8b26181fSAndroid Build Coastguard Worker 	u_int hash;
730*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 val;
731*8b26181fSAndroid Build Coastguard Worker 	struct valnode *p;
732*8b26181fSAndroid Build Coastguard Worker 
733*8b26181fSAndroid Build Coastguard Worker 	hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8);
734*8b26181fSAndroid Build Coastguard Worker 	hash %= MODULUS;
735*8b26181fSAndroid Build Coastguard Worker 
736*8b26181fSAndroid Build Coastguard Worker 	for (p = opt_state->hashtbl[hash]; p; p = p->next)
737*8b26181fSAndroid Build Coastguard Worker 		if (p->code == code && p->v0 == v0 && p->v1 == v1)
738*8b26181fSAndroid Build Coastguard Worker 			return p->val;
739*8b26181fSAndroid Build Coastguard Worker 
740*8b26181fSAndroid Build Coastguard Worker 	/*
741*8b26181fSAndroid Build Coastguard Worker 	 * Not found.  Allocate a new value, and assign it a new
742*8b26181fSAndroid Build Coastguard Worker 	 * value number.
743*8b26181fSAndroid Build Coastguard Worker 	 *
744*8b26181fSAndroid Build Coastguard Worker 	 * opt_state->curval starts out as 0, which means VAL_UNKNOWN; we
745*8b26181fSAndroid Build Coastguard Worker 	 * increment it before using it as the new value number, which
746*8b26181fSAndroid Build Coastguard Worker 	 * means we never assign VAL_UNKNOWN.
747*8b26181fSAndroid Build Coastguard Worker 	 *
748*8b26181fSAndroid Build Coastguard Worker 	 * XXX - unless we overflow, but we probably won't have 2^32-1
749*8b26181fSAndroid Build Coastguard Worker 	 * values; we treat 32 bits as effectively infinite.
750*8b26181fSAndroid Build Coastguard Worker 	 */
751*8b26181fSAndroid Build Coastguard Worker 	val = ++opt_state->curval;
752*8b26181fSAndroid Build Coastguard Worker 	if (BPF_MODE(code) == BPF_IMM &&
753*8b26181fSAndroid Build Coastguard Worker 	    (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) {
754*8b26181fSAndroid Build Coastguard Worker 		opt_state->vmap[val].const_val = v0;
755*8b26181fSAndroid Build Coastguard Worker 		opt_state->vmap[val].is_const = 1;
756*8b26181fSAndroid Build Coastguard Worker 	}
757*8b26181fSAndroid Build Coastguard Worker 	p = opt_state->next_vnode++;
758*8b26181fSAndroid Build Coastguard Worker 	p->val = val;
759*8b26181fSAndroid Build Coastguard Worker 	p->code = code;
760*8b26181fSAndroid Build Coastguard Worker 	p->v0 = v0;
761*8b26181fSAndroid Build Coastguard Worker 	p->v1 = v1;
762*8b26181fSAndroid Build Coastguard Worker 	p->next = opt_state->hashtbl[hash];
763*8b26181fSAndroid Build Coastguard Worker 	opt_state->hashtbl[hash] = p;
764*8b26181fSAndroid Build Coastguard Worker 
765*8b26181fSAndroid Build Coastguard Worker 	return val;
766*8b26181fSAndroid Build Coastguard Worker }
767*8b26181fSAndroid Build Coastguard Worker 
768*8b26181fSAndroid Build Coastguard Worker static inline void
vstore(struct stmt * s,bpf_u_int32 * valp,bpf_u_int32 newval,int alter)769*8b26181fSAndroid Build Coastguard Worker vstore(struct stmt *s, bpf_u_int32 *valp, bpf_u_int32 newval, int alter)
770*8b26181fSAndroid Build Coastguard Worker {
771*8b26181fSAndroid Build Coastguard Worker 	if (alter && newval != VAL_UNKNOWN && *valp == newval)
772*8b26181fSAndroid Build Coastguard Worker 		s->code = NOP;
773*8b26181fSAndroid Build Coastguard Worker 	else
774*8b26181fSAndroid Build Coastguard Worker 		*valp = newval;
775*8b26181fSAndroid Build Coastguard Worker }
776*8b26181fSAndroid Build Coastguard Worker 
777*8b26181fSAndroid Build Coastguard Worker /*
778*8b26181fSAndroid Build Coastguard Worker  * Do constant-folding on binary operators.
779*8b26181fSAndroid Build Coastguard Worker  * (Unary operators are handled elsewhere.)
780*8b26181fSAndroid Build Coastguard Worker  */
781*8b26181fSAndroid Build Coastguard Worker static void
fold_op(opt_state_t * opt_state,struct stmt * s,bpf_u_int32 v0,bpf_u_int32 v1)782*8b26181fSAndroid Build Coastguard Worker fold_op(opt_state_t *opt_state, struct stmt *s, bpf_u_int32 v0, bpf_u_int32 v1)
783*8b26181fSAndroid Build Coastguard Worker {
784*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 a, b;
785*8b26181fSAndroid Build Coastguard Worker 
786*8b26181fSAndroid Build Coastguard Worker 	a = opt_state->vmap[v0].const_val;
787*8b26181fSAndroid Build Coastguard Worker 	b = opt_state->vmap[v1].const_val;
788*8b26181fSAndroid Build Coastguard Worker 
789*8b26181fSAndroid Build Coastguard Worker 	switch (BPF_OP(s->code)) {
790*8b26181fSAndroid Build Coastguard Worker 	case BPF_ADD:
791*8b26181fSAndroid Build Coastguard Worker 		a += b;
792*8b26181fSAndroid Build Coastguard Worker 		break;
793*8b26181fSAndroid Build Coastguard Worker 
794*8b26181fSAndroid Build Coastguard Worker 	case BPF_SUB:
795*8b26181fSAndroid Build Coastguard Worker 		a -= b;
796*8b26181fSAndroid Build Coastguard Worker 		break;
797*8b26181fSAndroid Build Coastguard Worker 
798*8b26181fSAndroid Build Coastguard Worker 	case BPF_MUL:
799*8b26181fSAndroid Build Coastguard Worker 		a *= b;
800*8b26181fSAndroid Build Coastguard Worker 		break;
801*8b26181fSAndroid Build Coastguard Worker 
802*8b26181fSAndroid Build Coastguard Worker 	case BPF_DIV:
803*8b26181fSAndroid Build Coastguard Worker 		if (b == 0)
804*8b26181fSAndroid Build Coastguard Worker 			opt_error(opt_state, "division by zero");
805*8b26181fSAndroid Build Coastguard Worker 		a /= b;
806*8b26181fSAndroid Build Coastguard Worker 		break;
807*8b26181fSAndroid Build Coastguard Worker 
808*8b26181fSAndroid Build Coastguard Worker 	case BPF_MOD:
809*8b26181fSAndroid Build Coastguard Worker 		if (b == 0)
810*8b26181fSAndroid Build Coastguard Worker 			opt_error(opt_state, "modulus by zero");
811*8b26181fSAndroid Build Coastguard Worker 		a %= b;
812*8b26181fSAndroid Build Coastguard Worker 		break;
813*8b26181fSAndroid Build Coastguard Worker 
814*8b26181fSAndroid Build Coastguard Worker 	case BPF_AND:
815*8b26181fSAndroid Build Coastguard Worker 		a &= b;
816*8b26181fSAndroid Build Coastguard Worker 		break;
817*8b26181fSAndroid Build Coastguard Worker 
818*8b26181fSAndroid Build Coastguard Worker 	case BPF_OR:
819*8b26181fSAndroid Build Coastguard Worker 		a |= b;
820*8b26181fSAndroid Build Coastguard Worker 		break;
821*8b26181fSAndroid Build Coastguard Worker 
822*8b26181fSAndroid Build Coastguard Worker 	case BPF_XOR:
823*8b26181fSAndroid Build Coastguard Worker 		a ^= b;
824*8b26181fSAndroid Build Coastguard Worker 		break;
825*8b26181fSAndroid Build Coastguard Worker 
826*8b26181fSAndroid Build Coastguard Worker 	case BPF_LSH:
827*8b26181fSAndroid Build Coastguard Worker 		/*
828*8b26181fSAndroid Build Coastguard Worker 		 * A left shift of more than the width of the type
829*8b26181fSAndroid Build Coastguard Worker 		 * is undefined in C; we'll just treat it as shifting
830*8b26181fSAndroid Build Coastguard Worker 		 * all the bits out.
831*8b26181fSAndroid Build Coastguard Worker 		 *
832*8b26181fSAndroid Build Coastguard Worker 		 * XXX - the BPF interpreter doesn't check for this,
833*8b26181fSAndroid Build Coastguard Worker 		 * so its behavior is dependent on the behavior of
834*8b26181fSAndroid Build Coastguard Worker 		 * the processor on which it's running.  There are
835*8b26181fSAndroid Build Coastguard Worker 		 * processors on which it shifts all the bits out
836*8b26181fSAndroid Build Coastguard Worker 		 * and processors on which it does no shift.
837*8b26181fSAndroid Build Coastguard Worker 		 */
838*8b26181fSAndroid Build Coastguard Worker 		if (b < 32)
839*8b26181fSAndroid Build Coastguard Worker 			a <<= b;
840*8b26181fSAndroid Build Coastguard Worker 		else
841*8b26181fSAndroid Build Coastguard Worker 			a = 0;
842*8b26181fSAndroid Build Coastguard Worker 		break;
843*8b26181fSAndroid Build Coastguard Worker 
844*8b26181fSAndroid Build Coastguard Worker 	case BPF_RSH:
845*8b26181fSAndroid Build Coastguard Worker 		/*
846*8b26181fSAndroid Build Coastguard Worker 		 * A right shift of more than the width of the type
847*8b26181fSAndroid Build Coastguard Worker 		 * is undefined in C; we'll just treat it as shifting
848*8b26181fSAndroid Build Coastguard Worker 		 * all the bits out.
849*8b26181fSAndroid Build Coastguard Worker 		 *
850*8b26181fSAndroid Build Coastguard Worker 		 * XXX - the BPF interpreter doesn't check for this,
851*8b26181fSAndroid Build Coastguard Worker 		 * so its behavior is dependent on the behavior of
852*8b26181fSAndroid Build Coastguard Worker 		 * the processor on which it's running.  There are
853*8b26181fSAndroid Build Coastguard Worker 		 * processors on which it shifts all the bits out
854*8b26181fSAndroid Build Coastguard Worker 		 * and processors on which it does no shift.
855*8b26181fSAndroid Build Coastguard Worker 		 */
856*8b26181fSAndroid Build Coastguard Worker 		if (b < 32)
857*8b26181fSAndroid Build Coastguard Worker 			a >>= b;
858*8b26181fSAndroid Build Coastguard Worker 		else
859*8b26181fSAndroid Build Coastguard Worker 			a = 0;
860*8b26181fSAndroid Build Coastguard Worker 		break;
861*8b26181fSAndroid Build Coastguard Worker 
862*8b26181fSAndroid Build Coastguard Worker 	default:
863*8b26181fSAndroid Build Coastguard Worker 		abort();
864*8b26181fSAndroid Build Coastguard Worker 	}
865*8b26181fSAndroid Build Coastguard Worker 	s->k = a;
866*8b26181fSAndroid Build Coastguard Worker 	s->code = BPF_LD|BPF_IMM;
867*8b26181fSAndroid Build Coastguard Worker 	/*
868*8b26181fSAndroid Build Coastguard Worker 	 * XXX - optimizer loop detection.
869*8b26181fSAndroid Build Coastguard Worker 	 */
870*8b26181fSAndroid Build Coastguard Worker 	opt_state->non_branch_movement_performed = 1;
871*8b26181fSAndroid Build Coastguard Worker 	opt_state->done = 0;
872*8b26181fSAndroid Build Coastguard Worker }
873*8b26181fSAndroid Build Coastguard Worker 
874*8b26181fSAndroid Build Coastguard Worker static inline struct slist *
this_op(struct slist * s)875*8b26181fSAndroid Build Coastguard Worker this_op(struct slist *s)
876*8b26181fSAndroid Build Coastguard Worker {
877*8b26181fSAndroid Build Coastguard Worker 	while (s != 0 && s->s.code == NOP)
878*8b26181fSAndroid Build Coastguard Worker 		s = s->next;
879*8b26181fSAndroid Build Coastguard Worker 	return s;
880*8b26181fSAndroid Build Coastguard Worker }
881*8b26181fSAndroid Build Coastguard Worker 
882*8b26181fSAndroid Build Coastguard Worker static void
opt_not(struct block * b)883*8b26181fSAndroid Build Coastguard Worker opt_not(struct block *b)
884*8b26181fSAndroid Build Coastguard Worker {
885*8b26181fSAndroid Build Coastguard Worker 	struct block *tmp = JT(b);
886*8b26181fSAndroid Build Coastguard Worker 
887*8b26181fSAndroid Build Coastguard Worker 	JT(b) = JF(b);
888*8b26181fSAndroid Build Coastguard Worker 	JF(b) = tmp;
889*8b26181fSAndroid Build Coastguard Worker }
890*8b26181fSAndroid Build Coastguard Worker 
891*8b26181fSAndroid Build Coastguard Worker static void
opt_peep(opt_state_t * opt_state,struct block * b)892*8b26181fSAndroid Build Coastguard Worker opt_peep(opt_state_t *opt_state, struct block *b)
893*8b26181fSAndroid Build Coastguard Worker {
894*8b26181fSAndroid Build Coastguard Worker 	struct slist *s;
895*8b26181fSAndroid Build Coastguard Worker 	struct slist *next, *last;
896*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 val;
897*8b26181fSAndroid Build Coastguard Worker 
898*8b26181fSAndroid Build Coastguard Worker 	s = b->stmts;
899*8b26181fSAndroid Build Coastguard Worker 	if (s == 0)
900*8b26181fSAndroid Build Coastguard Worker 		return;
901*8b26181fSAndroid Build Coastguard Worker 
902*8b26181fSAndroid Build Coastguard Worker 	last = s;
903*8b26181fSAndroid Build Coastguard Worker 	for (/*empty*/; /*empty*/; s = next) {
904*8b26181fSAndroid Build Coastguard Worker 		/*
905*8b26181fSAndroid Build Coastguard Worker 		 * Skip over nops.
906*8b26181fSAndroid Build Coastguard Worker 		 */
907*8b26181fSAndroid Build Coastguard Worker 		s = this_op(s);
908*8b26181fSAndroid Build Coastguard Worker 		if (s == 0)
909*8b26181fSAndroid Build Coastguard Worker 			break;	/* nothing left in the block */
910*8b26181fSAndroid Build Coastguard Worker 
911*8b26181fSAndroid Build Coastguard Worker 		/*
912*8b26181fSAndroid Build Coastguard Worker 		 * Find the next real instruction after that one
913*8b26181fSAndroid Build Coastguard Worker 		 * (skipping nops).
914*8b26181fSAndroid Build Coastguard Worker 		 */
915*8b26181fSAndroid Build Coastguard Worker 		next = this_op(s->next);
916*8b26181fSAndroid Build Coastguard Worker 		if (next == 0)
917*8b26181fSAndroid Build Coastguard Worker 			break;	/* no next instruction */
918*8b26181fSAndroid Build Coastguard Worker 		last = next;
919*8b26181fSAndroid Build Coastguard Worker 
920*8b26181fSAndroid Build Coastguard Worker 		/*
921*8b26181fSAndroid Build Coastguard Worker 		 * st  M[k]	-->	st  M[k]
922*8b26181fSAndroid Build Coastguard Worker 		 * ldx M[k]		tax
923*8b26181fSAndroid Build Coastguard Worker 		 */
924*8b26181fSAndroid Build Coastguard Worker 		if (s->s.code == BPF_ST &&
925*8b26181fSAndroid Build Coastguard Worker 		    next->s.code == (BPF_LDX|BPF_MEM) &&
926*8b26181fSAndroid Build Coastguard Worker 		    s->s.k == next->s.k) {
927*8b26181fSAndroid Build Coastguard Worker 			/*
928*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
929*8b26181fSAndroid Build Coastguard Worker 			 */
930*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
931*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
932*8b26181fSAndroid Build Coastguard Worker 			next->s.code = BPF_MISC|BPF_TAX;
933*8b26181fSAndroid Build Coastguard Worker 		}
934*8b26181fSAndroid Build Coastguard Worker 		/*
935*8b26181fSAndroid Build Coastguard Worker 		 * ld  #k	-->	ldx  #k
936*8b26181fSAndroid Build Coastguard Worker 		 * tax			txa
937*8b26181fSAndroid Build Coastguard Worker 		 */
938*8b26181fSAndroid Build Coastguard Worker 		if (s->s.code == (BPF_LD|BPF_IMM) &&
939*8b26181fSAndroid Build Coastguard Worker 		    next->s.code == (BPF_MISC|BPF_TAX)) {
940*8b26181fSAndroid Build Coastguard Worker 			s->s.code = BPF_LDX|BPF_IMM;
941*8b26181fSAndroid Build Coastguard Worker 			next->s.code = BPF_MISC|BPF_TXA;
942*8b26181fSAndroid Build Coastguard Worker 			/*
943*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
944*8b26181fSAndroid Build Coastguard Worker 			 */
945*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
946*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
947*8b26181fSAndroid Build Coastguard Worker 		}
948*8b26181fSAndroid Build Coastguard Worker 		/*
949*8b26181fSAndroid Build Coastguard Worker 		 * This is an ugly special case, but it happens
950*8b26181fSAndroid Build Coastguard Worker 		 * when you say tcp[k] or udp[k] where k is a constant.
951*8b26181fSAndroid Build Coastguard Worker 		 */
952*8b26181fSAndroid Build Coastguard Worker 		if (s->s.code == (BPF_LD|BPF_IMM)) {
953*8b26181fSAndroid Build Coastguard Worker 			struct slist *add, *tax, *ild;
954*8b26181fSAndroid Build Coastguard Worker 
955*8b26181fSAndroid Build Coastguard Worker 			/*
956*8b26181fSAndroid Build Coastguard Worker 			 * Check that X isn't used on exit from this
957*8b26181fSAndroid Build Coastguard Worker 			 * block (which the optimizer might cause).
958*8b26181fSAndroid Build Coastguard Worker 			 * We know the code generator won't generate
959*8b26181fSAndroid Build Coastguard Worker 			 * any local dependencies.
960*8b26181fSAndroid Build Coastguard Worker 			 */
961*8b26181fSAndroid Build Coastguard Worker 			if (ATOMELEM(b->out_use, X_ATOM))
962*8b26181fSAndroid Build Coastguard Worker 				continue;
963*8b26181fSAndroid Build Coastguard Worker 
964*8b26181fSAndroid Build Coastguard Worker 			/*
965*8b26181fSAndroid Build Coastguard Worker 			 * Check that the instruction following the ldi
966*8b26181fSAndroid Build Coastguard Worker 			 * is an addx, or it's an ldxms with an addx
967*8b26181fSAndroid Build Coastguard Worker 			 * following it (with 0 or more nops between the
968*8b26181fSAndroid Build Coastguard Worker 			 * ldxms and addx).
969*8b26181fSAndroid Build Coastguard Worker 			 */
970*8b26181fSAndroid Build Coastguard Worker 			if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B))
971*8b26181fSAndroid Build Coastguard Worker 				add = next;
972*8b26181fSAndroid Build Coastguard Worker 			else
973*8b26181fSAndroid Build Coastguard Worker 				add = this_op(next->next);
974*8b26181fSAndroid Build Coastguard Worker 			if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X))
975*8b26181fSAndroid Build Coastguard Worker 				continue;
976*8b26181fSAndroid Build Coastguard Worker 
977*8b26181fSAndroid Build Coastguard Worker 			/*
978*8b26181fSAndroid Build Coastguard Worker 			 * Check that a tax follows that (with 0 or more
979*8b26181fSAndroid Build Coastguard Worker 			 * nops between them).
980*8b26181fSAndroid Build Coastguard Worker 			 */
981*8b26181fSAndroid Build Coastguard Worker 			tax = this_op(add->next);
982*8b26181fSAndroid Build Coastguard Worker 			if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX))
983*8b26181fSAndroid Build Coastguard Worker 				continue;
984*8b26181fSAndroid Build Coastguard Worker 
985*8b26181fSAndroid Build Coastguard Worker 			/*
986*8b26181fSAndroid Build Coastguard Worker 			 * Check that an ild follows that (with 0 or more
987*8b26181fSAndroid Build Coastguard Worker 			 * nops between them).
988*8b26181fSAndroid Build Coastguard Worker 			 */
989*8b26181fSAndroid Build Coastguard Worker 			ild = this_op(tax->next);
990*8b26181fSAndroid Build Coastguard Worker 			if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD ||
991*8b26181fSAndroid Build Coastguard Worker 			    BPF_MODE(ild->s.code) != BPF_IND)
992*8b26181fSAndroid Build Coastguard Worker 				continue;
993*8b26181fSAndroid Build Coastguard Worker 			/*
994*8b26181fSAndroid Build Coastguard Worker 			 * We want to turn this sequence:
995*8b26181fSAndroid Build Coastguard Worker 			 *
996*8b26181fSAndroid Build Coastguard Worker 			 * (004) ldi     #0x2		{s}
997*8b26181fSAndroid Build Coastguard Worker 			 * (005) ldxms   [14]		{next}  -- optional
998*8b26181fSAndroid Build Coastguard Worker 			 * (006) addx			{add}
999*8b26181fSAndroid Build Coastguard Worker 			 * (007) tax			{tax}
1000*8b26181fSAndroid Build Coastguard Worker 			 * (008) ild     [x+0]		{ild}
1001*8b26181fSAndroid Build Coastguard Worker 			 *
1002*8b26181fSAndroid Build Coastguard Worker 			 * into this sequence:
1003*8b26181fSAndroid Build Coastguard Worker 			 *
1004*8b26181fSAndroid Build Coastguard Worker 			 * (004) nop
1005*8b26181fSAndroid Build Coastguard Worker 			 * (005) ldxms   [14]
1006*8b26181fSAndroid Build Coastguard Worker 			 * (006) nop
1007*8b26181fSAndroid Build Coastguard Worker 			 * (007) nop
1008*8b26181fSAndroid Build Coastguard Worker 			 * (008) ild     [x+2]
1009*8b26181fSAndroid Build Coastguard Worker 			 *
1010*8b26181fSAndroid Build Coastguard Worker 			 * XXX We need to check that X is not
1011*8b26181fSAndroid Build Coastguard Worker 			 * subsequently used, because we want to change
1012*8b26181fSAndroid Build Coastguard Worker 			 * what'll be in it after this sequence.
1013*8b26181fSAndroid Build Coastguard Worker 			 *
1014*8b26181fSAndroid Build Coastguard Worker 			 * We know we can eliminate the accumulator
1015*8b26181fSAndroid Build Coastguard Worker 			 * modifications earlier in the sequence since
1016*8b26181fSAndroid Build Coastguard Worker 			 * it is defined by the last stmt of this sequence
1017*8b26181fSAndroid Build Coastguard Worker 			 * (i.e., the last statement of the sequence loads
1018*8b26181fSAndroid Build Coastguard Worker 			 * a value into the accumulator, so we can eliminate
1019*8b26181fSAndroid Build Coastguard Worker 			 * earlier operations on the accumulator).
1020*8b26181fSAndroid Build Coastguard Worker 			 */
1021*8b26181fSAndroid Build Coastguard Worker 			ild->s.k += s->s.k;
1022*8b26181fSAndroid Build Coastguard Worker 			s->s.code = NOP;
1023*8b26181fSAndroid Build Coastguard Worker 			add->s.code = NOP;
1024*8b26181fSAndroid Build Coastguard Worker 			tax->s.code = NOP;
1025*8b26181fSAndroid Build Coastguard Worker 			/*
1026*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
1027*8b26181fSAndroid Build Coastguard Worker 			 */
1028*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
1029*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
1030*8b26181fSAndroid Build Coastguard Worker 		}
1031*8b26181fSAndroid Build Coastguard Worker 	}
1032*8b26181fSAndroid Build Coastguard Worker 	/*
1033*8b26181fSAndroid Build Coastguard Worker 	 * If the comparison at the end of a block is an equality
1034*8b26181fSAndroid Build Coastguard Worker 	 * comparison against a constant, and nobody uses the value
1035*8b26181fSAndroid Build Coastguard Worker 	 * we leave in the A register at the end of a block, and
1036*8b26181fSAndroid Build Coastguard Worker 	 * the operation preceding the comparison is an arithmetic
1037*8b26181fSAndroid Build Coastguard Worker 	 * operation, we can sometime optimize it away.
1038*8b26181fSAndroid Build Coastguard Worker 	 */
1039*8b26181fSAndroid Build Coastguard Worker 	if (b->s.code == (BPF_JMP|BPF_JEQ|BPF_K) &&
1040*8b26181fSAndroid Build Coastguard Worker 	    !ATOMELEM(b->out_use, A_ATOM)) {
1041*8b26181fSAndroid Build Coastguard Worker 		/*
1042*8b26181fSAndroid Build Coastguard Worker 		 * We can optimize away certain subtractions of the
1043*8b26181fSAndroid Build Coastguard Worker 		 * X register.
1044*8b26181fSAndroid Build Coastguard Worker 		 */
1045*8b26181fSAndroid Build Coastguard Worker 		if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X)) {
1046*8b26181fSAndroid Build Coastguard Worker 			val = b->val[X_ATOM];
1047*8b26181fSAndroid Build Coastguard Worker 			if (opt_state->vmap[val].is_const) {
1048*8b26181fSAndroid Build Coastguard Worker 				/*
1049*8b26181fSAndroid Build Coastguard Worker 				 * If we have a subtract to do a comparison,
1050*8b26181fSAndroid Build Coastguard Worker 				 * and the X register is a known constant,
1051*8b26181fSAndroid Build Coastguard Worker 				 * we can merge this value into the
1052*8b26181fSAndroid Build Coastguard Worker 				 * comparison:
1053*8b26181fSAndroid Build Coastguard Worker 				 *
1054*8b26181fSAndroid Build Coastguard Worker 				 * sub x  ->	nop
1055*8b26181fSAndroid Build Coastguard Worker 				 * jeq #y	jeq #(x+y)
1056*8b26181fSAndroid Build Coastguard Worker 				 */
1057*8b26181fSAndroid Build Coastguard Worker 				b->s.k += opt_state->vmap[val].const_val;
1058*8b26181fSAndroid Build Coastguard Worker 				last->s.code = NOP;
1059*8b26181fSAndroid Build Coastguard Worker 				/*
1060*8b26181fSAndroid Build Coastguard Worker 				 * XXX - optimizer loop detection.
1061*8b26181fSAndroid Build Coastguard Worker 				 */
1062*8b26181fSAndroid Build Coastguard Worker 				opt_state->non_branch_movement_performed = 1;
1063*8b26181fSAndroid Build Coastguard Worker 				opt_state->done = 0;
1064*8b26181fSAndroid Build Coastguard Worker 			} else if (b->s.k == 0) {
1065*8b26181fSAndroid Build Coastguard Worker 				/*
1066*8b26181fSAndroid Build Coastguard Worker 				 * If the X register isn't a constant,
1067*8b26181fSAndroid Build Coastguard Worker 				 * and the comparison in the test is
1068*8b26181fSAndroid Build Coastguard Worker 				 * against 0, we can compare with the
1069*8b26181fSAndroid Build Coastguard Worker 				 * X register, instead:
1070*8b26181fSAndroid Build Coastguard Worker 				 *
1071*8b26181fSAndroid Build Coastguard Worker 				 * sub x  ->	nop
1072*8b26181fSAndroid Build Coastguard Worker 				 * jeq #0	jeq x
1073*8b26181fSAndroid Build Coastguard Worker 				 */
1074*8b26181fSAndroid Build Coastguard Worker 				last->s.code = NOP;
1075*8b26181fSAndroid Build Coastguard Worker 				b->s.code = BPF_JMP|BPF_JEQ|BPF_X;
1076*8b26181fSAndroid Build Coastguard Worker 				/*
1077*8b26181fSAndroid Build Coastguard Worker 				 * XXX - optimizer loop detection.
1078*8b26181fSAndroid Build Coastguard Worker 				 */
1079*8b26181fSAndroid Build Coastguard Worker 				opt_state->non_branch_movement_performed = 1;
1080*8b26181fSAndroid Build Coastguard Worker 				opt_state->done = 0;
1081*8b26181fSAndroid Build Coastguard Worker 			}
1082*8b26181fSAndroid Build Coastguard Worker 		}
1083*8b26181fSAndroid Build Coastguard Worker 		/*
1084*8b26181fSAndroid Build Coastguard Worker 		 * Likewise, a constant subtract can be simplified:
1085*8b26181fSAndroid Build Coastguard Worker 		 *
1086*8b26181fSAndroid Build Coastguard Worker 		 * sub #x ->	nop
1087*8b26181fSAndroid Build Coastguard Worker 		 * jeq #y ->	jeq #(x+y)
1088*8b26181fSAndroid Build Coastguard Worker 		 */
1089*8b26181fSAndroid Build Coastguard Worker 		else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K)) {
1090*8b26181fSAndroid Build Coastguard Worker 			last->s.code = NOP;
1091*8b26181fSAndroid Build Coastguard Worker 			b->s.k += last->s.k;
1092*8b26181fSAndroid Build Coastguard Worker 			/*
1093*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
1094*8b26181fSAndroid Build Coastguard Worker 			 */
1095*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
1096*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
1097*8b26181fSAndroid Build Coastguard Worker 		}
1098*8b26181fSAndroid Build Coastguard Worker 		/*
1099*8b26181fSAndroid Build Coastguard Worker 		 * And, similarly, a constant AND can be simplified
1100*8b26181fSAndroid Build Coastguard Worker 		 * if we're testing against 0, i.e.:
1101*8b26181fSAndroid Build Coastguard Worker 		 *
1102*8b26181fSAndroid Build Coastguard Worker 		 * and #k	nop
1103*8b26181fSAndroid Build Coastguard Worker 		 * jeq #0  ->	jset #k
1104*8b26181fSAndroid Build Coastguard Worker 		 */
1105*8b26181fSAndroid Build Coastguard Worker 		else if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
1106*8b26181fSAndroid Build Coastguard Worker 		    b->s.k == 0) {
1107*8b26181fSAndroid Build Coastguard Worker 			b->s.k = last->s.k;
1108*8b26181fSAndroid Build Coastguard Worker 			b->s.code = BPF_JMP|BPF_K|BPF_JSET;
1109*8b26181fSAndroid Build Coastguard Worker 			last->s.code = NOP;
1110*8b26181fSAndroid Build Coastguard Worker 			/*
1111*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
1112*8b26181fSAndroid Build Coastguard Worker 			 */
1113*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
1114*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
1115*8b26181fSAndroid Build Coastguard Worker 			opt_not(b);
1116*8b26181fSAndroid Build Coastguard Worker 		}
1117*8b26181fSAndroid Build Coastguard Worker 	}
1118*8b26181fSAndroid Build Coastguard Worker 	/*
1119*8b26181fSAndroid Build Coastguard Worker 	 * jset #0        ->   never
1120*8b26181fSAndroid Build Coastguard Worker 	 * jset #ffffffff ->   always
1121*8b26181fSAndroid Build Coastguard Worker 	 */
1122*8b26181fSAndroid Build Coastguard Worker 	if (b->s.code == (BPF_JMP|BPF_K|BPF_JSET)) {
1123*8b26181fSAndroid Build Coastguard Worker 		if (b->s.k == 0)
1124*8b26181fSAndroid Build Coastguard Worker 			JT(b) = JF(b);
1125*8b26181fSAndroid Build Coastguard Worker 		if (b->s.k == 0xffffffffU)
1126*8b26181fSAndroid Build Coastguard Worker 			JF(b) = JT(b);
1127*8b26181fSAndroid Build Coastguard Worker 	}
1128*8b26181fSAndroid Build Coastguard Worker 	/*
1129*8b26181fSAndroid Build Coastguard Worker 	 * If we're comparing against the index register, and the index
1130*8b26181fSAndroid Build Coastguard Worker 	 * register is a known constant, we can just compare against that
1131*8b26181fSAndroid Build Coastguard Worker 	 * constant.
1132*8b26181fSAndroid Build Coastguard Worker 	 */
1133*8b26181fSAndroid Build Coastguard Worker 	val = b->val[X_ATOM];
1134*8b26181fSAndroid Build Coastguard Worker 	if (opt_state->vmap[val].is_const && BPF_SRC(b->s.code) == BPF_X) {
1135*8b26181fSAndroid Build Coastguard Worker 		bpf_u_int32 v = opt_state->vmap[val].const_val;
1136*8b26181fSAndroid Build Coastguard Worker 		b->s.code &= ~BPF_X;
1137*8b26181fSAndroid Build Coastguard Worker 		b->s.k = v;
1138*8b26181fSAndroid Build Coastguard Worker 	}
1139*8b26181fSAndroid Build Coastguard Worker 	/*
1140*8b26181fSAndroid Build Coastguard Worker 	 * If the accumulator is a known constant, we can compute the
1141*8b26181fSAndroid Build Coastguard Worker 	 * comparison result.
1142*8b26181fSAndroid Build Coastguard Worker 	 */
1143*8b26181fSAndroid Build Coastguard Worker 	val = b->val[A_ATOM];
1144*8b26181fSAndroid Build Coastguard Worker 	if (opt_state->vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) {
1145*8b26181fSAndroid Build Coastguard Worker 		bpf_u_int32 v = opt_state->vmap[val].const_val;
1146*8b26181fSAndroid Build Coastguard Worker 		switch (BPF_OP(b->s.code)) {
1147*8b26181fSAndroid Build Coastguard Worker 
1148*8b26181fSAndroid Build Coastguard Worker 		case BPF_JEQ:
1149*8b26181fSAndroid Build Coastguard Worker 			v = v == b->s.k;
1150*8b26181fSAndroid Build Coastguard Worker 			break;
1151*8b26181fSAndroid Build Coastguard Worker 
1152*8b26181fSAndroid Build Coastguard Worker 		case BPF_JGT:
1153*8b26181fSAndroid Build Coastguard Worker 			v = v > b->s.k;
1154*8b26181fSAndroid Build Coastguard Worker 			break;
1155*8b26181fSAndroid Build Coastguard Worker 
1156*8b26181fSAndroid Build Coastguard Worker 		case BPF_JGE:
1157*8b26181fSAndroid Build Coastguard Worker 			v = v >= b->s.k;
1158*8b26181fSAndroid Build Coastguard Worker 			break;
1159*8b26181fSAndroid Build Coastguard Worker 
1160*8b26181fSAndroid Build Coastguard Worker 		case BPF_JSET:
1161*8b26181fSAndroid Build Coastguard Worker 			v &= b->s.k;
1162*8b26181fSAndroid Build Coastguard Worker 			break;
1163*8b26181fSAndroid Build Coastguard Worker 
1164*8b26181fSAndroid Build Coastguard Worker 		default:
1165*8b26181fSAndroid Build Coastguard Worker 			abort();
1166*8b26181fSAndroid Build Coastguard Worker 		}
1167*8b26181fSAndroid Build Coastguard Worker 		if (JF(b) != JT(b)) {
1168*8b26181fSAndroid Build Coastguard Worker 			/*
1169*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
1170*8b26181fSAndroid Build Coastguard Worker 			 */
1171*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
1172*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
1173*8b26181fSAndroid Build Coastguard Worker 		}
1174*8b26181fSAndroid Build Coastguard Worker 		if (v)
1175*8b26181fSAndroid Build Coastguard Worker 			JF(b) = JT(b);
1176*8b26181fSAndroid Build Coastguard Worker 		else
1177*8b26181fSAndroid Build Coastguard Worker 			JT(b) = JF(b);
1178*8b26181fSAndroid Build Coastguard Worker 	}
1179*8b26181fSAndroid Build Coastguard Worker }
1180*8b26181fSAndroid Build Coastguard Worker 
1181*8b26181fSAndroid Build Coastguard Worker /*
1182*8b26181fSAndroid Build Coastguard Worker  * Compute the symbolic value of expression of 's', and update
1183*8b26181fSAndroid Build Coastguard Worker  * anything it defines in the value table 'val'.  If 'alter' is true,
1184*8b26181fSAndroid Build Coastguard Worker  * do various optimizations.  This code would be cleaner if symbolic
1185*8b26181fSAndroid Build Coastguard Worker  * evaluation and code transformations weren't folded together.
1186*8b26181fSAndroid Build Coastguard Worker  */
1187*8b26181fSAndroid Build Coastguard Worker static void
opt_stmt(opt_state_t * opt_state,struct stmt * s,bpf_u_int32 val[],int alter)1188*8b26181fSAndroid Build Coastguard Worker opt_stmt(opt_state_t *opt_state, struct stmt *s, bpf_u_int32 val[], int alter)
1189*8b26181fSAndroid Build Coastguard Worker {
1190*8b26181fSAndroid Build Coastguard Worker 	int op;
1191*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 v;
1192*8b26181fSAndroid Build Coastguard Worker 
1193*8b26181fSAndroid Build Coastguard Worker 	switch (s->code) {
1194*8b26181fSAndroid Build Coastguard Worker 
1195*8b26181fSAndroid Build Coastguard Worker 	case BPF_LD|BPF_ABS|BPF_W:
1196*8b26181fSAndroid Build Coastguard Worker 	case BPF_LD|BPF_ABS|BPF_H:
1197*8b26181fSAndroid Build Coastguard Worker 	case BPF_LD|BPF_ABS|BPF_B:
1198*8b26181fSAndroid Build Coastguard Worker 		v = F(opt_state, s->code, s->k, 0L);
1199*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[A_ATOM], v, alter);
1200*8b26181fSAndroid Build Coastguard Worker 		break;
1201*8b26181fSAndroid Build Coastguard Worker 
1202*8b26181fSAndroid Build Coastguard Worker 	case BPF_LD|BPF_IND|BPF_W:
1203*8b26181fSAndroid Build Coastguard Worker 	case BPF_LD|BPF_IND|BPF_H:
1204*8b26181fSAndroid Build Coastguard Worker 	case BPF_LD|BPF_IND|BPF_B:
1205*8b26181fSAndroid Build Coastguard Worker 		v = val[X_ATOM];
1206*8b26181fSAndroid Build Coastguard Worker 		if (alter && opt_state->vmap[v].is_const) {
1207*8b26181fSAndroid Build Coastguard Worker 			s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code);
1208*8b26181fSAndroid Build Coastguard Worker 			s->k += opt_state->vmap[v].const_val;
1209*8b26181fSAndroid Build Coastguard Worker 			v = F(opt_state, s->code, s->k, 0L);
1210*8b26181fSAndroid Build Coastguard Worker 			/*
1211*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
1212*8b26181fSAndroid Build Coastguard Worker 			 */
1213*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
1214*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
1215*8b26181fSAndroid Build Coastguard Worker 		}
1216*8b26181fSAndroid Build Coastguard Worker 		else
1217*8b26181fSAndroid Build Coastguard Worker 			v = F(opt_state, s->code, s->k, v);
1218*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[A_ATOM], v, alter);
1219*8b26181fSAndroid Build Coastguard Worker 		break;
1220*8b26181fSAndroid Build Coastguard Worker 
1221*8b26181fSAndroid Build Coastguard Worker 	case BPF_LD|BPF_LEN:
1222*8b26181fSAndroid Build Coastguard Worker 		v = F(opt_state, s->code, 0L, 0L);
1223*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[A_ATOM], v, alter);
1224*8b26181fSAndroid Build Coastguard Worker 		break;
1225*8b26181fSAndroid Build Coastguard Worker 
1226*8b26181fSAndroid Build Coastguard Worker 	case BPF_LD|BPF_IMM:
1227*8b26181fSAndroid Build Coastguard Worker 		v = K(s->k);
1228*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[A_ATOM], v, alter);
1229*8b26181fSAndroid Build Coastguard Worker 		break;
1230*8b26181fSAndroid Build Coastguard Worker 
1231*8b26181fSAndroid Build Coastguard Worker 	case BPF_LDX|BPF_IMM:
1232*8b26181fSAndroid Build Coastguard Worker 		v = K(s->k);
1233*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[X_ATOM], v, alter);
1234*8b26181fSAndroid Build Coastguard Worker 		break;
1235*8b26181fSAndroid Build Coastguard Worker 
1236*8b26181fSAndroid Build Coastguard Worker 	case BPF_LDX|BPF_MSH|BPF_B:
1237*8b26181fSAndroid Build Coastguard Worker 		v = F(opt_state, s->code, s->k, 0L);
1238*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[X_ATOM], v, alter);
1239*8b26181fSAndroid Build Coastguard Worker 		break;
1240*8b26181fSAndroid Build Coastguard Worker 
1241*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_NEG:
1242*8b26181fSAndroid Build Coastguard Worker 		if (alter && opt_state->vmap[val[A_ATOM]].is_const) {
1243*8b26181fSAndroid Build Coastguard Worker 			s->code = BPF_LD|BPF_IMM;
1244*8b26181fSAndroid Build Coastguard Worker 			/*
1245*8b26181fSAndroid Build Coastguard Worker 			 * Do this negation as unsigned arithmetic; that's
1246*8b26181fSAndroid Build Coastguard Worker 			 * what modern BPF engines do, and it guarantees
1247*8b26181fSAndroid Build Coastguard Worker 			 * that all possible values can be negated.  (Yeah,
1248*8b26181fSAndroid Build Coastguard Worker 			 * negating 0x80000000, the minimum signed 32-bit
1249*8b26181fSAndroid Build Coastguard Worker 			 * two's-complement value, results in 0x80000000,
1250*8b26181fSAndroid Build Coastguard Worker 			 * so it's still negative, but we *should* be doing
1251*8b26181fSAndroid Build Coastguard Worker 			 * all unsigned arithmetic here, to match what
1252*8b26181fSAndroid Build Coastguard Worker 			 * modern BPF engines do.)
1253*8b26181fSAndroid Build Coastguard Worker 			 *
1254*8b26181fSAndroid Build Coastguard Worker 			 * Express it as 0U - (unsigned value) so that we
1255*8b26181fSAndroid Build Coastguard Worker 			 * don't get compiler warnings about negating an
1256*8b26181fSAndroid Build Coastguard Worker 			 * unsigned value and don't get UBSan warnings
1257*8b26181fSAndroid Build Coastguard Worker 			 * about the result of negating 0x80000000 being
1258*8b26181fSAndroid Build Coastguard Worker 			 * undefined.
1259*8b26181fSAndroid Build Coastguard Worker 			 */
1260*8b26181fSAndroid Build Coastguard Worker 			s->k = 0U - opt_state->vmap[val[A_ATOM]].const_val;
1261*8b26181fSAndroid Build Coastguard Worker 			val[A_ATOM] = K(s->k);
1262*8b26181fSAndroid Build Coastguard Worker 		}
1263*8b26181fSAndroid Build Coastguard Worker 		else
1264*8b26181fSAndroid Build Coastguard Worker 			val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], 0L);
1265*8b26181fSAndroid Build Coastguard Worker 		break;
1266*8b26181fSAndroid Build Coastguard Worker 
1267*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_ADD|BPF_K:
1268*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_SUB|BPF_K:
1269*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_MUL|BPF_K:
1270*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_DIV|BPF_K:
1271*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_MOD|BPF_K:
1272*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_AND|BPF_K:
1273*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_OR|BPF_K:
1274*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_XOR|BPF_K:
1275*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_LSH|BPF_K:
1276*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_RSH|BPF_K:
1277*8b26181fSAndroid Build Coastguard Worker 		op = BPF_OP(s->code);
1278*8b26181fSAndroid Build Coastguard Worker 		if (alter) {
1279*8b26181fSAndroid Build Coastguard Worker 			if (s->k == 0) {
1280*8b26181fSAndroid Build Coastguard Worker 				/*
1281*8b26181fSAndroid Build Coastguard Worker 				 * Optimize operations where the constant
1282*8b26181fSAndroid Build Coastguard Worker 				 * is zero.
1283*8b26181fSAndroid Build Coastguard Worker 				 *
1284*8b26181fSAndroid Build Coastguard Worker 				 * Don't optimize away "sub #0"
1285*8b26181fSAndroid Build Coastguard Worker 				 * as it may be needed later to
1286*8b26181fSAndroid Build Coastguard Worker 				 * fixup the generated math code.
1287*8b26181fSAndroid Build Coastguard Worker 				 *
1288*8b26181fSAndroid Build Coastguard Worker 				 * Fail if we're dividing by zero or taking
1289*8b26181fSAndroid Build Coastguard Worker 				 * a modulus by zero.
1290*8b26181fSAndroid Build Coastguard Worker 				 */
1291*8b26181fSAndroid Build Coastguard Worker 				if (op == BPF_ADD ||
1292*8b26181fSAndroid Build Coastguard Worker 				    op == BPF_LSH || op == BPF_RSH ||
1293*8b26181fSAndroid Build Coastguard Worker 				    op == BPF_OR || op == BPF_XOR) {
1294*8b26181fSAndroid Build Coastguard Worker 					s->code = NOP;
1295*8b26181fSAndroid Build Coastguard Worker 					break;
1296*8b26181fSAndroid Build Coastguard Worker 				}
1297*8b26181fSAndroid Build Coastguard Worker 				if (op == BPF_MUL || op == BPF_AND) {
1298*8b26181fSAndroid Build Coastguard Worker 					s->code = BPF_LD|BPF_IMM;
1299*8b26181fSAndroid Build Coastguard Worker 					val[A_ATOM] = K(s->k);
1300*8b26181fSAndroid Build Coastguard Worker 					break;
1301*8b26181fSAndroid Build Coastguard Worker 				}
1302*8b26181fSAndroid Build Coastguard Worker 				if (op == BPF_DIV)
1303*8b26181fSAndroid Build Coastguard Worker 					opt_error(opt_state,
1304*8b26181fSAndroid Build Coastguard Worker 					    "division by zero");
1305*8b26181fSAndroid Build Coastguard Worker 				if (op == BPF_MOD)
1306*8b26181fSAndroid Build Coastguard Worker 					opt_error(opt_state,
1307*8b26181fSAndroid Build Coastguard Worker 					    "modulus by zero");
1308*8b26181fSAndroid Build Coastguard Worker 			}
1309*8b26181fSAndroid Build Coastguard Worker 			if (opt_state->vmap[val[A_ATOM]].is_const) {
1310*8b26181fSAndroid Build Coastguard Worker 				fold_op(opt_state, s, val[A_ATOM], K(s->k));
1311*8b26181fSAndroid Build Coastguard Worker 				val[A_ATOM] = K(s->k);
1312*8b26181fSAndroid Build Coastguard Worker 				break;
1313*8b26181fSAndroid Build Coastguard Worker 			}
1314*8b26181fSAndroid Build Coastguard Worker 		}
1315*8b26181fSAndroid Build Coastguard Worker 		val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], K(s->k));
1316*8b26181fSAndroid Build Coastguard Worker 		break;
1317*8b26181fSAndroid Build Coastguard Worker 
1318*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_ADD|BPF_X:
1319*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_SUB|BPF_X:
1320*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_MUL|BPF_X:
1321*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_DIV|BPF_X:
1322*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_MOD|BPF_X:
1323*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_AND|BPF_X:
1324*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_OR|BPF_X:
1325*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_XOR|BPF_X:
1326*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_LSH|BPF_X:
1327*8b26181fSAndroid Build Coastguard Worker 	case BPF_ALU|BPF_RSH|BPF_X:
1328*8b26181fSAndroid Build Coastguard Worker 		op = BPF_OP(s->code);
1329*8b26181fSAndroid Build Coastguard Worker 		if (alter && opt_state->vmap[val[X_ATOM]].is_const) {
1330*8b26181fSAndroid Build Coastguard Worker 			if (opt_state->vmap[val[A_ATOM]].is_const) {
1331*8b26181fSAndroid Build Coastguard Worker 				fold_op(opt_state, s, val[A_ATOM], val[X_ATOM]);
1332*8b26181fSAndroid Build Coastguard Worker 				val[A_ATOM] = K(s->k);
1333*8b26181fSAndroid Build Coastguard Worker 			}
1334*8b26181fSAndroid Build Coastguard Worker 			else {
1335*8b26181fSAndroid Build Coastguard Worker 				s->code = BPF_ALU|BPF_K|op;
1336*8b26181fSAndroid Build Coastguard Worker 				s->k = opt_state->vmap[val[X_ATOM]].const_val;
1337*8b26181fSAndroid Build Coastguard Worker 				if ((op == BPF_LSH || op == BPF_RSH) &&
1338*8b26181fSAndroid Build Coastguard Worker 				    s->k > 31)
1339*8b26181fSAndroid Build Coastguard Worker 					opt_error(opt_state,
1340*8b26181fSAndroid Build Coastguard Worker 					    "shift by more than 31 bits");
1341*8b26181fSAndroid Build Coastguard Worker 				/*
1342*8b26181fSAndroid Build Coastguard Worker 				 * XXX - optimizer loop detection.
1343*8b26181fSAndroid Build Coastguard Worker 				 */
1344*8b26181fSAndroid Build Coastguard Worker 				opt_state->non_branch_movement_performed = 1;
1345*8b26181fSAndroid Build Coastguard Worker 				opt_state->done = 0;
1346*8b26181fSAndroid Build Coastguard Worker 				val[A_ATOM] =
1347*8b26181fSAndroid Build Coastguard Worker 					F(opt_state, s->code, val[A_ATOM], K(s->k));
1348*8b26181fSAndroid Build Coastguard Worker 			}
1349*8b26181fSAndroid Build Coastguard Worker 			break;
1350*8b26181fSAndroid Build Coastguard Worker 		}
1351*8b26181fSAndroid Build Coastguard Worker 		/*
1352*8b26181fSAndroid Build Coastguard Worker 		 * Check if we're doing something to an accumulator
1353*8b26181fSAndroid Build Coastguard Worker 		 * that is 0, and simplify.  This may not seem like
1354*8b26181fSAndroid Build Coastguard Worker 		 * much of a simplification but it could open up further
1355*8b26181fSAndroid Build Coastguard Worker 		 * optimizations.
1356*8b26181fSAndroid Build Coastguard Worker 		 * XXX We could also check for mul by 1, etc.
1357*8b26181fSAndroid Build Coastguard Worker 		 */
1358*8b26181fSAndroid Build Coastguard Worker 		if (alter && opt_state->vmap[val[A_ATOM]].is_const
1359*8b26181fSAndroid Build Coastguard Worker 		    && opt_state->vmap[val[A_ATOM]].const_val == 0) {
1360*8b26181fSAndroid Build Coastguard Worker 			if (op == BPF_ADD || op == BPF_OR || op == BPF_XOR) {
1361*8b26181fSAndroid Build Coastguard Worker 				s->code = BPF_MISC|BPF_TXA;
1362*8b26181fSAndroid Build Coastguard Worker 				vstore(s, &val[A_ATOM], val[X_ATOM], alter);
1363*8b26181fSAndroid Build Coastguard Worker 				break;
1364*8b26181fSAndroid Build Coastguard Worker 			}
1365*8b26181fSAndroid Build Coastguard Worker 			else if (op == BPF_MUL || op == BPF_DIV || op == BPF_MOD ||
1366*8b26181fSAndroid Build Coastguard Worker 				 op == BPF_AND || op == BPF_LSH || op == BPF_RSH) {
1367*8b26181fSAndroid Build Coastguard Worker 				s->code = BPF_LD|BPF_IMM;
1368*8b26181fSAndroid Build Coastguard Worker 				s->k = 0;
1369*8b26181fSAndroid Build Coastguard Worker 				vstore(s, &val[A_ATOM], K(s->k), alter);
1370*8b26181fSAndroid Build Coastguard Worker 				break;
1371*8b26181fSAndroid Build Coastguard Worker 			}
1372*8b26181fSAndroid Build Coastguard Worker 			else if (op == BPF_NEG) {
1373*8b26181fSAndroid Build Coastguard Worker 				s->code = NOP;
1374*8b26181fSAndroid Build Coastguard Worker 				break;
1375*8b26181fSAndroid Build Coastguard Worker 			}
1376*8b26181fSAndroid Build Coastguard Worker 		}
1377*8b26181fSAndroid Build Coastguard Worker 		val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], val[X_ATOM]);
1378*8b26181fSAndroid Build Coastguard Worker 		break;
1379*8b26181fSAndroid Build Coastguard Worker 
1380*8b26181fSAndroid Build Coastguard Worker 	case BPF_MISC|BPF_TXA:
1381*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[A_ATOM], val[X_ATOM], alter);
1382*8b26181fSAndroid Build Coastguard Worker 		break;
1383*8b26181fSAndroid Build Coastguard Worker 
1384*8b26181fSAndroid Build Coastguard Worker 	case BPF_LD|BPF_MEM:
1385*8b26181fSAndroid Build Coastguard Worker 		v = val[s->k];
1386*8b26181fSAndroid Build Coastguard Worker 		if (alter && opt_state->vmap[v].is_const) {
1387*8b26181fSAndroid Build Coastguard Worker 			s->code = BPF_LD|BPF_IMM;
1388*8b26181fSAndroid Build Coastguard Worker 			s->k = opt_state->vmap[v].const_val;
1389*8b26181fSAndroid Build Coastguard Worker 			/*
1390*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
1391*8b26181fSAndroid Build Coastguard Worker 			 */
1392*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
1393*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
1394*8b26181fSAndroid Build Coastguard Worker 		}
1395*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[A_ATOM], v, alter);
1396*8b26181fSAndroid Build Coastguard Worker 		break;
1397*8b26181fSAndroid Build Coastguard Worker 
1398*8b26181fSAndroid Build Coastguard Worker 	case BPF_MISC|BPF_TAX:
1399*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[X_ATOM], val[A_ATOM], alter);
1400*8b26181fSAndroid Build Coastguard Worker 		break;
1401*8b26181fSAndroid Build Coastguard Worker 
1402*8b26181fSAndroid Build Coastguard Worker 	case BPF_LDX|BPF_MEM:
1403*8b26181fSAndroid Build Coastguard Worker 		v = val[s->k];
1404*8b26181fSAndroid Build Coastguard Worker 		if (alter && opt_state->vmap[v].is_const) {
1405*8b26181fSAndroid Build Coastguard Worker 			s->code = BPF_LDX|BPF_IMM;
1406*8b26181fSAndroid Build Coastguard Worker 			s->k = opt_state->vmap[v].const_val;
1407*8b26181fSAndroid Build Coastguard Worker 			/*
1408*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
1409*8b26181fSAndroid Build Coastguard Worker 			 */
1410*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
1411*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
1412*8b26181fSAndroid Build Coastguard Worker 		}
1413*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[X_ATOM], v, alter);
1414*8b26181fSAndroid Build Coastguard Worker 		break;
1415*8b26181fSAndroid Build Coastguard Worker 
1416*8b26181fSAndroid Build Coastguard Worker 	case BPF_ST:
1417*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[s->k], val[A_ATOM], alter);
1418*8b26181fSAndroid Build Coastguard Worker 		break;
1419*8b26181fSAndroid Build Coastguard Worker 
1420*8b26181fSAndroid Build Coastguard Worker 	case BPF_STX:
1421*8b26181fSAndroid Build Coastguard Worker 		vstore(s, &val[s->k], val[X_ATOM], alter);
1422*8b26181fSAndroid Build Coastguard Worker 		break;
1423*8b26181fSAndroid Build Coastguard Worker 	}
1424*8b26181fSAndroid Build Coastguard Worker }
1425*8b26181fSAndroid Build Coastguard Worker 
1426*8b26181fSAndroid Build Coastguard Worker static void
deadstmt(opt_state_t * opt_state,register struct stmt * s,register struct stmt * last[])1427*8b26181fSAndroid Build Coastguard Worker deadstmt(opt_state_t *opt_state, register struct stmt *s, register struct stmt *last[])
1428*8b26181fSAndroid Build Coastguard Worker {
1429*8b26181fSAndroid Build Coastguard Worker 	register int atom;
1430*8b26181fSAndroid Build Coastguard Worker 
1431*8b26181fSAndroid Build Coastguard Worker 	atom = atomuse(s);
1432*8b26181fSAndroid Build Coastguard Worker 	if (atom >= 0) {
1433*8b26181fSAndroid Build Coastguard Worker 		if (atom == AX_ATOM) {
1434*8b26181fSAndroid Build Coastguard Worker 			last[X_ATOM] = 0;
1435*8b26181fSAndroid Build Coastguard Worker 			last[A_ATOM] = 0;
1436*8b26181fSAndroid Build Coastguard Worker 		}
1437*8b26181fSAndroid Build Coastguard Worker 		else
1438*8b26181fSAndroid Build Coastguard Worker 			last[atom] = 0;
1439*8b26181fSAndroid Build Coastguard Worker 	}
1440*8b26181fSAndroid Build Coastguard Worker 	atom = atomdef(s);
1441*8b26181fSAndroid Build Coastguard Worker 	if (atom >= 0) {
1442*8b26181fSAndroid Build Coastguard Worker 		if (last[atom]) {
1443*8b26181fSAndroid Build Coastguard Worker 			/*
1444*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
1445*8b26181fSAndroid Build Coastguard Worker 			 */
1446*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
1447*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
1448*8b26181fSAndroid Build Coastguard Worker 			last[atom]->code = NOP;
1449*8b26181fSAndroid Build Coastguard Worker 		}
1450*8b26181fSAndroid Build Coastguard Worker 		last[atom] = s;
1451*8b26181fSAndroid Build Coastguard Worker 	}
1452*8b26181fSAndroid Build Coastguard Worker }
1453*8b26181fSAndroid Build Coastguard Worker 
1454*8b26181fSAndroid Build Coastguard Worker static void
opt_deadstores(opt_state_t * opt_state,register struct block * b)1455*8b26181fSAndroid Build Coastguard Worker opt_deadstores(opt_state_t *opt_state, register struct block *b)
1456*8b26181fSAndroid Build Coastguard Worker {
1457*8b26181fSAndroid Build Coastguard Worker 	register struct slist *s;
1458*8b26181fSAndroid Build Coastguard Worker 	register int atom;
1459*8b26181fSAndroid Build Coastguard Worker 	struct stmt *last[N_ATOMS];
1460*8b26181fSAndroid Build Coastguard Worker 
1461*8b26181fSAndroid Build Coastguard Worker 	memset((char *)last, 0, sizeof last);
1462*8b26181fSAndroid Build Coastguard Worker 
1463*8b26181fSAndroid Build Coastguard Worker 	for (s = b->stmts; s != 0; s = s->next)
1464*8b26181fSAndroid Build Coastguard Worker 		deadstmt(opt_state, &s->s, last);
1465*8b26181fSAndroid Build Coastguard Worker 	deadstmt(opt_state, &b->s, last);
1466*8b26181fSAndroid Build Coastguard Worker 
1467*8b26181fSAndroid Build Coastguard Worker 	for (atom = 0; atom < N_ATOMS; ++atom)
1468*8b26181fSAndroid Build Coastguard Worker 		if (last[atom] && !ATOMELEM(b->out_use, atom)) {
1469*8b26181fSAndroid Build Coastguard Worker 			last[atom]->code = NOP;
1470*8b26181fSAndroid Build Coastguard Worker 			/*
1471*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
1472*8b26181fSAndroid Build Coastguard Worker 			 */
1473*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
1474*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
1475*8b26181fSAndroid Build Coastguard Worker 		}
1476*8b26181fSAndroid Build Coastguard Worker }
1477*8b26181fSAndroid Build Coastguard Worker 
1478*8b26181fSAndroid Build Coastguard Worker static void
opt_blk(opt_state_t * opt_state,struct block * b,int do_stmts)1479*8b26181fSAndroid Build Coastguard Worker opt_blk(opt_state_t *opt_state, struct block *b, int do_stmts)
1480*8b26181fSAndroid Build Coastguard Worker {
1481*8b26181fSAndroid Build Coastguard Worker 	struct slist *s;
1482*8b26181fSAndroid Build Coastguard Worker 	struct edge *p;
1483*8b26181fSAndroid Build Coastguard Worker 	int i;
1484*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 aval, xval;
1485*8b26181fSAndroid Build Coastguard Worker 
1486*8b26181fSAndroid Build Coastguard Worker #if 0
1487*8b26181fSAndroid Build Coastguard Worker 	for (s = b->stmts; s && s->next; s = s->next)
1488*8b26181fSAndroid Build Coastguard Worker 		if (BPF_CLASS(s->s.code) == BPF_JMP) {
1489*8b26181fSAndroid Build Coastguard Worker 			do_stmts = 0;
1490*8b26181fSAndroid Build Coastguard Worker 			break;
1491*8b26181fSAndroid Build Coastguard Worker 		}
1492*8b26181fSAndroid Build Coastguard Worker #endif
1493*8b26181fSAndroid Build Coastguard Worker 
1494*8b26181fSAndroid Build Coastguard Worker 	/*
1495*8b26181fSAndroid Build Coastguard Worker 	 * Initialize the atom values.
1496*8b26181fSAndroid Build Coastguard Worker 	 */
1497*8b26181fSAndroid Build Coastguard Worker 	p = b->in_edges;
1498*8b26181fSAndroid Build Coastguard Worker 	if (p == 0) {
1499*8b26181fSAndroid Build Coastguard Worker 		/*
1500*8b26181fSAndroid Build Coastguard Worker 		 * We have no predecessors, so everything is undefined
1501*8b26181fSAndroid Build Coastguard Worker 		 * upon entry to this block.
1502*8b26181fSAndroid Build Coastguard Worker 		 */
1503*8b26181fSAndroid Build Coastguard Worker 		memset((char *)b->val, 0, sizeof(b->val));
1504*8b26181fSAndroid Build Coastguard Worker 	} else {
1505*8b26181fSAndroid Build Coastguard Worker 		/*
1506*8b26181fSAndroid Build Coastguard Worker 		 * Inherit values from our predecessors.
1507*8b26181fSAndroid Build Coastguard Worker 		 *
1508*8b26181fSAndroid Build Coastguard Worker 		 * First, get the values from the predecessor along the
1509*8b26181fSAndroid Build Coastguard Worker 		 * first edge leading to this node.
1510*8b26181fSAndroid Build Coastguard Worker 		 */
1511*8b26181fSAndroid Build Coastguard Worker 		memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val));
1512*8b26181fSAndroid Build Coastguard Worker 		/*
1513*8b26181fSAndroid Build Coastguard Worker 		 * Now look at all the other nodes leading to this node.
1514*8b26181fSAndroid Build Coastguard Worker 		 * If, for the predecessor along that edge, a register
1515*8b26181fSAndroid Build Coastguard Worker 		 * has a different value from the one we have (i.e.,
1516*8b26181fSAndroid Build Coastguard Worker 		 * control paths are merging, and the merging paths
1517*8b26181fSAndroid Build Coastguard Worker 		 * assign different values to that register), give the
1518*8b26181fSAndroid Build Coastguard Worker 		 * register the undefined value of 0.
1519*8b26181fSAndroid Build Coastguard Worker 		 */
1520*8b26181fSAndroid Build Coastguard Worker 		while ((p = p->next) != NULL) {
1521*8b26181fSAndroid Build Coastguard Worker 			for (i = 0; i < N_ATOMS; ++i)
1522*8b26181fSAndroid Build Coastguard Worker 				if (b->val[i] != p->pred->val[i])
1523*8b26181fSAndroid Build Coastguard Worker 					b->val[i] = 0;
1524*8b26181fSAndroid Build Coastguard Worker 		}
1525*8b26181fSAndroid Build Coastguard Worker 	}
1526*8b26181fSAndroid Build Coastguard Worker 	aval = b->val[A_ATOM];
1527*8b26181fSAndroid Build Coastguard Worker 	xval = b->val[X_ATOM];
1528*8b26181fSAndroid Build Coastguard Worker 	for (s = b->stmts; s; s = s->next)
1529*8b26181fSAndroid Build Coastguard Worker 		opt_stmt(opt_state, &s->s, b->val, do_stmts);
1530*8b26181fSAndroid Build Coastguard Worker 
1531*8b26181fSAndroid Build Coastguard Worker 	/*
1532*8b26181fSAndroid Build Coastguard Worker 	 * This is a special case: if we don't use anything from this
1533*8b26181fSAndroid Build Coastguard Worker 	 * block, and we load the accumulator or index register with a
1534*8b26181fSAndroid Build Coastguard Worker 	 * value that is already there, or if this block is a return,
1535*8b26181fSAndroid Build Coastguard Worker 	 * eliminate all the statements.
1536*8b26181fSAndroid Build Coastguard Worker 	 *
1537*8b26181fSAndroid Build Coastguard Worker 	 * XXX - what if it does a store?  Presumably that falls under
1538*8b26181fSAndroid Build Coastguard Worker 	 * the heading of "if we don't use anything from this block",
1539*8b26181fSAndroid Build Coastguard Worker 	 * i.e., if we use any memory location set to a different
1540*8b26181fSAndroid Build Coastguard Worker 	 * value by this block, then we use something from this block.
1541*8b26181fSAndroid Build Coastguard Worker 	 *
1542*8b26181fSAndroid Build Coastguard Worker 	 * XXX - why does it matter whether we use anything from this
1543*8b26181fSAndroid Build Coastguard Worker 	 * block?  If the accumulator or index register doesn't change
1544*8b26181fSAndroid Build Coastguard Worker 	 * its value, isn't that OK even if we use that value?
1545*8b26181fSAndroid Build Coastguard Worker 	 *
1546*8b26181fSAndroid Build Coastguard Worker 	 * XXX - if we load the accumulator with a different value,
1547*8b26181fSAndroid Build Coastguard Worker 	 * and the block ends with a conditional branch, we obviously
1548*8b26181fSAndroid Build Coastguard Worker 	 * can't eliminate it, as the branch depends on that value.
1549*8b26181fSAndroid Build Coastguard Worker 	 * For the index register, the conditional branch only depends
1550*8b26181fSAndroid Build Coastguard Worker 	 * on the index register value if the test is against the index
1551*8b26181fSAndroid Build Coastguard Worker 	 * register value rather than a constant; if nothing uses the
1552*8b26181fSAndroid Build Coastguard Worker 	 * value we put into the index register, and we're not testing
1553*8b26181fSAndroid Build Coastguard Worker 	 * against the index register's value, and there aren't any
1554*8b26181fSAndroid Build Coastguard Worker 	 * other problems that would keep us from eliminating this
1555*8b26181fSAndroid Build Coastguard Worker 	 * block, can we eliminate it?
1556*8b26181fSAndroid Build Coastguard Worker 	 */
1557*8b26181fSAndroid Build Coastguard Worker 	if (do_stmts &&
1558*8b26181fSAndroid Build Coastguard Worker 	    ((b->out_use == 0 &&
1559*8b26181fSAndroid Build Coastguard Worker 	      aval != VAL_UNKNOWN && b->val[A_ATOM] == aval &&
1560*8b26181fSAndroid Build Coastguard Worker 	      xval != VAL_UNKNOWN && b->val[X_ATOM] == xval) ||
1561*8b26181fSAndroid Build Coastguard Worker 	     BPF_CLASS(b->s.code) == BPF_RET)) {
1562*8b26181fSAndroid Build Coastguard Worker 		if (b->stmts != 0) {
1563*8b26181fSAndroid Build Coastguard Worker 			b->stmts = 0;
1564*8b26181fSAndroid Build Coastguard Worker 			/*
1565*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
1566*8b26181fSAndroid Build Coastguard Worker 			 */
1567*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
1568*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
1569*8b26181fSAndroid Build Coastguard Worker 		}
1570*8b26181fSAndroid Build Coastguard Worker 	} else {
1571*8b26181fSAndroid Build Coastguard Worker 		opt_peep(opt_state, b);
1572*8b26181fSAndroid Build Coastguard Worker 		opt_deadstores(opt_state, b);
1573*8b26181fSAndroid Build Coastguard Worker 	}
1574*8b26181fSAndroid Build Coastguard Worker 	/*
1575*8b26181fSAndroid Build Coastguard Worker 	 * Set up values for branch optimizer.
1576*8b26181fSAndroid Build Coastguard Worker 	 */
1577*8b26181fSAndroid Build Coastguard Worker 	if (BPF_SRC(b->s.code) == BPF_K)
1578*8b26181fSAndroid Build Coastguard Worker 		b->oval = K(b->s.k);
1579*8b26181fSAndroid Build Coastguard Worker 	else
1580*8b26181fSAndroid Build Coastguard Worker 		b->oval = b->val[X_ATOM];
1581*8b26181fSAndroid Build Coastguard Worker 	b->et.code = b->s.code;
1582*8b26181fSAndroid Build Coastguard Worker 	b->ef.code = -b->s.code;
1583*8b26181fSAndroid Build Coastguard Worker }
1584*8b26181fSAndroid Build Coastguard Worker 
1585*8b26181fSAndroid Build Coastguard Worker /*
1586*8b26181fSAndroid Build Coastguard Worker  * Return true if any register that is used on exit from 'succ', has
1587*8b26181fSAndroid Build Coastguard Worker  * an exit value that is different from the corresponding exit value
1588*8b26181fSAndroid Build Coastguard Worker  * from 'b'.
1589*8b26181fSAndroid Build Coastguard Worker  */
1590*8b26181fSAndroid Build Coastguard Worker static int
use_conflict(struct block * b,struct block * succ)1591*8b26181fSAndroid Build Coastguard Worker use_conflict(struct block *b, struct block *succ)
1592*8b26181fSAndroid Build Coastguard Worker {
1593*8b26181fSAndroid Build Coastguard Worker 	int atom;
1594*8b26181fSAndroid Build Coastguard Worker 	atomset use = succ->out_use;
1595*8b26181fSAndroid Build Coastguard Worker 
1596*8b26181fSAndroid Build Coastguard Worker 	if (use == 0)
1597*8b26181fSAndroid Build Coastguard Worker 		return 0;
1598*8b26181fSAndroid Build Coastguard Worker 
1599*8b26181fSAndroid Build Coastguard Worker 	for (atom = 0; atom < N_ATOMS; ++atom)
1600*8b26181fSAndroid Build Coastguard Worker 		if (ATOMELEM(use, atom))
1601*8b26181fSAndroid Build Coastguard Worker 			if (b->val[atom] != succ->val[atom])
1602*8b26181fSAndroid Build Coastguard Worker 				return 1;
1603*8b26181fSAndroid Build Coastguard Worker 	return 0;
1604*8b26181fSAndroid Build Coastguard Worker }
1605*8b26181fSAndroid Build Coastguard Worker 
1606*8b26181fSAndroid Build Coastguard Worker /*
1607*8b26181fSAndroid Build Coastguard Worker  * Given a block that is the successor of an edge, and an edge that
1608*8b26181fSAndroid Build Coastguard Worker  * dominates that edge, return either a pointer to a child of that
1609*8b26181fSAndroid Build Coastguard Worker  * block (a block to which that block jumps) if that block is a
1610*8b26181fSAndroid Build Coastguard Worker  * candidate to replace the successor of the latter edge or NULL
1611*8b26181fSAndroid Build Coastguard Worker  * if neither of the children of the first block are candidates.
1612*8b26181fSAndroid Build Coastguard Worker  */
1613*8b26181fSAndroid Build Coastguard Worker static struct block *
fold_edge(struct block * child,struct edge * ep)1614*8b26181fSAndroid Build Coastguard Worker fold_edge(struct block *child, struct edge *ep)
1615*8b26181fSAndroid Build Coastguard Worker {
1616*8b26181fSAndroid Build Coastguard Worker 	int sense;
1617*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 aval0, aval1, oval0, oval1;
1618*8b26181fSAndroid Build Coastguard Worker 	int code = ep->code;
1619*8b26181fSAndroid Build Coastguard Worker 
1620*8b26181fSAndroid Build Coastguard Worker 	if (code < 0) {
1621*8b26181fSAndroid Build Coastguard Worker 		/*
1622*8b26181fSAndroid Build Coastguard Worker 		 * This edge is a "branch if false" edge.
1623*8b26181fSAndroid Build Coastguard Worker 		 */
1624*8b26181fSAndroid Build Coastguard Worker 		code = -code;
1625*8b26181fSAndroid Build Coastguard Worker 		sense = 0;
1626*8b26181fSAndroid Build Coastguard Worker 	} else {
1627*8b26181fSAndroid Build Coastguard Worker 		/*
1628*8b26181fSAndroid Build Coastguard Worker 		 * This edge is a "branch if true" edge.
1629*8b26181fSAndroid Build Coastguard Worker 		 */
1630*8b26181fSAndroid Build Coastguard Worker 		sense = 1;
1631*8b26181fSAndroid Build Coastguard Worker 	}
1632*8b26181fSAndroid Build Coastguard Worker 
1633*8b26181fSAndroid Build Coastguard Worker 	/*
1634*8b26181fSAndroid Build Coastguard Worker 	 * If the opcode for the branch at the end of the block we
1635*8b26181fSAndroid Build Coastguard Worker 	 * were handed isn't the same as the opcode for the branch
1636*8b26181fSAndroid Build Coastguard Worker 	 * to which the edge we were handed corresponds, the tests
1637*8b26181fSAndroid Build Coastguard Worker 	 * for those branches aren't testing the same conditions,
1638*8b26181fSAndroid Build Coastguard Worker 	 * so the blocks to which the first block branches aren't
1639*8b26181fSAndroid Build Coastguard Worker 	 * candidates to replace the successor of the edge.
1640*8b26181fSAndroid Build Coastguard Worker 	 */
1641*8b26181fSAndroid Build Coastguard Worker 	if (child->s.code != code)
1642*8b26181fSAndroid Build Coastguard Worker 		return 0;
1643*8b26181fSAndroid Build Coastguard Worker 
1644*8b26181fSAndroid Build Coastguard Worker 	aval0 = child->val[A_ATOM];
1645*8b26181fSAndroid Build Coastguard Worker 	oval0 = child->oval;
1646*8b26181fSAndroid Build Coastguard Worker 	aval1 = ep->pred->val[A_ATOM];
1647*8b26181fSAndroid Build Coastguard Worker 	oval1 = ep->pred->oval;
1648*8b26181fSAndroid Build Coastguard Worker 
1649*8b26181fSAndroid Build Coastguard Worker 	/*
1650*8b26181fSAndroid Build Coastguard Worker 	 * If the A register value on exit from the successor block
1651*8b26181fSAndroid Build Coastguard Worker 	 * isn't the same as the A register value on exit from the
1652*8b26181fSAndroid Build Coastguard Worker 	 * predecessor of the edge, the blocks to which the first
1653*8b26181fSAndroid Build Coastguard Worker 	 * block branches aren't candidates to replace the successor
1654*8b26181fSAndroid Build Coastguard Worker 	 * of the edge.
1655*8b26181fSAndroid Build Coastguard Worker 	 */
1656*8b26181fSAndroid Build Coastguard Worker 	if (aval0 != aval1)
1657*8b26181fSAndroid Build Coastguard Worker 		return 0;
1658*8b26181fSAndroid Build Coastguard Worker 
1659*8b26181fSAndroid Build Coastguard Worker 	if (oval0 == oval1)
1660*8b26181fSAndroid Build Coastguard Worker 		/*
1661*8b26181fSAndroid Build Coastguard Worker 		 * The operands of the branch instructions are
1662*8b26181fSAndroid Build Coastguard Worker 		 * identical, so the branches are testing the
1663*8b26181fSAndroid Build Coastguard Worker 		 * same condition, and the result is true if a true
1664*8b26181fSAndroid Build Coastguard Worker 		 * branch was taken to get here, otherwise false.
1665*8b26181fSAndroid Build Coastguard Worker 		 */
1666*8b26181fSAndroid Build Coastguard Worker 		return sense ? JT(child) : JF(child);
1667*8b26181fSAndroid Build Coastguard Worker 
1668*8b26181fSAndroid Build Coastguard Worker 	if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K))
1669*8b26181fSAndroid Build Coastguard Worker 		/*
1670*8b26181fSAndroid Build Coastguard Worker 		 * At this point, we only know the comparison if we
1671*8b26181fSAndroid Build Coastguard Worker 		 * came down the true branch, and it was an equality
1672*8b26181fSAndroid Build Coastguard Worker 		 * comparison with a constant.
1673*8b26181fSAndroid Build Coastguard Worker 		 *
1674*8b26181fSAndroid Build Coastguard Worker 		 * I.e., if we came down the true branch, and the branch
1675*8b26181fSAndroid Build Coastguard Worker 		 * was an equality comparison with a constant, we know the
1676*8b26181fSAndroid Build Coastguard Worker 		 * accumulator contains that constant.  If we came down
1677*8b26181fSAndroid Build Coastguard Worker 		 * the false branch, or the comparison wasn't with a
1678*8b26181fSAndroid Build Coastguard Worker 		 * constant, we don't know what was in the accumulator.
1679*8b26181fSAndroid Build Coastguard Worker 		 *
1680*8b26181fSAndroid Build Coastguard Worker 		 * We rely on the fact that distinct constants have distinct
1681*8b26181fSAndroid Build Coastguard Worker 		 * value numbers.
1682*8b26181fSAndroid Build Coastguard Worker 		 */
1683*8b26181fSAndroid Build Coastguard Worker 		return JF(child);
1684*8b26181fSAndroid Build Coastguard Worker 
1685*8b26181fSAndroid Build Coastguard Worker 	return 0;
1686*8b26181fSAndroid Build Coastguard Worker }
1687*8b26181fSAndroid Build Coastguard Worker 
1688*8b26181fSAndroid Build Coastguard Worker /*
1689*8b26181fSAndroid Build Coastguard Worker  * If we can make this edge go directly to a child of the edge's current
1690*8b26181fSAndroid Build Coastguard Worker  * successor, do so.
1691*8b26181fSAndroid Build Coastguard Worker  */
1692*8b26181fSAndroid Build Coastguard Worker static void
opt_j(opt_state_t * opt_state,struct edge * ep)1693*8b26181fSAndroid Build Coastguard Worker opt_j(opt_state_t *opt_state, struct edge *ep)
1694*8b26181fSAndroid Build Coastguard Worker {
1695*8b26181fSAndroid Build Coastguard Worker 	register u_int i, k;
1696*8b26181fSAndroid Build Coastguard Worker 	register struct block *target;
1697*8b26181fSAndroid Build Coastguard Worker 
1698*8b26181fSAndroid Build Coastguard Worker 	/*
1699*8b26181fSAndroid Build Coastguard Worker 	 * Does this edge go to a block where, if the test
1700*8b26181fSAndroid Build Coastguard Worker 	 * at the end of it succeeds, it goes to a block
1701*8b26181fSAndroid Build Coastguard Worker 	 * that's a leaf node of the DAG, i.e. a return
1702*8b26181fSAndroid Build Coastguard Worker 	 * statement?
1703*8b26181fSAndroid Build Coastguard Worker 	 * If so, there's nothing to optimize.
1704*8b26181fSAndroid Build Coastguard Worker 	 */
1705*8b26181fSAndroid Build Coastguard Worker 	if (JT(ep->succ) == 0)
1706*8b26181fSAndroid Build Coastguard Worker 		return;
1707*8b26181fSAndroid Build Coastguard Worker 
1708*8b26181fSAndroid Build Coastguard Worker 	/*
1709*8b26181fSAndroid Build Coastguard Worker 	 * Does this edge go to a block that goes, in turn, to
1710*8b26181fSAndroid Build Coastguard Worker 	 * the same block regardless of whether the test at the
1711*8b26181fSAndroid Build Coastguard Worker 	 * end succeeds or fails?
1712*8b26181fSAndroid Build Coastguard Worker 	 */
1713*8b26181fSAndroid Build Coastguard Worker 	if (JT(ep->succ) == JF(ep->succ)) {
1714*8b26181fSAndroid Build Coastguard Worker 		/*
1715*8b26181fSAndroid Build Coastguard Worker 		 * Common branch targets can be eliminated, provided
1716*8b26181fSAndroid Build Coastguard Worker 		 * there is no data dependency.
1717*8b26181fSAndroid Build Coastguard Worker 		 *
1718*8b26181fSAndroid Build Coastguard Worker 		 * Check whether any register used on exit from the
1719*8b26181fSAndroid Build Coastguard Worker 		 * block to which the successor of this edge goes
1720*8b26181fSAndroid Build Coastguard Worker 		 * has a value at that point that's different from
1721*8b26181fSAndroid Build Coastguard Worker 		 * the value it has on exit from the predecessor of
1722*8b26181fSAndroid Build Coastguard Worker 		 * this edge.  If not, the predecessor of this edge
1723*8b26181fSAndroid Build Coastguard Worker 		 * can just go to the block to which the successor
1724*8b26181fSAndroid Build Coastguard Worker 		 * of this edge goes, bypassing the successor of this
1725*8b26181fSAndroid Build Coastguard Worker 		 * edge, as the successor of this edge isn't doing
1726*8b26181fSAndroid Build Coastguard Worker 		 * any calculations whose results are different
1727*8b26181fSAndroid Build Coastguard Worker 		 * from what the blocks before it did and isn't
1728*8b26181fSAndroid Build Coastguard Worker 		 * doing any tests the results of which matter.
1729*8b26181fSAndroid Build Coastguard Worker 		 */
1730*8b26181fSAndroid Build Coastguard Worker 		if (!use_conflict(ep->pred, JT(ep->succ))) {
1731*8b26181fSAndroid Build Coastguard Worker 			/*
1732*8b26181fSAndroid Build Coastguard Worker 			 * No, there isn't.
1733*8b26181fSAndroid Build Coastguard Worker 			 * Make this edge go to the block to
1734*8b26181fSAndroid Build Coastguard Worker 			 * which the successor of that edge
1735*8b26181fSAndroid Build Coastguard Worker 			 * goes.
1736*8b26181fSAndroid Build Coastguard Worker 			 *
1737*8b26181fSAndroid Build Coastguard Worker 			 * XXX - optimizer loop detection.
1738*8b26181fSAndroid Build Coastguard Worker 			 */
1739*8b26181fSAndroid Build Coastguard Worker 			opt_state->non_branch_movement_performed = 1;
1740*8b26181fSAndroid Build Coastguard Worker 			opt_state->done = 0;
1741*8b26181fSAndroid Build Coastguard Worker 			ep->succ = JT(ep->succ);
1742*8b26181fSAndroid Build Coastguard Worker 		}
1743*8b26181fSAndroid Build Coastguard Worker 	}
1744*8b26181fSAndroid Build Coastguard Worker 	/*
1745*8b26181fSAndroid Build Coastguard Worker 	 * For each edge dominator that matches the successor of this
1746*8b26181fSAndroid Build Coastguard Worker 	 * edge, promote the edge successor to the its grandchild.
1747*8b26181fSAndroid Build Coastguard Worker 	 *
1748*8b26181fSAndroid Build Coastguard Worker 	 * XXX We violate the set abstraction here in favor a reasonably
1749*8b26181fSAndroid Build Coastguard Worker 	 * efficient loop.
1750*8b26181fSAndroid Build Coastguard Worker 	 */
1751*8b26181fSAndroid Build Coastguard Worker  top:
1752*8b26181fSAndroid Build Coastguard Worker 	for (i = 0; i < opt_state->edgewords; ++i) {
1753*8b26181fSAndroid Build Coastguard Worker 		/* i'th word in the bitset of dominators */
1754*8b26181fSAndroid Build Coastguard Worker 		register bpf_u_int32 x = ep->edom[i];
1755*8b26181fSAndroid Build Coastguard Worker 
1756*8b26181fSAndroid Build Coastguard Worker 		while (x != 0) {
1757*8b26181fSAndroid Build Coastguard Worker 			/* Find the next dominator in that word and mark it as found */
1758*8b26181fSAndroid Build Coastguard Worker 			k = lowest_set_bit(x);
1759*8b26181fSAndroid Build Coastguard Worker 			x &=~ ((bpf_u_int32)1 << k);
1760*8b26181fSAndroid Build Coastguard Worker 			k += i * BITS_PER_WORD;
1761*8b26181fSAndroid Build Coastguard Worker 
1762*8b26181fSAndroid Build Coastguard Worker 			target = fold_edge(ep->succ, opt_state->edges[k]);
1763*8b26181fSAndroid Build Coastguard Worker 			/*
1764*8b26181fSAndroid Build Coastguard Worker 			 * We have a candidate to replace the successor
1765*8b26181fSAndroid Build Coastguard Worker 			 * of ep.
1766*8b26181fSAndroid Build Coastguard Worker 			 *
1767*8b26181fSAndroid Build Coastguard Worker 			 * Check that there is no data dependency between
1768*8b26181fSAndroid Build Coastguard Worker 			 * nodes that will be violated if we move the edge;
1769*8b26181fSAndroid Build Coastguard Worker 			 * i.e., if any register used on exit from the
1770*8b26181fSAndroid Build Coastguard Worker 			 * candidate has a value at that point different
1771*8b26181fSAndroid Build Coastguard Worker 			 * from the value it has when we exit the
1772*8b26181fSAndroid Build Coastguard Worker 			 * predecessor of that edge, there's a data
1773*8b26181fSAndroid Build Coastguard Worker 			 * dependency that will be violated.
1774*8b26181fSAndroid Build Coastguard Worker 			 */
1775*8b26181fSAndroid Build Coastguard Worker 			if (target != 0 && !use_conflict(ep->pred, target)) {
1776*8b26181fSAndroid Build Coastguard Worker 				/*
1777*8b26181fSAndroid Build Coastguard Worker 				 * It's safe to replace the successor of
1778*8b26181fSAndroid Build Coastguard Worker 				 * ep; do so, and note that we've made
1779*8b26181fSAndroid Build Coastguard Worker 				 * at least one change.
1780*8b26181fSAndroid Build Coastguard Worker 				 *
1781*8b26181fSAndroid Build Coastguard Worker 				 * XXX - this is one of the operations that
1782*8b26181fSAndroid Build Coastguard Worker 				 * happens when the optimizer gets into
1783*8b26181fSAndroid Build Coastguard Worker 				 * one of those infinite loops.
1784*8b26181fSAndroid Build Coastguard Worker 				 */
1785*8b26181fSAndroid Build Coastguard Worker 				opt_state->done = 0;
1786*8b26181fSAndroid Build Coastguard Worker 				ep->succ = target;
1787*8b26181fSAndroid Build Coastguard Worker 				if (JT(target) != 0)
1788*8b26181fSAndroid Build Coastguard Worker 					/*
1789*8b26181fSAndroid Build Coastguard Worker 					 * Start over unless we hit a leaf.
1790*8b26181fSAndroid Build Coastguard Worker 					 */
1791*8b26181fSAndroid Build Coastguard Worker 					goto top;
1792*8b26181fSAndroid Build Coastguard Worker 				return;
1793*8b26181fSAndroid Build Coastguard Worker 			}
1794*8b26181fSAndroid Build Coastguard Worker 		}
1795*8b26181fSAndroid Build Coastguard Worker 	}
1796*8b26181fSAndroid Build Coastguard Worker }
1797*8b26181fSAndroid Build Coastguard Worker 
1798*8b26181fSAndroid Build Coastguard Worker /*
1799*8b26181fSAndroid Build Coastguard Worker  * XXX - is this, and and_pullup(), what's described in section 6.1.2
1800*8b26181fSAndroid Build Coastguard Worker  * "Predicate Assertion Propagation" in the BPF+ paper?
1801*8b26181fSAndroid Build Coastguard Worker  *
1802*8b26181fSAndroid Build Coastguard Worker  * Note that this looks at block dominators, not edge dominators.
1803*8b26181fSAndroid Build Coastguard Worker  * Don't think so.
1804*8b26181fSAndroid Build Coastguard Worker  *
1805*8b26181fSAndroid Build Coastguard Worker  * "A or B" compiles into
1806*8b26181fSAndroid Build Coastguard Worker  *
1807*8b26181fSAndroid Build Coastguard Worker  *          A
1808*8b26181fSAndroid Build Coastguard Worker  *       t / \ f
1809*8b26181fSAndroid Build Coastguard Worker  *        /   B
1810*8b26181fSAndroid Build Coastguard Worker  *       / t / \ f
1811*8b26181fSAndroid Build Coastguard Worker  *      \   /
1812*8b26181fSAndroid Build Coastguard Worker  *       \ /
1813*8b26181fSAndroid Build Coastguard Worker  *        X
1814*8b26181fSAndroid Build Coastguard Worker  *
1815*8b26181fSAndroid Build Coastguard Worker  *
1816*8b26181fSAndroid Build Coastguard Worker  */
1817*8b26181fSAndroid Build Coastguard Worker static void
or_pullup(opt_state_t * opt_state,struct block * b)1818*8b26181fSAndroid Build Coastguard Worker or_pullup(opt_state_t *opt_state, struct block *b)
1819*8b26181fSAndroid Build Coastguard Worker {
1820*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 val;
1821*8b26181fSAndroid Build Coastguard Worker 	int at_top;
1822*8b26181fSAndroid Build Coastguard Worker 	struct block *pull;
1823*8b26181fSAndroid Build Coastguard Worker 	struct block **diffp, **samep;
1824*8b26181fSAndroid Build Coastguard Worker 	struct edge *ep;
1825*8b26181fSAndroid Build Coastguard Worker 
1826*8b26181fSAndroid Build Coastguard Worker 	ep = b->in_edges;
1827*8b26181fSAndroid Build Coastguard Worker 	if (ep == 0)
1828*8b26181fSAndroid Build Coastguard Worker 		return;
1829*8b26181fSAndroid Build Coastguard Worker 
1830*8b26181fSAndroid Build Coastguard Worker 	/*
1831*8b26181fSAndroid Build Coastguard Worker 	 * Make sure each predecessor loads the same value.
1832*8b26181fSAndroid Build Coastguard Worker 	 * XXX why?
1833*8b26181fSAndroid Build Coastguard Worker 	 */
1834*8b26181fSAndroid Build Coastguard Worker 	val = ep->pred->val[A_ATOM];
1835*8b26181fSAndroid Build Coastguard Worker 	for (ep = ep->next; ep != 0; ep = ep->next)
1836*8b26181fSAndroid Build Coastguard Worker 		if (val != ep->pred->val[A_ATOM])
1837*8b26181fSAndroid Build Coastguard Worker 			return;
1838*8b26181fSAndroid Build Coastguard Worker 
1839*8b26181fSAndroid Build Coastguard Worker 	/*
1840*8b26181fSAndroid Build Coastguard Worker 	 * For the first edge in the list of edges coming into this block,
1841*8b26181fSAndroid Build Coastguard Worker 	 * see whether the predecessor of that edge comes here via a true
1842*8b26181fSAndroid Build Coastguard Worker 	 * branch or a false branch.
1843*8b26181fSAndroid Build Coastguard Worker 	 */
1844*8b26181fSAndroid Build Coastguard Worker 	if (JT(b->in_edges->pred) == b)
1845*8b26181fSAndroid Build Coastguard Worker 		diffp = &JT(b->in_edges->pred);	/* jt */
1846*8b26181fSAndroid Build Coastguard Worker 	else
1847*8b26181fSAndroid Build Coastguard Worker 		diffp = &JF(b->in_edges->pred);	/* jf */
1848*8b26181fSAndroid Build Coastguard Worker 
1849*8b26181fSAndroid Build Coastguard Worker 	/*
1850*8b26181fSAndroid Build Coastguard Worker 	 * diffp is a pointer to a pointer to the block.
1851*8b26181fSAndroid Build Coastguard Worker 	 *
1852*8b26181fSAndroid Build Coastguard Worker 	 * Go down the false chain looking as far as you can,
1853*8b26181fSAndroid Build Coastguard Worker 	 * making sure that each jump-compare is doing the
1854*8b26181fSAndroid Build Coastguard Worker 	 * same as the original block.
1855*8b26181fSAndroid Build Coastguard Worker 	 *
1856*8b26181fSAndroid Build Coastguard Worker 	 * If you reach the bottom before you reach a
1857*8b26181fSAndroid Build Coastguard Worker 	 * different jump-compare, just exit.  There's nothing
1858*8b26181fSAndroid Build Coastguard Worker 	 * to do here.  XXX - no, this version is checking for
1859*8b26181fSAndroid Build Coastguard Worker 	 * the value leaving the block; that's from the BPF+
1860*8b26181fSAndroid Build Coastguard Worker 	 * pullup routine.
1861*8b26181fSAndroid Build Coastguard Worker 	 */
1862*8b26181fSAndroid Build Coastguard Worker 	at_top = 1;
1863*8b26181fSAndroid Build Coastguard Worker 	for (;;) {
1864*8b26181fSAndroid Build Coastguard Worker 		/*
1865*8b26181fSAndroid Build Coastguard Worker 		 * Done if that's not going anywhere XXX
1866*8b26181fSAndroid Build Coastguard Worker 		 */
1867*8b26181fSAndroid Build Coastguard Worker 		if (*diffp == 0)
1868*8b26181fSAndroid Build Coastguard Worker 			return;
1869*8b26181fSAndroid Build Coastguard Worker 
1870*8b26181fSAndroid Build Coastguard Worker 		/*
1871*8b26181fSAndroid Build Coastguard Worker 		 * Done if that predecessor blah blah blah isn't
1872*8b26181fSAndroid Build Coastguard Worker 		 * going the same place we're going XXX
1873*8b26181fSAndroid Build Coastguard Worker 		 *
1874*8b26181fSAndroid Build Coastguard Worker 		 * Does the true edge of this block point to the same
1875*8b26181fSAndroid Build Coastguard Worker 		 * location as the true edge of b?
1876*8b26181fSAndroid Build Coastguard Worker 		 */
1877*8b26181fSAndroid Build Coastguard Worker 		if (JT(*diffp) != JT(b))
1878*8b26181fSAndroid Build Coastguard Worker 			return;
1879*8b26181fSAndroid Build Coastguard Worker 
1880*8b26181fSAndroid Build Coastguard Worker 		/*
1881*8b26181fSAndroid Build Coastguard Worker 		 * Done if this node isn't a dominator of that
1882*8b26181fSAndroid Build Coastguard Worker 		 * node blah blah blah XXX
1883*8b26181fSAndroid Build Coastguard Worker 		 *
1884*8b26181fSAndroid Build Coastguard Worker 		 * Does b dominate diffp?
1885*8b26181fSAndroid Build Coastguard Worker 		 */
1886*8b26181fSAndroid Build Coastguard Worker 		if (!SET_MEMBER((*diffp)->dom, b->id))
1887*8b26181fSAndroid Build Coastguard Worker 			return;
1888*8b26181fSAndroid Build Coastguard Worker 
1889*8b26181fSAndroid Build Coastguard Worker 		/*
1890*8b26181fSAndroid Build Coastguard Worker 		 * Break out of the loop if that node's value of A
1891*8b26181fSAndroid Build Coastguard Worker 		 * isn't the value of A above XXX
1892*8b26181fSAndroid Build Coastguard Worker 		 */
1893*8b26181fSAndroid Build Coastguard Worker 		if ((*diffp)->val[A_ATOM] != val)
1894*8b26181fSAndroid Build Coastguard Worker 			break;
1895*8b26181fSAndroid Build Coastguard Worker 
1896*8b26181fSAndroid Build Coastguard Worker 		/*
1897*8b26181fSAndroid Build Coastguard Worker 		 * Get the JF for that node XXX
1898*8b26181fSAndroid Build Coastguard Worker 		 * Go down the false path.
1899*8b26181fSAndroid Build Coastguard Worker 		 */
1900*8b26181fSAndroid Build Coastguard Worker 		diffp = &JF(*diffp);
1901*8b26181fSAndroid Build Coastguard Worker 		at_top = 0;
1902*8b26181fSAndroid Build Coastguard Worker 	}
1903*8b26181fSAndroid Build Coastguard Worker 
1904*8b26181fSAndroid Build Coastguard Worker 	/*
1905*8b26181fSAndroid Build Coastguard Worker 	 * Now that we've found a different jump-compare in a chain
1906*8b26181fSAndroid Build Coastguard Worker 	 * below b, search further down until we find another
1907*8b26181fSAndroid Build Coastguard Worker 	 * jump-compare that looks at the original value.  This
1908*8b26181fSAndroid Build Coastguard Worker 	 * jump-compare should get pulled up.  XXX again we're
1909*8b26181fSAndroid Build Coastguard Worker 	 * comparing values not jump-compares.
1910*8b26181fSAndroid Build Coastguard Worker 	 */
1911*8b26181fSAndroid Build Coastguard Worker 	samep = &JF(*diffp);
1912*8b26181fSAndroid Build Coastguard Worker 	for (;;) {
1913*8b26181fSAndroid Build Coastguard Worker 		/*
1914*8b26181fSAndroid Build Coastguard Worker 		 * Done if that's not going anywhere XXX
1915*8b26181fSAndroid Build Coastguard Worker 		 */
1916*8b26181fSAndroid Build Coastguard Worker 		if (*samep == 0)
1917*8b26181fSAndroid Build Coastguard Worker 			return;
1918*8b26181fSAndroid Build Coastguard Worker 
1919*8b26181fSAndroid Build Coastguard Worker 		/*
1920*8b26181fSAndroid Build Coastguard Worker 		 * Done if that predecessor blah blah blah isn't
1921*8b26181fSAndroid Build Coastguard Worker 		 * going the same place we're going XXX
1922*8b26181fSAndroid Build Coastguard Worker 		 */
1923*8b26181fSAndroid Build Coastguard Worker 		if (JT(*samep) != JT(b))
1924*8b26181fSAndroid Build Coastguard Worker 			return;
1925*8b26181fSAndroid Build Coastguard Worker 
1926*8b26181fSAndroid Build Coastguard Worker 		/*
1927*8b26181fSAndroid Build Coastguard Worker 		 * Done if this node isn't a dominator of that
1928*8b26181fSAndroid Build Coastguard Worker 		 * node blah blah blah XXX
1929*8b26181fSAndroid Build Coastguard Worker 		 *
1930*8b26181fSAndroid Build Coastguard Worker 		 * Does b dominate samep?
1931*8b26181fSAndroid Build Coastguard Worker 		 */
1932*8b26181fSAndroid Build Coastguard Worker 		if (!SET_MEMBER((*samep)->dom, b->id))
1933*8b26181fSAndroid Build Coastguard Worker 			return;
1934*8b26181fSAndroid Build Coastguard Worker 
1935*8b26181fSAndroid Build Coastguard Worker 		/*
1936*8b26181fSAndroid Build Coastguard Worker 		 * Break out of the loop if that node's value of A
1937*8b26181fSAndroid Build Coastguard Worker 		 * is the value of A above XXX
1938*8b26181fSAndroid Build Coastguard Worker 		 */
1939*8b26181fSAndroid Build Coastguard Worker 		if ((*samep)->val[A_ATOM] == val)
1940*8b26181fSAndroid Build Coastguard Worker 			break;
1941*8b26181fSAndroid Build Coastguard Worker 
1942*8b26181fSAndroid Build Coastguard Worker 		/* XXX Need to check that there are no data dependencies
1943*8b26181fSAndroid Build Coastguard Worker 		   between dp0 and dp1.  Currently, the code generator
1944*8b26181fSAndroid Build Coastguard Worker 		   will not produce such dependencies. */
1945*8b26181fSAndroid Build Coastguard Worker 		samep = &JF(*samep);
1946*8b26181fSAndroid Build Coastguard Worker 	}
1947*8b26181fSAndroid Build Coastguard Worker #ifdef notdef
1948*8b26181fSAndroid Build Coastguard Worker 	/* XXX This doesn't cover everything. */
1949*8b26181fSAndroid Build Coastguard Worker 	for (i = 0; i < N_ATOMS; ++i)
1950*8b26181fSAndroid Build Coastguard Worker 		if ((*samep)->val[i] != pred->val[i])
1951*8b26181fSAndroid Build Coastguard Worker 			return;
1952*8b26181fSAndroid Build Coastguard Worker #endif
1953*8b26181fSAndroid Build Coastguard Worker 	/* Pull up the node. */
1954*8b26181fSAndroid Build Coastguard Worker 	pull = *samep;
1955*8b26181fSAndroid Build Coastguard Worker 	*samep = JF(pull);
1956*8b26181fSAndroid Build Coastguard Worker 	JF(pull) = *diffp;
1957*8b26181fSAndroid Build Coastguard Worker 
1958*8b26181fSAndroid Build Coastguard Worker 	/*
1959*8b26181fSAndroid Build Coastguard Worker 	 * At the top of the chain, each predecessor needs to point at the
1960*8b26181fSAndroid Build Coastguard Worker 	 * pulled up node.  Inside the chain, there is only one predecessor
1961*8b26181fSAndroid Build Coastguard Worker 	 * to worry about.
1962*8b26181fSAndroid Build Coastguard Worker 	 */
1963*8b26181fSAndroid Build Coastguard Worker 	if (at_top) {
1964*8b26181fSAndroid Build Coastguard Worker 		for (ep = b->in_edges; ep != 0; ep = ep->next) {
1965*8b26181fSAndroid Build Coastguard Worker 			if (JT(ep->pred) == b)
1966*8b26181fSAndroid Build Coastguard Worker 				JT(ep->pred) = pull;
1967*8b26181fSAndroid Build Coastguard Worker 			else
1968*8b26181fSAndroid Build Coastguard Worker 				JF(ep->pred) = pull;
1969*8b26181fSAndroid Build Coastguard Worker 		}
1970*8b26181fSAndroid Build Coastguard Worker 	}
1971*8b26181fSAndroid Build Coastguard Worker 	else
1972*8b26181fSAndroid Build Coastguard Worker 		*diffp = pull;
1973*8b26181fSAndroid Build Coastguard Worker 
1974*8b26181fSAndroid Build Coastguard Worker 	/*
1975*8b26181fSAndroid Build Coastguard Worker 	 * XXX - this is one of the operations that happens when the
1976*8b26181fSAndroid Build Coastguard Worker 	 * optimizer gets into one of those infinite loops.
1977*8b26181fSAndroid Build Coastguard Worker 	 */
1978*8b26181fSAndroid Build Coastguard Worker 	opt_state->done = 0;
1979*8b26181fSAndroid Build Coastguard Worker }
1980*8b26181fSAndroid Build Coastguard Worker 
1981*8b26181fSAndroid Build Coastguard Worker static void
and_pullup(opt_state_t * opt_state,struct block * b)1982*8b26181fSAndroid Build Coastguard Worker and_pullup(opt_state_t *opt_state, struct block *b)
1983*8b26181fSAndroid Build Coastguard Worker {
1984*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 val;
1985*8b26181fSAndroid Build Coastguard Worker 	int at_top;
1986*8b26181fSAndroid Build Coastguard Worker 	struct block *pull;
1987*8b26181fSAndroid Build Coastguard Worker 	struct block **diffp, **samep;
1988*8b26181fSAndroid Build Coastguard Worker 	struct edge *ep;
1989*8b26181fSAndroid Build Coastguard Worker 
1990*8b26181fSAndroid Build Coastguard Worker 	ep = b->in_edges;
1991*8b26181fSAndroid Build Coastguard Worker 	if (ep == 0)
1992*8b26181fSAndroid Build Coastguard Worker 		return;
1993*8b26181fSAndroid Build Coastguard Worker 
1994*8b26181fSAndroid Build Coastguard Worker 	/*
1995*8b26181fSAndroid Build Coastguard Worker 	 * Make sure each predecessor loads the same value.
1996*8b26181fSAndroid Build Coastguard Worker 	 */
1997*8b26181fSAndroid Build Coastguard Worker 	val = ep->pred->val[A_ATOM];
1998*8b26181fSAndroid Build Coastguard Worker 	for (ep = ep->next; ep != 0; ep = ep->next)
1999*8b26181fSAndroid Build Coastguard Worker 		if (val != ep->pred->val[A_ATOM])
2000*8b26181fSAndroid Build Coastguard Worker 			return;
2001*8b26181fSAndroid Build Coastguard Worker 
2002*8b26181fSAndroid Build Coastguard Worker 	if (JT(b->in_edges->pred) == b)
2003*8b26181fSAndroid Build Coastguard Worker 		diffp = &JT(b->in_edges->pred);
2004*8b26181fSAndroid Build Coastguard Worker 	else
2005*8b26181fSAndroid Build Coastguard Worker 		diffp = &JF(b->in_edges->pred);
2006*8b26181fSAndroid Build Coastguard Worker 
2007*8b26181fSAndroid Build Coastguard Worker 	at_top = 1;
2008*8b26181fSAndroid Build Coastguard Worker 	for (;;) {
2009*8b26181fSAndroid Build Coastguard Worker 		if (*diffp == 0)
2010*8b26181fSAndroid Build Coastguard Worker 			return;
2011*8b26181fSAndroid Build Coastguard Worker 
2012*8b26181fSAndroid Build Coastguard Worker 		if (JF(*diffp) != JF(b))
2013*8b26181fSAndroid Build Coastguard Worker 			return;
2014*8b26181fSAndroid Build Coastguard Worker 
2015*8b26181fSAndroid Build Coastguard Worker 		if (!SET_MEMBER((*diffp)->dom, b->id))
2016*8b26181fSAndroid Build Coastguard Worker 			return;
2017*8b26181fSAndroid Build Coastguard Worker 
2018*8b26181fSAndroid Build Coastguard Worker 		if ((*diffp)->val[A_ATOM] != val)
2019*8b26181fSAndroid Build Coastguard Worker 			break;
2020*8b26181fSAndroid Build Coastguard Worker 
2021*8b26181fSAndroid Build Coastguard Worker 		diffp = &JT(*diffp);
2022*8b26181fSAndroid Build Coastguard Worker 		at_top = 0;
2023*8b26181fSAndroid Build Coastguard Worker 	}
2024*8b26181fSAndroid Build Coastguard Worker 	samep = &JT(*diffp);
2025*8b26181fSAndroid Build Coastguard Worker 	for (;;) {
2026*8b26181fSAndroid Build Coastguard Worker 		if (*samep == 0)
2027*8b26181fSAndroid Build Coastguard Worker 			return;
2028*8b26181fSAndroid Build Coastguard Worker 
2029*8b26181fSAndroid Build Coastguard Worker 		if (JF(*samep) != JF(b))
2030*8b26181fSAndroid Build Coastguard Worker 			return;
2031*8b26181fSAndroid Build Coastguard Worker 
2032*8b26181fSAndroid Build Coastguard Worker 		if (!SET_MEMBER((*samep)->dom, b->id))
2033*8b26181fSAndroid Build Coastguard Worker 			return;
2034*8b26181fSAndroid Build Coastguard Worker 
2035*8b26181fSAndroid Build Coastguard Worker 		if ((*samep)->val[A_ATOM] == val)
2036*8b26181fSAndroid Build Coastguard Worker 			break;
2037*8b26181fSAndroid Build Coastguard Worker 
2038*8b26181fSAndroid Build Coastguard Worker 		/* XXX Need to check that there are no data dependencies
2039*8b26181fSAndroid Build Coastguard Worker 		   between diffp and samep.  Currently, the code generator
2040*8b26181fSAndroid Build Coastguard Worker 		   will not produce such dependencies. */
2041*8b26181fSAndroid Build Coastguard Worker 		samep = &JT(*samep);
2042*8b26181fSAndroid Build Coastguard Worker 	}
2043*8b26181fSAndroid Build Coastguard Worker #ifdef notdef
2044*8b26181fSAndroid Build Coastguard Worker 	/* XXX This doesn't cover everything. */
2045*8b26181fSAndroid Build Coastguard Worker 	for (i = 0; i < N_ATOMS; ++i)
2046*8b26181fSAndroid Build Coastguard Worker 		if ((*samep)->val[i] != pred->val[i])
2047*8b26181fSAndroid Build Coastguard Worker 			return;
2048*8b26181fSAndroid Build Coastguard Worker #endif
2049*8b26181fSAndroid Build Coastguard Worker 	/* Pull up the node. */
2050*8b26181fSAndroid Build Coastguard Worker 	pull = *samep;
2051*8b26181fSAndroid Build Coastguard Worker 	*samep = JT(pull);
2052*8b26181fSAndroid Build Coastguard Worker 	JT(pull) = *diffp;
2053*8b26181fSAndroid Build Coastguard Worker 
2054*8b26181fSAndroid Build Coastguard Worker 	/*
2055*8b26181fSAndroid Build Coastguard Worker 	 * At the top of the chain, each predecessor needs to point at the
2056*8b26181fSAndroid Build Coastguard Worker 	 * pulled up node.  Inside the chain, there is only one predecessor
2057*8b26181fSAndroid Build Coastguard Worker 	 * to worry about.
2058*8b26181fSAndroid Build Coastguard Worker 	 */
2059*8b26181fSAndroid Build Coastguard Worker 	if (at_top) {
2060*8b26181fSAndroid Build Coastguard Worker 		for (ep = b->in_edges; ep != 0; ep = ep->next) {
2061*8b26181fSAndroid Build Coastguard Worker 			if (JT(ep->pred) == b)
2062*8b26181fSAndroid Build Coastguard Worker 				JT(ep->pred) = pull;
2063*8b26181fSAndroid Build Coastguard Worker 			else
2064*8b26181fSAndroid Build Coastguard Worker 				JF(ep->pred) = pull;
2065*8b26181fSAndroid Build Coastguard Worker 		}
2066*8b26181fSAndroid Build Coastguard Worker 	}
2067*8b26181fSAndroid Build Coastguard Worker 	else
2068*8b26181fSAndroid Build Coastguard Worker 		*diffp = pull;
2069*8b26181fSAndroid Build Coastguard Worker 
2070*8b26181fSAndroid Build Coastguard Worker 	/*
2071*8b26181fSAndroid Build Coastguard Worker 	 * XXX - this is one of the operations that happens when the
2072*8b26181fSAndroid Build Coastguard Worker 	 * optimizer gets into one of those infinite loops.
2073*8b26181fSAndroid Build Coastguard Worker 	 */
2074*8b26181fSAndroid Build Coastguard Worker 	opt_state->done = 0;
2075*8b26181fSAndroid Build Coastguard Worker }
2076*8b26181fSAndroid Build Coastguard Worker 
2077*8b26181fSAndroid Build Coastguard Worker static void
opt_blks(opt_state_t * opt_state,struct icode * ic,int do_stmts)2078*8b26181fSAndroid Build Coastguard Worker opt_blks(opt_state_t *opt_state, struct icode *ic, int do_stmts)
2079*8b26181fSAndroid Build Coastguard Worker {
2080*8b26181fSAndroid Build Coastguard Worker 	int i, maxlevel;
2081*8b26181fSAndroid Build Coastguard Worker 	struct block *p;
2082*8b26181fSAndroid Build Coastguard Worker 
2083*8b26181fSAndroid Build Coastguard Worker 	init_val(opt_state);
2084*8b26181fSAndroid Build Coastguard Worker 	maxlevel = ic->root->level;
2085*8b26181fSAndroid Build Coastguard Worker 
2086*8b26181fSAndroid Build Coastguard Worker 	find_inedges(opt_state, ic->root);
2087*8b26181fSAndroid Build Coastguard Worker 	for (i = maxlevel; i >= 0; --i)
2088*8b26181fSAndroid Build Coastguard Worker 		for (p = opt_state->levels[i]; p; p = p->link)
2089*8b26181fSAndroid Build Coastguard Worker 			opt_blk(opt_state, p, do_stmts);
2090*8b26181fSAndroid Build Coastguard Worker 
2091*8b26181fSAndroid Build Coastguard Worker 	if (do_stmts)
2092*8b26181fSAndroid Build Coastguard Worker 		/*
2093*8b26181fSAndroid Build Coastguard Worker 		 * No point trying to move branches; it can't possibly
2094*8b26181fSAndroid Build Coastguard Worker 		 * make a difference at this point.
2095*8b26181fSAndroid Build Coastguard Worker 		 *
2096*8b26181fSAndroid Build Coastguard Worker 		 * XXX - this might be after we detect a loop where
2097*8b26181fSAndroid Build Coastguard Worker 		 * we were just looping infinitely moving branches
2098*8b26181fSAndroid Build Coastguard Worker 		 * in such a fashion that we went through two or more
2099*8b26181fSAndroid Build Coastguard Worker 		 * versions of the machine code, eventually returning
2100*8b26181fSAndroid Build Coastguard Worker 		 * to the first version.  (We're really not doing a
2101*8b26181fSAndroid Build Coastguard Worker 		 * full loop detection, we're just testing for two
2102*8b26181fSAndroid Build Coastguard Worker 		 * passes in a row where we do nothing but
2103*8b26181fSAndroid Build Coastguard Worker 		 * move branches.)
2104*8b26181fSAndroid Build Coastguard Worker 		 */
2105*8b26181fSAndroid Build Coastguard Worker 		return;
2106*8b26181fSAndroid Build Coastguard Worker 
2107*8b26181fSAndroid Build Coastguard Worker 	/*
2108*8b26181fSAndroid Build Coastguard Worker 	 * Is this what the BPF+ paper describes in sections 6.1.1,
2109*8b26181fSAndroid Build Coastguard Worker 	 * 6.1.2, and 6.1.3?
2110*8b26181fSAndroid Build Coastguard Worker 	 */
2111*8b26181fSAndroid Build Coastguard Worker 	for (i = 1; i <= maxlevel; ++i) {
2112*8b26181fSAndroid Build Coastguard Worker 		for (p = opt_state->levels[i]; p; p = p->link) {
2113*8b26181fSAndroid Build Coastguard Worker 			opt_j(opt_state, &p->et);
2114*8b26181fSAndroid Build Coastguard Worker 			opt_j(opt_state, &p->ef);
2115*8b26181fSAndroid Build Coastguard Worker 		}
2116*8b26181fSAndroid Build Coastguard Worker 	}
2117*8b26181fSAndroid Build Coastguard Worker 
2118*8b26181fSAndroid Build Coastguard Worker 	find_inedges(opt_state, ic->root);
2119*8b26181fSAndroid Build Coastguard Worker 	for (i = 1; i <= maxlevel; ++i) {
2120*8b26181fSAndroid Build Coastguard Worker 		for (p = opt_state->levels[i]; p; p = p->link) {
2121*8b26181fSAndroid Build Coastguard Worker 			or_pullup(opt_state, p);
2122*8b26181fSAndroid Build Coastguard Worker 			and_pullup(opt_state, p);
2123*8b26181fSAndroid Build Coastguard Worker 		}
2124*8b26181fSAndroid Build Coastguard Worker 	}
2125*8b26181fSAndroid Build Coastguard Worker }
2126*8b26181fSAndroid Build Coastguard Worker 
2127*8b26181fSAndroid Build Coastguard Worker static inline void
link_inedge(struct edge * parent,struct block * child)2128*8b26181fSAndroid Build Coastguard Worker link_inedge(struct edge *parent, struct block *child)
2129*8b26181fSAndroid Build Coastguard Worker {
2130*8b26181fSAndroid Build Coastguard Worker 	parent->next = child->in_edges;
2131*8b26181fSAndroid Build Coastguard Worker 	child->in_edges = parent;
2132*8b26181fSAndroid Build Coastguard Worker }
2133*8b26181fSAndroid Build Coastguard Worker 
2134*8b26181fSAndroid Build Coastguard Worker static void
find_inedges(opt_state_t * opt_state,struct block * root)2135*8b26181fSAndroid Build Coastguard Worker find_inedges(opt_state_t *opt_state, struct block *root)
2136*8b26181fSAndroid Build Coastguard Worker {
2137*8b26181fSAndroid Build Coastguard Worker 	u_int i;
2138*8b26181fSAndroid Build Coastguard Worker 	int level;
2139*8b26181fSAndroid Build Coastguard Worker 	struct block *b;
2140*8b26181fSAndroid Build Coastguard Worker 
2141*8b26181fSAndroid Build Coastguard Worker 	for (i = 0; i < opt_state->n_blocks; ++i)
2142*8b26181fSAndroid Build Coastguard Worker 		opt_state->blocks[i]->in_edges = 0;
2143*8b26181fSAndroid Build Coastguard Worker 
2144*8b26181fSAndroid Build Coastguard Worker 	/*
2145*8b26181fSAndroid Build Coastguard Worker 	 * Traverse the graph, adding each edge to the predecessor
2146*8b26181fSAndroid Build Coastguard Worker 	 * list of its successors.  Skip the leaves (i.e. level 0).
2147*8b26181fSAndroid Build Coastguard Worker 	 */
2148*8b26181fSAndroid Build Coastguard Worker 	for (level = root->level; level > 0; --level) {
2149*8b26181fSAndroid Build Coastguard Worker 		for (b = opt_state->levels[level]; b != 0; b = b->link) {
2150*8b26181fSAndroid Build Coastguard Worker 			link_inedge(&b->et, JT(b));
2151*8b26181fSAndroid Build Coastguard Worker 			link_inedge(&b->ef, JF(b));
2152*8b26181fSAndroid Build Coastguard Worker 		}
2153*8b26181fSAndroid Build Coastguard Worker 	}
2154*8b26181fSAndroid Build Coastguard Worker }
2155*8b26181fSAndroid Build Coastguard Worker 
2156*8b26181fSAndroid Build Coastguard Worker static void
opt_root(struct block ** b)2157*8b26181fSAndroid Build Coastguard Worker opt_root(struct block **b)
2158*8b26181fSAndroid Build Coastguard Worker {
2159*8b26181fSAndroid Build Coastguard Worker 	struct slist *tmp, *s;
2160*8b26181fSAndroid Build Coastguard Worker 
2161*8b26181fSAndroid Build Coastguard Worker 	s = (*b)->stmts;
2162*8b26181fSAndroid Build Coastguard Worker 	(*b)->stmts = 0;
2163*8b26181fSAndroid Build Coastguard Worker 	while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b))
2164*8b26181fSAndroid Build Coastguard Worker 		*b = JT(*b);
2165*8b26181fSAndroid Build Coastguard Worker 
2166*8b26181fSAndroid Build Coastguard Worker 	tmp = (*b)->stmts;
2167*8b26181fSAndroid Build Coastguard Worker 	if (tmp != 0)
2168*8b26181fSAndroid Build Coastguard Worker 		sappend(s, tmp);
2169*8b26181fSAndroid Build Coastguard Worker 	(*b)->stmts = s;
2170*8b26181fSAndroid Build Coastguard Worker 
2171*8b26181fSAndroid Build Coastguard Worker 	/*
2172*8b26181fSAndroid Build Coastguard Worker 	 * If the root node is a return, then there is no
2173*8b26181fSAndroid Build Coastguard Worker 	 * point executing any statements (since the bpf machine
2174*8b26181fSAndroid Build Coastguard Worker 	 * has no side effects).
2175*8b26181fSAndroid Build Coastguard Worker 	 */
2176*8b26181fSAndroid Build Coastguard Worker 	if (BPF_CLASS((*b)->s.code) == BPF_RET)
2177*8b26181fSAndroid Build Coastguard Worker 		(*b)->stmts = 0;
2178*8b26181fSAndroid Build Coastguard Worker }
2179*8b26181fSAndroid Build Coastguard Worker 
2180*8b26181fSAndroid Build Coastguard Worker static void
opt_loop(opt_state_t * opt_state,struct icode * ic,int do_stmts)2181*8b26181fSAndroid Build Coastguard Worker opt_loop(opt_state_t *opt_state, struct icode *ic, int do_stmts)
2182*8b26181fSAndroid Build Coastguard Worker {
2183*8b26181fSAndroid Build Coastguard Worker 
2184*8b26181fSAndroid Build Coastguard Worker #ifdef BDEBUG
2185*8b26181fSAndroid Build Coastguard Worker 	if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
2186*8b26181fSAndroid Build Coastguard Worker 		printf("opt_loop(root, %d) begin\n", do_stmts);
2187*8b26181fSAndroid Build Coastguard Worker 		opt_dump(opt_state, ic);
2188*8b26181fSAndroid Build Coastguard Worker 	}
2189*8b26181fSAndroid Build Coastguard Worker #endif
2190*8b26181fSAndroid Build Coastguard Worker 
2191*8b26181fSAndroid Build Coastguard Worker 	/*
2192*8b26181fSAndroid Build Coastguard Worker 	 * XXX - optimizer loop detection.
2193*8b26181fSAndroid Build Coastguard Worker 	 */
2194*8b26181fSAndroid Build Coastguard Worker 	int loop_count = 0;
2195*8b26181fSAndroid Build Coastguard Worker 	for (;;) {
2196*8b26181fSAndroid Build Coastguard Worker 		opt_state->done = 1;
2197*8b26181fSAndroid Build Coastguard Worker 		/*
2198*8b26181fSAndroid Build Coastguard Worker 		 * XXX - optimizer loop detection.
2199*8b26181fSAndroid Build Coastguard Worker 		 */
2200*8b26181fSAndroid Build Coastguard Worker 		opt_state->non_branch_movement_performed = 0;
2201*8b26181fSAndroid Build Coastguard Worker 		find_levels(opt_state, ic);
2202*8b26181fSAndroid Build Coastguard Worker 		find_dom(opt_state, ic->root);
2203*8b26181fSAndroid Build Coastguard Worker 		find_closure(opt_state, ic->root);
2204*8b26181fSAndroid Build Coastguard Worker 		find_ud(opt_state, ic->root);
2205*8b26181fSAndroid Build Coastguard Worker 		find_edom(opt_state, ic->root);
2206*8b26181fSAndroid Build Coastguard Worker 		opt_blks(opt_state, ic, do_stmts);
2207*8b26181fSAndroid Build Coastguard Worker #ifdef BDEBUG
2208*8b26181fSAndroid Build Coastguard Worker 		if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
2209*8b26181fSAndroid Build Coastguard Worker 			printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, opt_state->done);
2210*8b26181fSAndroid Build Coastguard Worker 			opt_dump(opt_state, ic);
2211*8b26181fSAndroid Build Coastguard Worker 		}
2212*8b26181fSAndroid Build Coastguard Worker #endif
2213*8b26181fSAndroid Build Coastguard Worker 
2214*8b26181fSAndroid Build Coastguard Worker 		/*
2215*8b26181fSAndroid Build Coastguard Worker 		 * Was anything done in this optimizer pass?
2216*8b26181fSAndroid Build Coastguard Worker 		 */
2217*8b26181fSAndroid Build Coastguard Worker 		if (opt_state->done) {
2218*8b26181fSAndroid Build Coastguard Worker 			/*
2219*8b26181fSAndroid Build Coastguard Worker 			 * No, so we've reached a fixed point.
2220*8b26181fSAndroid Build Coastguard Worker 			 * We're done.
2221*8b26181fSAndroid Build Coastguard Worker 			 */
2222*8b26181fSAndroid Build Coastguard Worker 			break;
2223*8b26181fSAndroid Build Coastguard Worker 		}
2224*8b26181fSAndroid Build Coastguard Worker 
2225*8b26181fSAndroid Build Coastguard Worker 		/*
2226*8b26181fSAndroid Build Coastguard Worker 		 * XXX - was anything done other than branch movement
2227*8b26181fSAndroid Build Coastguard Worker 		 * in this pass?
2228*8b26181fSAndroid Build Coastguard Worker 		 */
2229*8b26181fSAndroid Build Coastguard Worker 		if (opt_state->non_branch_movement_performed) {
2230*8b26181fSAndroid Build Coastguard Worker 			/*
2231*8b26181fSAndroid Build Coastguard Worker 			 * Yes.  Clear any loop-detection counter;
2232*8b26181fSAndroid Build Coastguard Worker 			 * we're making some form of progress (assuming
2233*8b26181fSAndroid Build Coastguard Worker 			 * we can't get into a cycle doing *other*
2234*8b26181fSAndroid Build Coastguard Worker 			 * optimizations...).
2235*8b26181fSAndroid Build Coastguard Worker 			 */
2236*8b26181fSAndroid Build Coastguard Worker 			loop_count = 0;
2237*8b26181fSAndroid Build Coastguard Worker 		} else {
2238*8b26181fSAndroid Build Coastguard Worker 			/*
2239*8b26181fSAndroid Build Coastguard Worker 			 * No - increment the counter, and quit if
2240*8b26181fSAndroid Build Coastguard Worker 			 * it's up to 100.
2241*8b26181fSAndroid Build Coastguard Worker 			 */
2242*8b26181fSAndroid Build Coastguard Worker 			loop_count++;
2243*8b26181fSAndroid Build Coastguard Worker 			if (loop_count >= 100) {
2244*8b26181fSAndroid Build Coastguard Worker 				/*
2245*8b26181fSAndroid Build Coastguard Worker 				 * We've done nothing but branch movement
2246*8b26181fSAndroid Build Coastguard Worker 				 * for 100 passes; we're probably
2247*8b26181fSAndroid Build Coastguard Worker 				 * in a cycle and will never reach a
2248*8b26181fSAndroid Build Coastguard Worker 				 * fixed point.
2249*8b26181fSAndroid Build Coastguard Worker 				 *
2250*8b26181fSAndroid Build Coastguard Worker 				 * XXX - yes, we really need a non-
2251*8b26181fSAndroid Build Coastguard Worker 				 * heuristic way of detecting a cycle.
2252*8b26181fSAndroid Build Coastguard Worker 				 */
2253*8b26181fSAndroid Build Coastguard Worker 				opt_state->done = 1;
2254*8b26181fSAndroid Build Coastguard Worker 				break;
2255*8b26181fSAndroid Build Coastguard Worker 			}
2256*8b26181fSAndroid Build Coastguard Worker 		}
2257*8b26181fSAndroid Build Coastguard Worker 	}
2258*8b26181fSAndroid Build Coastguard Worker }
2259*8b26181fSAndroid Build Coastguard Worker 
2260*8b26181fSAndroid Build Coastguard Worker /*
2261*8b26181fSAndroid Build Coastguard Worker  * Optimize the filter code in its dag representation.
2262*8b26181fSAndroid Build Coastguard Worker  * Return 0 on success, -1 on error.
2263*8b26181fSAndroid Build Coastguard Worker  */
2264*8b26181fSAndroid Build Coastguard Worker int
bpf_optimize(struct icode * ic,char * errbuf)2265*8b26181fSAndroid Build Coastguard Worker bpf_optimize(struct icode *ic, char *errbuf)
2266*8b26181fSAndroid Build Coastguard Worker {
2267*8b26181fSAndroid Build Coastguard Worker 	opt_state_t opt_state;
2268*8b26181fSAndroid Build Coastguard Worker 
2269*8b26181fSAndroid Build Coastguard Worker 	memset(&opt_state, 0, sizeof(opt_state));
2270*8b26181fSAndroid Build Coastguard Worker 	opt_state.errbuf = errbuf;
2271*8b26181fSAndroid Build Coastguard Worker 	opt_state.non_branch_movement_performed = 0;
2272*8b26181fSAndroid Build Coastguard Worker 	if (setjmp(opt_state.top_ctx)) {
2273*8b26181fSAndroid Build Coastguard Worker 		opt_cleanup(&opt_state);
2274*8b26181fSAndroid Build Coastguard Worker 		return -1;
2275*8b26181fSAndroid Build Coastguard Worker 	}
2276*8b26181fSAndroid Build Coastguard Worker 	opt_init(&opt_state, ic);
2277*8b26181fSAndroid Build Coastguard Worker 	opt_loop(&opt_state, ic, 0);
2278*8b26181fSAndroid Build Coastguard Worker 	opt_loop(&opt_state, ic, 1);
2279*8b26181fSAndroid Build Coastguard Worker 	intern_blocks(&opt_state, ic);
2280*8b26181fSAndroid Build Coastguard Worker #ifdef BDEBUG
2281*8b26181fSAndroid Build Coastguard Worker 	if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
2282*8b26181fSAndroid Build Coastguard Worker 		printf("after intern_blocks()\n");
2283*8b26181fSAndroid Build Coastguard Worker 		opt_dump(&opt_state, ic);
2284*8b26181fSAndroid Build Coastguard Worker 	}
2285*8b26181fSAndroid Build Coastguard Worker #endif
2286*8b26181fSAndroid Build Coastguard Worker 	opt_root(&ic->root);
2287*8b26181fSAndroid Build Coastguard Worker #ifdef BDEBUG
2288*8b26181fSAndroid Build Coastguard Worker 	if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
2289*8b26181fSAndroid Build Coastguard Worker 		printf("after opt_root()\n");
2290*8b26181fSAndroid Build Coastguard Worker 		opt_dump(&opt_state, ic);
2291*8b26181fSAndroid Build Coastguard Worker 	}
2292*8b26181fSAndroid Build Coastguard Worker #endif
2293*8b26181fSAndroid Build Coastguard Worker 	opt_cleanup(&opt_state);
2294*8b26181fSAndroid Build Coastguard Worker 	return 0;
2295*8b26181fSAndroid Build Coastguard Worker }
2296*8b26181fSAndroid Build Coastguard Worker 
2297*8b26181fSAndroid Build Coastguard Worker static void
make_marks(struct icode * ic,struct block * p)2298*8b26181fSAndroid Build Coastguard Worker make_marks(struct icode *ic, struct block *p)
2299*8b26181fSAndroid Build Coastguard Worker {
2300*8b26181fSAndroid Build Coastguard Worker 	if (!isMarked(ic, p)) {
2301*8b26181fSAndroid Build Coastguard Worker 		Mark(ic, p);
2302*8b26181fSAndroid Build Coastguard Worker 		if (BPF_CLASS(p->s.code) != BPF_RET) {
2303*8b26181fSAndroid Build Coastguard Worker 			make_marks(ic, JT(p));
2304*8b26181fSAndroid Build Coastguard Worker 			make_marks(ic, JF(p));
2305*8b26181fSAndroid Build Coastguard Worker 		}
2306*8b26181fSAndroid Build Coastguard Worker 	}
2307*8b26181fSAndroid Build Coastguard Worker }
2308*8b26181fSAndroid Build Coastguard Worker 
2309*8b26181fSAndroid Build Coastguard Worker /*
2310*8b26181fSAndroid Build Coastguard Worker  * Mark code array such that isMarked(ic->cur_mark, i) is true
2311*8b26181fSAndroid Build Coastguard Worker  * only for nodes that are alive.
2312*8b26181fSAndroid Build Coastguard Worker  */
2313*8b26181fSAndroid Build Coastguard Worker static void
mark_code(struct icode * ic)2314*8b26181fSAndroid Build Coastguard Worker mark_code(struct icode *ic)
2315*8b26181fSAndroid Build Coastguard Worker {
2316*8b26181fSAndroid Build Coastguard Worker 	ic->cur_mark += 1;
2317*8b26181fSAndroid Build Coastguard Worker 	make_marks(ic, ic->root);
2318*8b26181fSAndroid Build Coastguard Worker }
2319*8b26181fSAndroid Build Coastguard Worker 
2320*8b26181fSAndroid Build Coastguard Worker /*
2321*8b26181fSAndroid Build Coastguard Worker  * True iff the two stmt lists load the same value from the packet into
2322*8b26181fSAndroid Build Coastguard Worker  * the accumulator.
2323*8b26181fSAndroid Build Coastguard Worker  */
2324*8b26181fSAndroid Build Coastguard Worker static int
eq_slist(struct slist * x,struct slist * y)2325*8b26181fSAndroid Build Coastguard Worker eq_slist(struct slist *x, struct slist *y)
2326*8b26181fSAndroid Build Coastguard Worker {
2327*8b26181fSAndroid Build Coastguard Worker 	for (;;) {
2328*8b26181fSAndroid Build Coastguard Worker 		while (x && x->s.code == NOP)
2329*8b26181fSAndroid Build Coastguard Worker 			x = x->next;
2330*8b26181fSAndroid Build Coastguard Worker 		while (y && y->s.code == NOP)
2331*8b26181fSAndroid Build Coastguard Worker 			y = y->next;
2332*8b26181fSAndroid Build Coastguard Worker 		if (x == 0)
2333*8b26181fSAndroid Build Coastguard Worker 			return y == 0;
2334*8b26181fSAndroid Build Coastguard Worker 		if (y == 0)
2335*8b26181fSAndroid Build Coastguard Worker 			return x == 0;
2336*8b26181fSAndroid Build Coastguard Worker 		if (x->s.code != y->s.code || x->s.k != y->s.k)
2337*8b26181fSAndroid Build Coastguard Worker 			return 0;
2338*8b26181fSAndroid Build Coastguard Worker 		x = x->next;
2339*8b26181fSAndroid Build Coastguard Worker 		y = y->next;
2340*8b26181fSAndroid Build Coastguard Worker 	}
2341*8b26181fSAndroid Build Coastguard Worker }
2342*8b26181fSAndroid Build Coastguard Worker 
2343*8b26181fSAndroid Build Coastguard Worker static inline int
eq_blk(struct block * b0,struct block * b1)2344*8b26181fSAndroid Build Coastguard Worker eq_blk(struct block *b0, struct block *b1)
2345*8b26181fSAndroid Build Coastguard Worker {
2346*8b26181fSAndroid Build Coastguard Worker 	if (b0->s.code == b1->s.code &&
2347*8b26181fSAndroid Build Coastguard Worker 	    b0->s.k == b1->s.k &&
2348*8b26181fSAndroid Build Coastguard Worker 	    b0->et.succ == b1->et.succ &&
2349*8b26181fSAndroid Build Coastguard Worker 	    b0->ef.succ == b1->ef.succ)
2350*8b26181fSAndroid Build Coastguard Worker 		return eq_slist(b0->stmts, b1->stmts);
2351*8b26181fSAndroid Build Coastguard Worker 	return 0;
2352*8b26181fSAndroid Build Coastguard Worker }
2353*8b26181fSAndroid Build Coastguard Worker 
2354*8b26181fSAndroid Build Coastguard Worker static void
intern_blocks(opt_state_t * opt_state,struct icode * ic)2355*8b26181fSAndroid Build Coastguard Worker intern_blocks(opt_state_t *opt_state, struct icode *ic)
2356*8b26181fSAndroid Build Coastguard Worker {
2357*8b26181fSAndroid Build Coastguard Worker 	struct block *p;
2358*8b26181fSAndroid Build Coastguard Worker 	u_int i, j;
2359*8b26181fSAndroid Build Coastguard Worker 	int done1; /* don't shadow global */
2360*8b26181fSAndroid Build Coastguard Worker  top:
2361*8b26181fSAndroid Build Coastguard Worker 	done1 = 1;
2362*8b26181fSAndroid Build Coastguard Worker 	for (i = 0; i < opt_state->n_blocks; ++i)
2363*8b26181fSAndroid Build Coastguard Worker 		opt_state->blocks[i]->link = 0;
2364*8b26181fSAndroid Build Coastguard Worker 
2365*8b26181fSAndroid Build Coastguard Worker 	mark_code(ic);
2366*8b26181fSAndroid Build Coastguard Worker 
2367*8b26181fSAndroid Build Coastguard Worker 	for (i = opt_state->n_blocks - 1; i != 0; ) {
2368*8b26181fSAndroid Build Coastguard Worker 		--i;
2369*8b26181fSAndroid Build Coastguard Worker 		if (!isMarked(ic, opt_state->blocks[i]))
2370*8b26181fSAndroid Build Coastguard Worker 			continue;
2371*8b26181fSAndroid Build Coastguard Worker 		for (j = i + 1; j < opt_state->n_blocks; ++j) {
2372*8b26181fSAndroid Build Coastguard Worker 			if (!isMarked(ic, opt_state->blocks[j]))
2373*8b26181fSAndroid Build Coastguard Worker 				continue;
2374*8b26181fSAndroid Build Coastguard Worker 			if (eq_blk(opt_state->blocks[i], opt_state->blocks[j])) {
2375*8b26181fSAndroid Build Coastguard Worker 				opt_state->blocks[i]->link = opt_state->blocks[j]->link ?
2376*8b26181fSAndroid Build Coastguard Worker 					opt_state->blocks[j]->link : opt_state->blocks[j];
2377*8b26181fSAndroid Build Coastguard Worker 				break;
2378*8b26181fSAndroid Build Coastguard Worker 			}
2379*8b26181fSAndroid Build Coastguard Worker 		}
2380*8b26181fSAndroid Build Coastguard Worker 	}
2381*8b26181fSAndroid Build Coastguard Worker 	for (i = 0; i < opt_state->n_blocks; ++i) {
2382*8b26181fSAndroid Build Coastguard Worker 		p = opt_state->blocks[i];
2383*8b26181fSAndroid Build Coastguard Worker 		if (JT(p) == 0)
2384*8b26181fSAndroid Build Coastguard Worker 			continue;
2385*8b26181fSAndroid Build Coastguard Worker 		if (JT(p)->link) {
2386*8b26181fSAndroid Build Coastguard Worker 			done1 = 0;
2387*8b26181fSAndroid Build Coastguard Worker 			JT(p) = JT(p)->link;
2388*8b26181fSAndroid Build Coastguard Worker 		}
2389*8b26181fSAndroid Build Coastguard Worker 		if (JF(p)->link) {
2390*8b26181fSAndroid Build Coastguard Worker 			done1 = 0;
2391*8b26181fSAndroid Build Coastguard Worker 			JF(p) = JF(p)->link;
2392*8b26181fSAndroid Build Coastguard Worker 		}
2393*8b26181fSAndroid Build Coastguard Worker 	}
2394*8b26181fSAndroid Build Coastguard Worker 	if (!done1)
2395*8b26181fSAndroid Build Coastguard Worker 		goto top;
2396*8b26181fSAndroid Build Coastguard Worker }
2397*8b26181fSAndroid Build Coastguard Worker 
2398*8b26181fSAndroid Build Coastguard Worker static void
opt_cleanup(opt_state_t * opt_state)2399*8b26181fSAndroid Build Coastguard Worker opt_cleanup(opt_state_t *opt_state)
2400*8b26181fSAndroid Build Coastguard Worker {
2401*8b26181fSAndroid Build Coastguard Worker 	free((void *)opt_state->vnode_base);
2402*8b26181fSAndroid Build Coastguard Worker 	free((void *)opt_state->vmap);
2403*8b26181fSAndroid Build Coastguard Worker 	free((void *)opt_state->edges);
2404*8b26181fSAndroid Build Coastguard Worker 	free((void *)opt_state->space);
2405*8b26181fSAndroid Build Coastguard Worker 	free((void *)opt_state->levels);
2406*8b26181fSAndroid Build Coastguard Worker 	free((void *)opt_state->blocks);
2407*8b26181fSAndroid Build Coastguard Worker }
2408*8b26181fSAndroid Build Coastguard Worker 
2409*8b26181fSAndroid Build Coastguard Worker /*
2410*8b26181fSAndroid Build Coastguard Worker  * For optimizer errors.
2411*8b26181fSAndroid Build Coastguard Worker  */
2412*8b26181fSAndroid Build Coastguard Worker static void PCAP_NORETURN
opt_error(opt_state_t * opt_state,const char * fmt,...)2413*8b26181fSAndroid Build Coastguard Worker opt_error(opt_state_t *opt_state, const char *fmt, ...)
2414*8b26181fSAndroid Build Coastguard Worker {
2415*8b26181fSAndroid Build Coastguard Worker 	va_list ap;
2416*8b26181fSAndroid Build Coastguard Worker 
2417*8b26181fSAndroid Build Coastguard Worker 	if (opt_state->errbuf != NULL) {
2418*8b26181fSAndroid Build Coastguard Worker 		va_start(ap, fmt);
2419*8b26181fSAndroid Build Coastguard Worker 		(void)vsnprintf(opt_state->errbuf,
2420*8b26181fSAndroid Build Coastguard Worker 		    PCAP_ERRBUF_SIZE, fmt, ap);
2421*8b26181fSAndroid Build Coastguard Worker 		va_end(ap);
2422*8b26181fSAndroid Build Coastguard Worker 	}
2423*8b26181fSAndroid Build Coastguard Worker 	longjmp(opt_state->top_ctx, 1);
2424*8b26181fSAndroid Build Coastguard Worker 	/* NOTREACHED */
2425*8b26181fSAndroid Build Coastguard Worker #ifdef _AIX
2426*8b26181fSAndroid Build Coastguard Worker 	PCAP_UNREACHABLE
2427*8b26181fSAndroid Build Coastguard Worker #endif /* _AIX */
2428*8b26181fSAndroid Build Coastguard Worker }
2429*8b26181fSAndroid Build Coastguard Worker 
2430*8b26181fSAndroid Build Coastguard Worker /*
2431*8b26181fSAndroid Build Coastguard Worker  * Return the number of stmts in 's'.
2432*8b26181fSAndroid Build Coastguard Worker  */
2433*8b26181fSAndroid Build Coastguard Worker static u_int
slength(struct slist * s)2434*8b26181fSAndroid Build Coastguard Worker slength(struct slist *s)
2435*8b26181fSAndroid Build Coastguard Worker {
2436*8b26181fSAndroid Build Coastguard Worker 	u_int n = 0;
2437*8b26181fSAndroid Build Coastguard Worker 
2438*8b26181fSAndroid Build Coastguard Worker 	for (; s; s = s->next)
2439*8b26181fSAndroid Build Coastguard Worker 		if (s->s.code != NOP)
2440*8b26181fSAndroid Build Coastguard Worker 			++n;
2441*8b26181fSAndroid Build Coastguard Worker 	return n;
2442*8b26181fSAndroid Build Coastguard Worker }
2443*8b26181fSAndroid Build Coastguard Worker 
2444*8b26181fSAndroid Build Coastguard Worker /*
2445*8b26181fSAndroid Build Coastguard Worker  * Return the number of nodes reachable by 'p'.
2446*8b26181fSAndroid Build Coastguard Worker  * All nodes should be initially unmarked.
2447*8b26181fSAndroid Build Coastguard Worker  */
2448*8b26181fSAndroid Build Coastguard Worker static int
count_blocks(struct icode * ic,struct block * p)2449*8b26181fSAndroid Build Coastguard Worker count_blocks(struct icode *ic, struct block *p)
2450*8b26181fSAndroid Build Coastguard Worker {
2451*8b26181fSAndroid Build Coastguard Worker 	if (p == 0 || isMarked(ic, p))
2452*8b26181fSAndroid Build Coastguard Worker 		return 0;
2453*8b26181fSAndroid Build Coastguard Worker 	Mark(ic, p);
2454*8b26181fSAndroid Build Coastguard Worker 	return count_blocks(ic, JT(p)) + count_blocks(ic, JF(p)) + 1;
2455*8b26181fSAndroid Build Coastguard Worker }
2456*8b26181fSAndroid Build Coastguard Worker 
2457*8b26181fSAndroid Build Coastguard Worker /*
2458*8b26181fSAndroid Build Coastguard Worker  * Do a depth first search on the flow graph, numbering the
2459*8b26181fSAndroid Build Coastguard Worker  * the basic blocks, and entering them into the 'blocks' array.`
2460*8b26181fSAndroid Build Coastguard Worker  */
2461*8b26181fSAndroid Build Coastguard Worker static void
number_blks_r(opt_state_t * opt_state,struct icode * ic,struct block * p)2462*8b26181fSAndroid Build Coastguard Worker number_blks_r(opt_state_t *opt_state, struct icode *ic, struct block *p)
2463*8b26181fSAndroid Build Coastguard Worker {
2464*8b26181fSAndroid Build Coastguard Worker 	u_int n;
2465*8b26181fSAndroid Build Coastguard Worker 
2466*8b26181fSAndroid Build Coastguard Worker 	if (p == 0 || isMarked(ic, p))
2467*8b26181fSAndroid Build Coastguard Worker 		return;
2468*8b26181fSAndroid Build Coastguard Worker 
2469*8b26181fSAndroid Build Coastguard Worker 	Mark(ic, p);
2470*8b26181fSAndroid Build Coastguard Worker 	n = opt_state->n_blocks++;
2471*8b26181fSAndroid Build Coastguard Worker 	if (opt_state->n_blocks == 0) {
2472*8b26181fSAndroid Build Coastguard Worker 		/*
2473*8b26181fSAndroid Build Coastguard Worker 		 * Overflow.
2474*8b26181fSAndroid Build Coastguard Worker 		 */
2475*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "filter is too complex to optimize");
2476*8b26181fSAndroid Build Coastguard Worker 	}
2477*8b26181fSAndroid Build Coastguard Worker 	p->id = n;
2478*8b26181fSAndroid Build Coastguard Worker 	opt_state->blocks[n] = p;
2479*8b26181fSAndroid Build Coastguard Worker 
2480*8b26181fSAndroid Build Coastguard Worker 	number_blks_r(opt_state, ic, JT(p));
2481*8b26181fSAndroid Build Coastguard Worker 	number_blks_r(opt_state, ic, JF(p));
2482*8b26181fSAndroid Build Coastguard Worker }
2483*8b26181fSAndroid Build Coastguard Worker 
2484*8b26181fSAndroid Build Coastguard Worker /*
2485*8b26181fSAndroid Build Coastguard Worker  * Return the number of stmts in the flowgraph reachable by 'p'.
2486*8b26181fSAndroid Build Coastguard Worker  * The nodes should be unmarked before calling.
2487*8b26181fSAndroid Build Coastguard Worker  *
2488*8b26181fSAndroid Build Coastguard Worker  * Note that "stmts" means "instructions", and that this includes
2489*8b26181fSAndroid Build Coastguard Worker  *
2490*8b26181fSAndroid Build Coastguard Worker  *	side-effect statements in 'p' (slength(p->stmts));
2491*8b26181fSAndroid Build Coastguard Worker  *
2492*8b26181fSAndroid Build Coastguard Worker  *	statements in the true branch from 'p' (count_stmts(JT(p)));
2493*8b26181fSAndroid Build Coastguard Worker  *
2494*8b26181fSAndroid Build Coastguard Worker  *	statements in the false branch from 'p' (count_stmts(JF(p)));
2495*8b26181fSAndroid Build Coastguard Worker  *
2496*8b26181fSAndroid Build Coastguard Worker  *	the conditional jump itself (1);
2497*8b26181fSAndroid Build Coastguard Worker  *
2498*8b26181fSAndroid Build Coastguard Worker  *	an extra long jump if the true branch requires it (p->longjt);
2499*8b26181fSAndroid Build Coastguard Worker  *
2500*8b26181fSAndroid Build Coastguard Worker  *	an extra long jump if the false branch requires it (p->longjf).
2501*8b26181fSAndroid Build Coastguard Worker  */
2502*8b26181fSAndroid Build Coastguard Worker static u_int
count_stmts(struct icode * ic,struct block * p)2503*8b26181fSAndroid Build Coastguard Worker count_stmts(struct icode *ic, struct block *p)
2504*8b26181fSAndroid Build Coastguard Worker {
2505*8b26181fSAndroid Build Coastguard Worker 	u_int n;
2506*8b26181fSAndroid Build Coastguard Worker 
2507*8b26181fSAndroid Build Coastguard Worker 	if (p == 0 || isMarked(ic, p))
2508*8b26181fSAndroid Build Coastguard Worker 		return 0;
2509*8b26181fSAndroid Build Coastguard Worker 	Mark(ic, p);
2510*8b26181fSAndroid Build Coastguard Worker 	n = count_stmts(ic, JT(p)) + count_stmts(ic, JF(p));
2511*8b26181fSAndroid Build Coastguard Worker 	return slength(p->stmts) + n + 1 + p->longjt + p->longjf;
2512*8b26181fSAndroid Build Coastguard Worker }
2513*8b26181fSAndroid Build Coastguard Worker 
2514*8b26181fSAndroid Build Coastguard Worker /*
2515*8b26181fSAndroid Build Coastguard Worker  * Allocate memory.  All allocation is done before optimization
2516*8b26181fSAndroid Build Coastguard Worker  * is begun.  A linear bound on the size of all data structures is computed
2517*8b26181fSAndroid Build Coastguard Worker  * from the total number of blocks and/or statements.
2518*8b26181fSAndroid Build Coastguard Worker  */
2519*8b26181fSAndroid Build Coastguard Worker static void
opt_init(opt_state_t * opt_state,struct icode * ic)2520*8b26181fSAndroid Build Coastguard Worker opt_init(opt_state_t *opt_state, struct icode *ic)
2521*8b26181fSAndroid Build Coastguard Worker {
2522*8b26181fSAndroid Build Coastguard Worker 	bpf_u_int32 *p;
2523*8b26181fSAndroid Build Coastguard Worker 	int i, n, max_stmts;
2524*8b26181fSAndroid Build Coastguard Worker 	u_int product;
2525*8b26181fSAndroid Build Coastguard Worker 	size_t block_memsize, edge_memsize;
2526*8b26181fSAndroid Build Coastguard Worker 
2527*8b26181fSAndroid Build Coastguard Worker 	/*
2528*8b26181fSAndroid Build Coastguard Worker 	 * First, count the blocks, so we can malloc an array to map
2529*8b26181fSAndroid Build Coastguard Worker 	 * block number to block.  Then, put the blocks into the array.
2530*8b26181fSAndroid Build Coastguard Worker 	 */
2531*8b26181fSAndroid Build Coastguard Worker 	unMarkAll(ic);
2532*8b26181fSAndroid Build Coastguard Worker 	n = count_blocks(ic, ic->root);
2533*8b26181fSAndroid Build Coastguard Worker 	opt_state->blocks = (struct block **)calloc(n, sizeof(*opt_state->blocks));
2534*8b26181fSAndroid Build Coastguard Worker 	if (opt_state->blocks == NULL)
2535*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "malloc");
2536*8b26181fSAndroid Build Coastguard Worker 	unMarkAll(ic);
2537*8b26181fSAndroid Build Coastguard Worker 	opt_state->n_blocks = 0;
2538*8b26181fSAndroid Build Coastguard Worker 	number_blks_r(opt_state, ic, ic->root);
2539*8b26181fSAndroid Build Coastguard Worker 
2540*8b26181fSAndroid Build Coastguard Worker 	/*
2541*8b26181fSAndroid Build Coastguard Worker 	 * This "should not happen".
2542*8b26181fSAndroid Build Coastguard Worker 	 */
2543*8b26181fSAndroid Build Coastguard Worker 	if (opt_state->n_blocks == 0)
2544*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "filter has no instructions; please report this as a libpcap issue");
2545*8b26181fSAndroid Build Coastguard Worker 
2546*8b26181fSAndroid Build Coastguard Worker 	opt_state->n_edges = 2 * opt_state->n_blocks;
2547*8b26181fSAndroid Build Coastguard Worker 	if ((opt_state->n_edges / 2) != opt_state->n_blocks) {
2548*8b26181fSAndroid Build Coastguard Worker 		/*
2549*8b26181fSAndroid Build Coastguard Worker 		 * Overflow.
2550*8b26181fSAndroid Build Coastguard Worker 		 */
2551*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "filter is too complex to optimize");
2552*8b26181fSAndroid Build Coastguard Worker 	}
2553*8b26181fSAndroid Build Coastguard Worker 	opt_state->edges = (struct edge **)calloc(opt_state->n_edges, sizeof(*opt_state->edges));
2554*8b26181fSAndroid Build Coastguard Worker 	if (opt_state->edges == NULL) {
2555*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "malloc");
2556*8b26181fSAndroid Build Coastguard Worker 	}
2557*8b26181fSAndroid Build Coastguard Worker 
2558*8b26181fSAndroid Build Coastguard Worker 	/*
2559*8b26181fSAndroid Build Coastguard Worker 	 * The number of levels is bounded by the number of nodes.
2560*8b26181fSAndroid Build Coastguard Worker 	 */
2561*8b26181fSAndroid Build Coastguard Worker 	opt_state->levels = (struct block **)calloc(opt_state->n_blocks, sizeof(*opt_state->levels));
2562*8b26181fSAndroid Build Coastguard Worker 	if (opt_state->levels == NULL) {
2563*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "malloc");
2564*8b26181fSAndroid Build Coastguard Worker 	}
2565*8b26181fSAndroid Build Coastguard Worker 
2566*8b26181fSAndroid Build Coastguard Worker 	opt_state->edgewords = opt_state->n_edges / BITS_PER_WORD + 1;
2567*8b26181fSAndroid Build Coastguard Worker 	opt_state->nodewords = opt_state->n_blocks / BITS_PER_WORD + 1;
2568*8b26181fSAndroid Build Coastguard Worker 
2569*8b26181fSAndroid Build Coastguard Worker 	/*
2570*8b26181fSAndroid Build Coastguard Worker 	 * Make sure opt_state->n_blocks * opt_state->nodewords fits
2571*8b26181fSAndroid Build Coastguard Worker 	 * in a u_int; we use it as a u_int number-of-iterations
2572*8b26181fSAndroid Build Coastguard Worker 	 * value.
2573*8b26181fSAndroid Build Coastguard Worker 	 */
2574*8b26181fSAndroid Build Coastguard Worker 	product = opt_state->n_blocks * opt_state->nodewords;
2575*8b26181fSAndroid Build Coastguard Worker 	if ((product / opt_state->n_blocks) != opt_state->nodewords) {
2576*8b26181fSAndroid Build Coastguard Worker 		/*
2577*8b26181fSAndroid Build Coastguard Worker 		 * XXX - just punt and don't try to optimize?
2578*8b26181fSAndroid Build Coastguard Worker 		 * In practice, this is unlikely to happen with
2579*8b26181fSAndroid Build Coastguard Worker 		 * a normal filter.
2580*8b26181fSAndroid Build Coastguard Worker 		 */
2581*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "filter is too complex to optimize");
2582*8b26181fSAndroid Build Coastguard Worker 	}
2583*8b26181fSAndroid Build Coastguard Worker 
2584*8b26181fSAndroid Build Coastguard Worker 	/*
2585*8b26181fSAndroid Build Coastguard Worker 	 * Make sure the total memory required for that doesn't
2586*8b26181fSAndroid Build Coastguard Worker 	 * overflow.
2587*8b26181fSAndroid Build Coastguard Worker 	 */
2588*8b26181fSAndroid Build Coastguard Worker 	block_memsize = (size_t)2 * product * sizeof(*opt_state->space);
2589*8b26181fSAndroid Build Coastguard Worker 	if ((block_memsize / product) != 2 * sizeof(*opt_state->space)) {
2590*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "filter is too complex to optimize");
2591*8b26181fSAndroid Build Coastguard Worker 	}
2592*8b26181fSAndroid Build Coastguard Worker 
2593*8b26181fSAndroid Build Coastguard Worker 	/*
2594*8b26181fSAndroid Build Coastguard Worker 	 * Make sure opt_state->n_edges * opt_state->edgewords fits
2595*8b26181fSAndroid Build Coastguard Worker 	 * in a u_int; we use it as a u_int number-of-iterations
2596*8b26181fSAndroid Build Coastguard Worker 	 * value.
2597*8b26181fSAndroid Build Coastguard Worker 	 */
2598*8b26181fSAndroid Build Coastguard Worker 	product = opt_state->n_edges * opt_state->edgewords;
2599*8b26181fSAndroid Build Coastguard Worker 	if ((product / opt_state->n_edges) != opt_state->edgewords) {
2600*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "filter is too complex to optimize");
2601*8b26181fSAndroid Build Coastguard Worker 	}
2602*8b26181fSAndroid Build Coastguard Worker 
2603*8b26181fSAndroid Build Coastguard Worker 	/*
2604*8b26181fSAndroid Build Coastguard Worker 	 * Make sure the total memory required for that doesn't
2605*8b26181fSAndroid Build Coastguard Worker 	 * overflow.
2606*8b26181fSAndroid Build Coastguard Worker 	 */
2607*8b26181fSAndroid Build Coastguard Worker 	edge_memsize = (size_t)product * sizeof(*opt_state->space);
2608*8b26181fSAndroid Build Coastguard Worker 	if (edge_memsize / product != sizeof(*opt_state->space)) {
2609*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "filter is too complex to optimize");
2610*8b26181fSAndroid Build Coastguard Worker 	}
2611*8b26181fSAndroid Build Coastguard Worker 
2612*8b26181fSAndroid Build Coastguard Worker 	/*
2613*8b26181fSAndroid Build Coastguard Worker 	 * Make sure the total memory required for both of them doesn't
2614*8b26181fSAndroid Build Coastguard Worker 	 * overflow.
2615*8b26181fSAndroid Build Coastguard Worker 	 */
2616*8b26181fSAndroid Build Coastguard Worker 	if (block_memsize > SIZE_MAX - edge_memsize) {
2617*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "filter is too complex to optimize");
2618*8b26181fSAndroid Build Coastguard Worker 	}
2619*8b26181fSAndroid Build Coastguard Worker 
2620*8b26181fSAndroid Build Coastguard Worker 	/* XXX */
2621*8b26181fSAndroid Build Coastguard Worker 	opt_state->space = (bpf_u_int32 *)malloc(block_memsize + edge_memsize);
2622*8b26181fSAndroid Build Coastguard Worker 	if (opt_state->space == NULL) {
2623*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "malloc");
2624*8b26181fSAndroid Build Coastguard Worker 	}
2625*8b26181fSAndroid Build Coastguard Worker 	p = opt_state->space;
2626*8b26181fSAndroid Build Coastguard Worker 	opt_state->all_dom_sets = p;
2627*8b26181fSAndroid Build Coastguard Worker 	for (i = 0; i < n; ++i) {
2628*8b26181fSAndroid Build Coastguard Worker 		opt_state->blocks[i]->dom = p;
2629*8b26181fSAndroid Build Coastguard Worker 		p += opt_state->nodewords;
2630*8b26181fSAndroid Build Coastguard Worker 	}
2631*8b26181fSAndroid Build Coastguard Worker 	opt_state->all_closure_sets = p;
2632*8b26181fSAndroid Build Coastguard Worker 	for (i = 0; i < n; ++i) {
2633*8b26181fSAndroid Build Coastguard Worker 		opt_state->blocks[i]->closure = p;
2634*8b26181fSAndroid Build Coastguard Worker 		p += opt_state->nodewords;
2635*8b26181fSAndroid Build Coastguard Worker 	}
2636*8b26181fSAndroid Build Coastguard Worker 	opt_state->all_edge_sets = p;
2637*8b26181fSAndroid Build Coastguard Worker 	for (i = 0; i < n; ++i) {
2638*8b26181fSAndroid Build Coastguard Worker 		register struct block *b = opt_state->blocks[i];
2639*8b26181fSAndroid Build Coastguard Worker 
2640*8b26181fSAndroid Build Coastguard Worker 		b->et.edom = p;
2641*8b26181fSAndroid Build Coastguard Worker 		p += opt_state->edgewords;
2642*8b26181fSAndroid Build Coastguard Worker 		b->ef.edom = p;
2643*8b26181fSAndroid Build Coastguard Worker 		p += opt_state->edgewords;
2644*8b26181fSAndroid Build Coastguard Worker 		b->et.id = i;
2645*8b26181fSAndroid Build Coastguard Worker 		opt_state->edges[i] = &b->et;
2646*8b26181fSAndroid Build Coastguard Worker 		b->ef.id = opt_state->n_blocks + i;
2647*8b26181fSAndroid Build Coastguard Worker 		opt_state->edges[opt_state->n_blocks + i] = &b->ef;
2648*8b26181fSAndroid Build Coastguard Worker 		b->et.pred = b;
2649*8b26181fSAndroid Build Coastguard Worker 		b->ef.pred = b;
2650*8b26181fSAndroid Build Coastguard Worker 	}
2651*8b26181fSAndroid Build Coastguard Worker 	max_stmts = 0;
2652*8b26181fSAndroid Build Coastguard Worker 	for (i = 0; i < n; ++i)
2653*8b26181fSAndroid Build Coastguard Worker 		max_stmts += slength(opt_state->blocks[i]->stmts) + 1;
2654*8b26181fSAndroid Build Coastguard Worker 	/*
2655*8b26181fSAndroid Build Coastguard Worker 	 * We allocate at most 3 value numbers per statement,
2656*8b26181fSAndroid Build Coastguard Worker 	 * so this is an upper bound on the number of valnodes
2657*8b26181fSAndroid Build Coastguard Worker 	 * we'll need.
2658*8b26181fSAndroid Build Coastguard Worker 	 */
2659*8b26181fSAndroid Build Coastguard Worker 	opt_state->maxval = 3 * max_stmts;
2660*8b26181fSAndroid Build Coastguard Worker 	opt_state->vmap = (struct vmapinfo *)calloc(opt_state->maxval, sizeof(*opt_state->vmap));
2661*8b26181fSAndroid Build Coastguard Worker 	if (opt_state->vmap == NULL) {
2662*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "malloc");
2663*8b26181fSAndroid Build Coastguard Worker 	}
2664*8b26181fSAndroid Build Coastguard Worker 	opt_state->vnode_base = (struct valnode *)calloc(opt_state->maxval, sizeof(*opt_state->vnode_base));
2665*8b26181fSAndroid Build Coastguard Worker 	if (opt_state->vnode_base == NULL) {
2666*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "malloc");
2667*8b26181fSAndroid Build Coastguard Worker 	}
2668*8b26181fSAndroid Build Coastguard Worker }
2669*8b26181fSAndroid Build Coastguard Worker 
2670*8b26181fSAndroid Build Coastguard Worker /*
2671*8b26181fSAndroid Build Coastguard Worker  * This is only used when supporting optimizer debugging.  It is
2672*8b26181fSAndroid Build Coastguard Worker  * global state, so do *not* do more than one compile in parallel
2673*8b26181fSAndroid Build Coastguard Worker  * and expect it to provide meaningful information.
2674*8b26181fSAndroid Build Coastguard Worker  */
2675*8b26181fSAndroid Build Coastguard Worker #ifdef BDEBUG
2676*8b26181fSAndroid Build Coastguard Worker int bids[NBIDS];
2677*8b26181fSAndroid Build Coastguard Worker #endif
2678*8b26181fSAndroid Build Coastguard Worker 
2679*8b26181fSAndroid Build Coastguard Worker static void PCAP_NORETURN conv_error(conv_state_t *, const char *, ...)
2680*8b26181fSAndroid Build Coastguard Worker     PCAP_PRINTFLIKE(2, 3);
2681*8b26181fSAndroid Build Coastguard Worker 
2682*8b26181fSAndroid Build Coastguard Worker /*
2683*8b26181fSAndroid Build Coastguard Worker  * Returns true if successful.  Returns false if a branch has
2684*8b26181fSAndroid Build Coastguard Worker  * an offset that is too large.  If so, we have marked that
2685*8b26181fSAndroid Build Coastguard Worker  * branch so that on a subsequent iteration, it will be treated
2686*8b26181fSAndroid Build Coastguard Worker  * properly.
2687*8b26181fSAndroid Build Coastguard Worker  */
2688*8b26181fSAndroid Build Coastguard Worker static int
convert_code_r(conv_state_t * conv_state,struct icode * ic,struct block * p)2689*8b26181fSAndroid Build Coastguard Worker convert_code_r(conv_state_t *conv_state, struct icode *ic, struct block *p)
2690*8b26181fSAndroid Build Coastguard Worker {
2691*8b26181fSAndroid Build Coastguard Worker 	struct bpf_insn *dst;
2692*8b26181fSAndroid Build Coastguard Worker 	struct slist *src;
2693*8b26181fSAndroid Build Coastguard Worker 	u_int slen;
2694*8b26181fSAndroid Build Coastguard Worker 	u_int off;
2695*8b26181fSAndroid Build Coastguard Worker 	struct slist **offset = NULL;
2696*8b26181fSAndroid Build Coastguard Worker 
2697*8b26181fSAndroid Build Coastguard Worker 	if (p == 0 || isMarked(ic, p))
2698*8b26181fSAndroid Build Coastguard Worker 		return (1);
2699*8b26181fSAndroid Build Coastguard Worker 	Mark(ic, p);
2700*8b26181fSAndroid Build Coastguard Worker 
2701*8b26181fSAndroid Build Coastguard Worker 	if (convert_code_r(conv_state, ic, JF(p)) == 0)
2702*8b26181fSAndroid Build Coastguard Worker 		return (0);
2703*8b26181fSAndroid Build Coastguard Worker 	if (convert_code_r(conv_state, ic, JT(p)) == 0)
2704*8b26181fSAndroid Build Coastguard Worker 		return (0);
2705*8b26181fSAndroid Build Coastguard Worker 
2706*8b26181fSAndroid Build Coastguard Worker 	slen = slength(p->stmts);
2707*8b26181fSAndroid Build Coastguard Worker 	dst = conv_state->ftail -= (slen + 1 + p->longjt + p->longjf);
2708*8b26181fSAndroid Build Coastguard Worker 		/* inflate length by any extra jumps */
2709*8b26181fSAndroid Build Coastguard Worker 
2710*8b26181fSAndroid Build Coastguard Worker 	p->offset = (int)(dst - conv_state->fstart);
2711*8b26181fSAndroid Build Coastguard Worker 
2712*8b26181fSAndroid Build Coastguard Worker 	/* generate offset[] for convenience  */
2713*8b26181fSAndroid Build Coastguard Worker 	if (slen) {
2714*8b26181fSAndroid Build Coastguard Worker 		offset = (struct slist **)calloc(slen, sizeof(struct slist *));
2715*8b26181fSAndroid Build Coastguard Worker 		if (!offset) {
2716*8b26181fSAndroid Build Coastguard Worker 			conv_error(conv_state, "not enough core");
2717*8b26181fSAndroid Build Coastguard Worker 			/*NOTREACHED*/
2718*8b26181fSAndroid Build Coastguard Worker 		}
2719*8b26181fSAndroid Build Coastguard Worker 	}
2720*8b26181fSAndroid Build Coastguard Worker 	src = p->stmts;
2721*8b26181fSAndroid Build Coastguard Worker 	for (off = 0; off < slen && src; off++) {
2722*8b26181fSAndroid Build Coastguard Worker #if 0
2723*8b26181fSAndroid Build Coastguard Worker 		printf("off=%d src=%x\n", off, src);
2724*8b26181fSAndroid Build Coastguard Worker #endif
2725*8b26181fSAndroid Build Coastguard Worker 		offset[off] = src;
2726*8b26181fSAndroid Build Coastguard Worker 		src = src->next;
2727*8b26181fSAndroid Build Coastguard Worker 	}
2728*8b26181fSAndroid Build Coastguard Worker 
2729*8b26181fSAndroid Build Coastguard Worker 	off = 0;
2730*8b26181fSAndroid Build Coastguard Worker 	for (src = p->stmts; src; src = src->next) {
2731*8b26181fSAndroid Build Coastguard Worker 		if (src->s.code == NOP)
2732*8b26181fSAndroid Build Coastguard Worker 			continue;
2733*8b26181fSAndroid Build Coastguard Worker 		dst->code = (u_short)src->s.code;
2734*8b26181fSAndroid Build Coastguard Worker 		dst->k = src->s.k;
2735*8b26181fSAndroid Build Coastguard Worker 
2736*8b26181fSAndroid Build Coastguard Worker 		/* fill block-local relative jump */
2737*8b26181fSAndroid Build Coastguard Worker 		if (BPF_CLASS(src->s.code) != BPF_JMP || src->s.code == (BPF_JMP|BPF_JA)) {
2738*8b26181fSAndroid Build Coastguard Worker #if 0
2739*8b26181fSAndroid Build Coastguard Worker 			if (src->s.jt || src->s.jf) {
2740*8b26181fSAndroid Build Coastguard Worker 				free(offset);
2741*8b26181fSAndroid Build Coastguard Worker 				conv_error(conv_state, "illegal jmp destination");
2742*8b26181fSAndroid Build Coastguard Worker 				/*NOTREACHED*/
2743*8b26181fSAndroid Build Coastguard Worker 			}
2744*8b26181fSAndroid Build Coastguard Worker #endif
2745*8b26181fSAndroid Build Coastguard Worker 			goto filled;
2746*8b26181fSAndroid Build Coastguard Worker 		}
2747*8b26181fSAndroid Build Coastguard Worker 		if (off == slen - 2)	/*???*/
2748*8b26181fSAndroid Build Coastguard Worker 			goto filled;
2749*8b26181fSAndroid Build Coastguard Worker 
2750*8b26181fSAndroid Build Coastguard Worker 	    {
2751*8b26181fSAndroid Build Coastguard Worker 		u_int i;
2752*8b26181fSAndroid Build Coastguard Worker 		int jt, jf;
2753*8b26181fSAndroid Build Coastguard Worker 		const char ljerr[] = "%s for block-local relative jump: off=%d";
2754*8b26181fSAndroid Build Coastguard Worker 
2755*8b26181fSAndroid Build Coastguard Worker #if 0
2756*8b26181fSAndroid Build Coastguard Worker 		printf("code=%x off=%d %x %x\n", src->s.code,
2757*8b26181fSAndroid Build Coastguard Worker 			off, src->s.jt, src->s.jf);
2758*8b26181fSAndroid Build Coastguard Worker #endif
2759*8b26181fSAndroid Build Coastguard Worker 
2760*8b26181fSAndroid Build Coastguard Worker 		if (!src->s.jt || !src->s.jf) {
2761*8b26181fSAndroid Build Coastguard Worker 			free(offset);
2762*8b26181fSAndroid Build Coastguard Worker 			conv_error(conv_state, ljerr, "no jmp destination", off);
2763*8b26181fSAndroid Build Coastguard Worker 			/*NOTREACHED*/
2764*8b26181fSAndroid Build Coastguard Worker 		}
2765*8b26181fSAndroid Build Coastguard Worker 
2766*8b26181fSAndroid Build Coastguard Worker 		jt = jf = 0;
2767*8b26181fSAndroid Build Coastguard Worker 		for (i = 0; i < slen; i++) {
2768*8b26181fSAndroid Build Coastguard Worker 			if (offset[i] == src->s.jt) {
2769*8b26181fSAndroid Build Coastguard Worker 				if (jt) {
2770*8b26181fSAndroid Build Coastguard Worker 					free(offset);
2771*8b26181fSAndroid Build Coastguard Worker 					conv_error(conv_state, ljerr, "multiple matches", off);
2772*8b26181fSAndroid Build Coastguard Worker 					/*NOTREACHED*/
2773*8b26181fSAndroid Build Coastguard Worker 				}
2774*8b26181fSAndroid Build Coastguard Worker 
2775*8b26181fSAndroid Build Coastguard Worker 				if (i - off - 1 >= 256) {
2776*8b26181fSAndroid Build Coastguard Worker 					free(offset);
2777*8b26181fSAndroid Build Coastguard Worker 					conv_error(conv_state, ljerr, "out-of-range jump", off);
2778*8b26181fSAndroid Build Coastguard Worker 					/*NOTREACHED*/
2779*8b26181fSAndroid Build Coastguard Worker 				}
2780*8b26181fSAndroid Build Coastguard Worker 				dst->jt = (u_char)(i - off - 1);
2781*8b26181fSAndroid Build Coastguard Worker 				jt++;
2782*8b26181fSAndroid Build Coastguard Worker 			}
2783*8b26181fSAndroid Build Coastguard Worker 			if (offset[i] == src->s.jf) {
2784*8b26181fSAndroid Build Coastguard Worker 				if (jf) {
2785*8b26181fSAndroid Build Coastguard Worker 					free(offset);
2786*8b26181fSAndroid Build Coastguard Worker 					conv_error(conv_state, ljerr, "multiple matches", off);
2787*8b26181fSAndroid Build Coastguard Worker 					/*NOTREACHED*/
2788*8b26181fSAndroid Build Coastguard Worker 				}
2789*8b26181fSAndroid Build Coastguard Worker 				if (i - off - 1 >= 256) {
2790*8b26181fSAndroid Build Coastguard Worker 					free(offset);
2791*8b26181fSAndroid Build Coastguard Worker 					conv_error(conv_state, ljerr, "out-of-range jump", off);
2792*8b26181fSAndroid Build Coastguard Worker 					/*NOTREACHED*/
2793*8b26181fSAndroid Build Coastguard Worker 				}
2794*8b26181fSAndroid Build Coastguard Worker 				dst->jf = (u_char)(i - off - 1);
2795*8b26181fSAndroid Build Coastguard Worker 				jf++;
2796*8b26181fSAndroid Build Coastguard Worker 			}
2797*8b26181fSAndroid Build Coastguard Worker 		}
2798*8b26181fSAndroid Build Coastguard Worker 		if (!jt || !jf) {
2799*8b26181fSAndroid Build Coastguard Worker 			free(offset);
2800*8b26181fSAndroid Build Coastguard Worker 			conv_error(conv_state, ljerr, "no destination found", off);
2801*8b26181fSAndroid Build Coastguard Worker 			/*NOTREACHED*/
2802*8b26181fSAndroid Build Coastguard Worker 		}
2803*8b26181fSAndroid Build Coastguard Worker 	    }
2804*8b26181fSAndroid Build Coastguard Worker filled:
2805*8b26181fSAndroid Build Coastguard Worker 		++dst;
2806*8b26181fSAndroid Build Coastguard Worker 		++off;
2807*8b26181fSAndroid Build Coastguard Worker 	}
2808*8b26181fSAndroid Build Coastguard Worker 	if (offset)
2809*8b26181fSAndroid Build Coastguard Worker 		free(offset);
2810*8b26181fSAndroid Build Coastguard Worker 
2811*8b26181fSAndroid Build Coastguard Worker #ifdef BDEBUG
2812*8b26181fSAndroid Build Coastguard Worker 	if (dst - conv_state->fstart < NBIDS)
2813*8b26181fSAndroid Build Coastguard Worker 		bids[dst - conv_state->fstart] = p->id + 1;
2814*8b26181fSAndroid Build Coastguard Worker #endif
2815*8b26181fSAndroid Build Coastguard Worker 	dst->code = (u_short)p->s.code;
2816*8b26181fSAndroid Build Coastguard Worker 	dst->k = p->s.k;
2817*8b26181fSAndroid Build Coastguard Worker 	if (JT(p)) {
2818*8b26181fSAndroid Build Coastguard Worker 		/* number of extra jumps inserted */
2819*8b26181fSAndroid Build Coastguard Worker 		u_char extrajmps = 0;
2820*8b26181fSAndroid Build Coastguard Worker 		off = JT(p)->offset - (p->offset + slen) - 1;
2821*8b26181fSAndroid Build Coastguard Worker 		if (off >= 256) {
2822*8b26181fSAndroid Build Coastguard Worker 		    /* offset too large for branch, must add a jump */
2823*8b26181fSAndroid Build Coastguard Worker 		    if (p->longjt == 0) {
2824*8b26181fSAndroid Build Coastguard Worker 			/* mark this instruction and retry */
2825*8b26181fSAndroid Build Coastguard Worker 			p->longjt++;
2826*8b26181fSAndroid Build Coastguard Worker 			return(0);
2827*8b26181fSAndroid Build Coastguard Worker 		    }
2828*8b26181fSAndroid Build Coastguard Worker 		    dst->jt = extrajmps;
2829*8b26181fSAndroid Build Coastguard Worker 		    extrajmps++;
2830*8b26181fSAndroid Build Coastguard Worker 		    dst[extrajmps].code = BPF_JMP|BPF_JA;
2831*8b26181fSAndroid Build Coastguard Worker 		    dst[extrajmps].k = off - extrajmps;
2832*8b26181fSAndroid Build Coastguard Worker 		}
2833*8b26181fSAndroid Build Coastguard Worker 		else
2834*8b26181fSAndroid Build Coastguard Worker 		    dst->jt = (u_char)off;
2835*8b26181fSAndroid Build Coastguard Worker 		off = JF(p)->offset - (p->offset + slen) - 1;
2836*8b26181fSAndroid Build Coastguard Worker 		if (off >= 256) {
2837*8b26181fSAndroid Build Coastguard Worker 		    /* offset too large for branch, must add a jump */
2838*8b26181fSAndroid Build Coastguard Worker 		    if (p->longjf == 0) {
2839*8b26181fSAndroid Build Coastguard Worker 			/* mark this instruction and retry */
2840*8b26181fSAndroid Build Coastguard Worker 			p->longjf++;
2841*8b26181fSAndroid Build Coastguard Worker 			return(0);
2842*8b26181fSAndroid Build Coastguard Worker 		    }
2843*8b26181fSAndroid Build Coastguard Worker 		    /* branch if F to following jump */
2844*8b26181fSAndroid Build Coastguard Worker 		    /* if two jumps are inserted, F goes to second one */
2845*8b26181fSAndroid Build Coastguard Worker 		    dst->jf = extrajmps;
2846*8b26181fSAndroid Build Coastguard Worker 		    extrajmps++;
2847*8b26181fSAndroid Build Coastguard Worker 		    dst[extrajmps].code = BPF_JMP|BPF_JA;
2848*8b26181fSAndroid Build Coastguard Worker 		    dst[extrajmps].k = off - extrajmps;
2849*8b26181fSAndroid Build Coastguard Worker 		}
2850*8b26181fSAndroid Build Coastguard Worker 		else
2851*8b26181fSAndroid Build Coastguard Worker 		    dst->jf = (u_char)off;
2852*8b26181fSAndroid Build Coastguard Worker 	}
2853*8b26181fSAndroid Build Coastguard Worker 	return (1);
2854*8b26181fSAndroid Build Coastguard Worker }
2855*8b26181fSAndroid Build Coastguard Worker 
2856*8b26181fSAndroid Build Coastguard Worker 
2857*8b26181fSAndroid Build Coastguard Worker /*
2858*8b26181fSAndroid Build Coastguard Worker  * Convert flowgraph intermediate representation to the
2859*8b26181fSAndroid Build Coastguard Worker  * BPF array representation.  Set *lenp to the number of instructions.
2860*8b26181fSAndroid Build Coastguard Worker  *
2861*8b26181fSAndroid Build Coastguard Worker  * This routine does *NOT* leak the memory pointed to by fp.  It *must
2862*8b26181fSAndroid Build Coastguard Worker  * not* do free(fp) before returning fp; doing so would make no sense,
2863*8b26181fSAndroid Build Coastguard Worker  * as the BPF array pointed to by the return value of icode_to_fcode()
2864*8b26181fSAndroid Build Coastguard Worker  * must be valid - it's being returned for use in a bpf_program structure.
2865*8b26181fSAndroid Build Coastguard Worker  *
2866*8b26181fSAndroid Build Coastguard Worker  * If it appears that icode_to_fcode() is leaking, the problem is that
2867*8b26181fSAndroid Build Coastguard Worker  * the program using pcap_compile() is failing to free the memory in
2868*8b26181fSAndroid Build Coastguard Worker  * the BPF program when it's done - the leak is in the program, not in
2869*8b26181fSAndroid Build Coastguard Worker  * the routine that happens to be allocating the memory.  (By analogy, if
2870*8b26181fSAndroid Build Coastguard Worker  * a program calls fopen() without ever calling fclose() on the FILE *,
2871*8b26181fSAndroid Build Coastguard Worker  * it will leak the FILE structure; the leak is not in fopen(), it's in
2872*8b26181fSAndroid Build Coastguard Worker  * the program.)  Change the program to use pcap_freecode() when it's
2873*8b26181fSAndroid Build Coastguard Worker  * done with the filter program.  See the pcap man page.
2874*8b26181fSAndroid Build Coastguard Worker  */
2875*8b26181fSAndroid Build Coastguard Worker struct bpf_insn *
icode_to_fcode(struct icode * ic,struct block * root,u_int * lenp,char * errbuf)2876*8b26181fSAndroid Build Coastguard Worker icode_to_fcode(struct icode *ic, struct block *root, u_int *lenp,
2877*8b26181fSAndroid Build Coastguard Worker     char *errbuf)
2878*8b26181fSAndroid Build Coastguard Worker {
2879*8b26181fSAndroid Build Coastguard Worker 	u_int n;
2880*8b26181fSAndroid Build Coastguard Worker 	struct bpf_insn *fp;
2881*8b26181fSAndroid Build Coastguard Worker 	conv_state_t conv_state;
2882*8b26181fSAndroid Build Coastguard Worker 
2883*8b26181fSAndroid Build Coastguard Worker 	conv_state.fstart = NULL;
2884*8b26181fSAndroid Build Coastguard Worker 	conv_state.errbuf = errbuf;
2885*8b26181fSAndroid Build Coastguard Worker 	if (setjmp(conv_state.top_ctx) != 0) {
2886*8b26181fSAndroid Build Coastguard Worker 		free(conv_state.fstart);
2887*8b26181fSAndroid Build Coastguard Worker 		return NULL;
2888*8b26181fSAndroid Build Coastguard Worker 	}
2889*8b26181fSAndroid Build Coastguard Worker 
2890*8b26181fSAndroid Build Coastguard Worker 	/*
2891*8b26181fSAndroid Build Coastguard Worker 	 * Loop doing convert_code_r() until no branches remain
2892*8b26181fSAndroid Build Coastguard Worker 	 * with too-large offsets.
2893*8b26181fSAndroid Build Coastguard Worker 	 */
2894*8b26181fSAndroid Build Coastguard Worker 	for (;;) {
2895*8b26181fSAndroid Build Coastguard Worker 	    unMarkAll(ic);
2896*8b26181fSAndroid Build Coastguard Worker 	    n = *lenp = count_stmts(ic, root);
2897*8b26181fSAndroid Build Coastguard Worker 
2898*8b26181fSAndroid Build Coastguard Worker 	    fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);
2899*8b26181fSAndroid Build Coastguard Worker 	    if (fp == NULL) {
2900*8b26181fSAndroid Build Coastguard Worker 		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
2901*8b26181fSAndroid Build Coastguard Worker 		    "malloc");
2902*8b26181fSAndroid Build Coastguard Worker 		return NULL;
2903*8b26181fSAndroid Build Coastguard Worker 	    }
2904*8b26181fSAndroid Build Coastguard Worker 	    memset((char *)fp, 0, sizeof(*fp) * n);
2905*8b26181fSAndroid Build Coastguard Worker 	    conv_state.fstart = fp;
2906*8b26181fSAndroid Build Coastguard Worker 	    conv_state.ftail = fp + n;
2907*8b26181fSAndroid Build Coastguard Worker 
2908*8b26181fSAndroid Build Coastguard Worker 	    unMarkAll(ic);
2909*8b26181fSAndroid Build Coastguard Worker 	    if (convert_code_r(&conv_state, ic, root))
2910*8b26181fSAndroid Build Coastguard Worker 		break;
2911*8b26181fSAndroid Build Coastguard Worker 	    free(fp);
2912*8b26181fSAndroid Build Coastguard Worker 	}
2913*8b26181fSAndroid Build Coastguard Worker 
2914*8b26181fSAndroid Build Coastguard Worker 	return fp;
2915*8b26181fSAndroid Build Coastguard Worker }
2916*8b26181fSAndroid Build Coastguard Worker 
2917*8b26181fSAndroid Build Coastguard Worker /*
2918*8b26181fSAndroid Build Coastguard Worker  * For iconv_to_fconv() errors.
2919*8b26181fSAndroid Build Coastguard Worker  */
2920*8b26181fSAndroid Build Coastguard Worker static void PCAP_NORETURN
conv_error(conv_state_t * conv_state,const char * fmt,...)2921*8b26181fSAndroid Build Coastguard Worker conv_error(conv_state_t *conv_state, const char *fmt, ...)
2922*8b26181fSAndroid Build Coastguard Worker {
2923*8b26181fSAndroid Build Coastguard Worker 	va_list ap;
2924*8b26181fSAndroid Build Coastguard Worker 
2925*8b26181fSAndroid Build Coastguard Worker 	va_start(ap, fmt);
2926*8b26181fSAndroid Build Coastguard Worker 	(void)vsnprintf(conv_state->errbuf,
2927*8b26181fSAndroid Build Coastguard Worker 	    PCAP_ERRBUF_SIZE, fmt, ap);
2928*8b26181fSAndroid Build Coastguard Worker 	va_end(ap);
2929*8b26181fSAndroid Build Coastguard Worker 	longjmp(conv_state->top_ctx, 1);
2930*8b26181fSAndroid Build Coastguard Worker 	/* NOTREACHED */
2931*8b26181fSAndroid Build Coastguard Worker #ifdef _AIX
2932*8b26181fSAndroid Build Coastguard Worker 	PCAP_UNREACHABLE
2933*8b26181fSAndroid Build Coastguard Worker #endif /* _AIX */
2934*8b26181fSAndroid Build Coastguard Worker }
2935*8b26181fSAndroid Build Coastguard Worker 
2936*8b26181fSAndroid Build Coastguard Worker /*
2937*8b26181fSAndroid Build Coastguard Worker  * Make a copy of a BPF program and put it in the "fcode" member of
2938*8b26181fSAndroid Build Coastguard Worker  * a "pcap_t".
2939*8b26181fSAndroid Build Coastguard Worker  *
2940*8b26181fSAndroid Build Coastguard Worker  * If we fail to allocate memory for the copy, fill in the "errbuf"
2941*8b26181fSAndroid Build Coastguard Worker  * member of the "pcap_t" with an error message, and return -1;
2942*8b26181fSAndroid Build Coastguard Worker  * otherwise, return 0.
2943*8b26181fSAndroid Build Coastguard Worker  */
2944*8b26181fSAndroid Build Coastguard Worker int
install_bpf_program(pcap_t * p,struct bpf_program * fp)2945*8b26181fSAndroid Build Coastguard Worker install_bpf_program(pcap_t *p, struct bpf_program *fp)
2946*8b26181fSAndroid Build Coastguard Worker {
2947*8b26181fSAndroid Build Coastguard Worker 	size_t prog_size;
2948*8b26181fSAndroid Build Coastguard Worker 
2949*8b26181fSAndroid Build Coastguard Worker 	/*
2950*8b26181fSAndroid Build Coastguard Worker 	 * Validate the program.
2951*8b26181fSAndroid Build Coastguard Worker 	 */
2952*8b26181fSAndroid Build Coastguard Worker 	if (!pcap_validate_filter(fp->bf_insns, fp->bf_len)) {
2953*8b26181fSAndroid Build Coastguard Worker 		snprintf(p->errbuf, sizeof(p->errbuf),
2954*8b26181fSAndroid Build Coastguard Worker 			"BPF program is not valid");
2955*8b26181fSAndroid Build Coastguard Worker 		return (-1);
2956*8b26181fSAndroid Build Coastguard Worker 	}
2957*8b26181fSAndroid Build Coastguard Worker 
2958*8b26181fSAndroid Build Coastguard Worker 	/*
2959*8b26181fSAndroid Build Coastguard Worker 	 * Free up any already installed program.
2960*8b26181fSAndroid Build Coastguard Worker 	 */
2961*8b26181fSAndroid Build Coastguard Worker 	pcap_freecode(&p->fcode);
2962*8b26181fSAndroid Build Coastguard Worker 
2963*8b26181fSAndroid Build Coastguard Worker 	prog_size = sizeof(*fp->bf_insns) * fp->bf_len;
2964*8b26181fSAndroid Build Coastguard Worker 	p->fcode.bf_len = fp->bf_len;
2965*8b26181fSAndroid Build Coastguard Worker 	p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size);
2966*8b26181fSAndroid Build Coastguard Worker 	if (p->fcode.bf_insns == NULL) {
2967*8b26181fSAndroid Build Coastguard Worker 		pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
2968*8b26181fSAndroid Build Coastguard Worker 		    errno, "malloc");
2969*8b26181fSAndroid Build Coastguard Worker 		return (-1);
2970*8b26181fSAndroid Build Coastguard Worker 	}
2971*8b26181fSAndroid Build Coastguard Worker 	memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size);
2972*8b26181fSAndroid Build Coastguard Worker 	return (0);
2973*8b26181fSAndroid Build Coastguard Worker }
2974*8b26181fSAndroid Build Coastguard Worker 
2975*8b26181fSAndroid Build Coastguard Worker #ifdef BDEBUG
2976*8b26181fSAndroid Build Coastguard Worker static void
dot_dump_node(struct icode * ic,struct block * block,struct bpf_program * prog,FILE * out)2977*8b26181fSAndroid Build Coastguard Worker dot_dump_node(struct icode *ic, struct block *block, struct bpf_program *prog,
2978*8b26181fSAndroid Build Coastguard Worker     FILE *out)
2979*8b26181fSAndroid Build Coastguard Worker {
2980*8b26181fSAndroid Build Coastguard Worker 	int icount, noffset;
2981*8b26181fSAndroid Build Coastguard Worker 	int i;
2982*8b26181fSAndroid Build Coastguard Worker 
2983*8b26181fSAndroid Build Coastguard Worker 	if (block == NULL || isMarked(ic, block))
2984*8b26181fSAndroid Build Coastguard Worker 		return;
2985*8b26181fSAndroid Build Coastguard Worker 	Mark(ic, block);
2986*8b26181fSAndroid Build Coastguard Worker 
2987*8b26181fSAndroid Build Coastguard Worker 	icount = slength(block->stmts) + 1 + block->longjt + block->longjf;
2988*8b26181fSAndroid Build Coastguard Worker 	noffset = min(block->offset + icount, (int)prog->bf_len);
2989*8b26181fSAndroid Build Coastguard Worker 
2990*8b26181fSAndroid Build Coastguard Worker 	fprintf(out, "\tblock%u [shape=ellipse, id=\"block-%u\" label=\"BLOCK%u\\n", block->id, block->id, block->id);
2991*8b26181fSAndroid Build Coastguard Worker 	for (i = block->offset; i < noffset; i++) {
2992*8b26181fSAndroid Build Coastguard Worker 		fprintf(out, "\\n%s", bpf_image(prog->bf_insns + i, i));
2993*8b26181fSAndroid Build Coastguard Worker 	}
2994*8b26181fSAndroid Build Coastguard Worker 	fprintf(out, "\" tooltip=\"");
2995*8b26181fSAndroid Build Coastguard Worker 	for (i = 0; i < BPF_MEMWORDS; i++)
2996*8b26181fSAndroid Build Coastguard Worker 		if (block->val[i] != VAL_UNKNOWN)
2997*8b26181fSAndroid Build Coastguard Worker 			fprintf(out, "val[%d]=%d ", i, block->val[i]);
2998*8b26181fSAndroid Build Coastguard Worker 	fprintf(out, "val[A]=%d ", block->val[A_ATOM]);
2999*8b26181fSAndroid Build Coastguard Worker 	fprintf(out, "val[X]=%d", block->val[X_ATOM]);
3000*8b26181fSAndroid Build Coastguard Worker 	fprintf(out, "\"");
3001*8b26181fSAndroid Build Coastguard Worker 	if (JT(block) == NULL)
3002*8b26181fSAndroid Build Coastguard Worker 		fprintf(out, ", peripheries=2");
3003*8b26181fSAndroid Build Coastguard Worker 	fprintf(out, "];\n");
3004*8b26181fSAndroid Build Coastguard Worker 
3005*8b26181fSAndroid Build Coastguard Worker 	dot_dump_node(ic, JT(block), prog, out);
3006*8b26181fSAndroid Build Coastguard Worker 	dot_dump_node(ic, JF(block), prog, out);
3007*8b26181fSAndroid Build Coastguard Worker }
3008*8b26181fSAndroid Build Coastguard Worker 
3009*8b26181fSAndroid Build Coastguard Worker static void
dot_dump_edge(struct icode * ic,struct block * block,FILE * out)3010*8b26181fSAndroid Build Coastguard Worker dot_dump_edge(struct icode *ic, struct block *block, FILE *out)
3011*8b26181fSAndroid Build Coastguard Worker {
3012*8b26181fSAndroid Build Coastguard Worker 	if (block == NULL || isMarked(ic, block))
3013*8b26181fSAndroid Build Coastguard Worker 		return;
3014*8b26181fSAndroid Build Coastguard Worker 	Mark(ic, block);
3015*8b26181fSAndroid Build Coastguard Worker 
3016*8b26181fSAndroid Build Coastguard Worker 	if (JT(block)) {
3017*8b26181fSAndroid Build Coastguard Worker 		fprintf(out, "\t\"block%u\":se -> \"block%u\":n [label=\"T\"]; \n",
3018*8b26181fSAndroid Build Coastguard Worker 				block->id, JT(block)->id);
3019*8b26181fSAndroid Build Coastguard Worker 		fprintf(out, "\t\"block%u\":sw -> \"block%u\":n [label=\"F\"]; \n",
3020*8b26181fSAndroid Build Coastguard Worker 			   block->id, JF(block)->id);
3021*8b26181fSAndroid Build Coastguard Worker 	}
3022*8b26181fSAndroid Build Coastguard Worker 	dot_dump_edge(ic, JT(block), out);
3023*8b26181fSAndroid Build Coastguard Worker 	dot_dump_edge(ic, JF(block), out);
3024*8b26181fSAndroid Build Coastguard Worker }
3025*8b26181fSAndroid Build Coastguard Worker 
3026*8b26181fSAndroid Build Coastguard Worker /* Output the block CFG using graphviz/DOT language
3027*8b26181fSAndroid Build Coastguard Worker  * In the CFG, block's code, value index for each registers at EXIT,
3028*8b26181fSAndroid Build Coastguard Worker  * and the jump relationship is show.
3029*8b26181fSAndroid Build Coastguard Worker  *
3030*8b26181fSAndroid Build Coastguard Worker  * example DOT for BPF `ip src host 1.1.1.1' is:
3031*8b26181fSAndroid Build Coastguard Worker     digraph BPF {
3032*8b26181fSAndroid Build Coastguard Worker 	block0 [shape=ellipse, id="block-0" label="BLOCK0\n\n(000) ldh      [12]\n(001) jeq      #0x800           jt 2	jf 5" tooltip="val[A]=0 val[X]=0"];
3033*8b26181fSAndroid Build Coastguard Worker 	block1 [shape=ellipse, id="block-1" label="BLOCK1\n\n(002) ld       [26]\n(003) jeq      #0x1010101       jt 4	jf 5" tooltip="val[A]=0 val[X]=0"];
3034*8b26181fSAndroid Build Coastguard Worker 	block2 [shape=ellipse, id="block-2" label="BLOCK2\n\n(004) ret      #68" tooltip="val[A]=0 val[X]=0", peripheries=2];
3035*8b26181fSAndroid Build Coastguard Worker 	block3 [shape=ellipse, id="block-3" label="BLOCK3\n\n(005) ret      #0" tooltip="val[A]=0 val[X]=0", peripheries=2];
3036*8b26181fSAndroid Build Coastguard Worker 	"block0":se -> "block1":n [label="T"];
3037*8b26181fSAndroid Build Coastguard Worker 	"block0":sw -> "block3":n [label="F"];
3038*8b26181fSAndroid Build Coastguard Worker 	"block1":se -> "block2":n [label="T"];
3039*8b26181fSAndroid Build Coastguard Worker 	"block1":sw -> "block3":n [label="F"];
3040*8b26181fSAndroid Build Coastguard Worker     }
3041*8b26181fSAndroid Build Coastguard Worker  *
3042*8b26181fSAndroid Build Coastguard Worker  *  After install graphviz on https://www.graphviz.org/, save it as bpf.dot
3043*8b26181fSAndroid Build Coastguard Worker  *  and run `dot -Tpng -O bpf.dot' to draw the graph.
3044*8b26181fSAndroid Build Coastguard Worker  */
3045*8b26181fSAndroid Build Coastguard Worker static int
dot_dump(struct icode * ic,char * errbuf)3046*8b26181fSAndroid Build Coastguard Worker dot_dump(struct icode *ic, char *errbuf)
3047*8b26181fSAndroid Build Coastguard Worker {
3048*8b26181fSAndroid Build Coastguard Worker 	struct bpf_program f;
3049*8b26181fSAndroid Build Coastguard Worker 	FILE *out = stdout;
3050*8b26181fSAndroid Build Coastguard Worker 
3051*8b26181fSAndroid Build Coastguard Worker 	memset(bids, 0, sizeof bids);
3052*8b26181fSAndroid Build Coastguard Worker 	f.bf_insns = icode_to_fcode(ic, ic->root, &f.bf_len, errbuf);
3053*8b26181fSAndroid Build Coastguard Worker 	if (f.bf_insns == NULL)
3054*8b26181fSAndroid Build Coastguard Worker 		return -1;
3055*8b26181fSAndroid Build Coastguard Worker 
3056*8b26181fSAndroid Build Coastguard Worker 	fprintf(out, "digraph BPF {\n");
3057*8b26181fSAndroid Build Coastguard Worker 	unMarkAll(ic);
3058*8b26181fSAndroid Build Coastguard Worker 	dot_dump_node(ic, ic->root, &f, out);
3059*8b26181fSAndroid Build Coastguard Worker 	unMarkAll(ic);
3060*8b26181fSAndroid Build Coastguard Worker 	dot_dump_edge(ic, ic->root, out);
3061*8b26181fSAndroid Build Coastguard Worker 	fprintf(out, "}\n");
3062*8b26181fSAndroid Build Coastguard Worker 
3063*8b26181fSAndroid Build Coastguard Worker 	free((char *)f.bf_insns);
3064*8b26181fSAndroid Build Coastguard Worker 	return 0;
3065*8b26181fSAndroid Build Coastguard Worker }
3066*8b26181fSAndroid Build Coastguard Worker 
3067*8b26181fSAndroid Build Coastguard Worker static int
plain_dump(struct icode * ic,char * errbuf)3068*8b26181fSAndroid Build Coastguard Worker plain_dump(struct icode *ic, char *errbuf)
3069*8b26181fSAndroid Build Coastguard Worker {
3070*8b26181fSAndroid Build Coastguard Worker 	struct bpf_program f;
3071*8b26181fSAndroid Build Coastguard Worker 
3072*8b26181fSAndroid Build Coastguard Worker 	memset(bids, 0, sizeof bids);
3073*8b26181fSAndroid Build Coastguard Worker 	f.bf_insns = icode_to_fcode(ic, ic->root, &f.bf_len, errbuf);
3074*8b26181fSAndroid Build Coastguard Worker 	if (f.bf_insns == NULL)
3075*8b26181fSAndroid Build Coastguard Worker 		return -1;
3076*8b26181fSAndroid Build Coastguard Worker 	bpf_dump(&f, 1);
3077*8b26181fSAndroid Build Coastguard Worker 	putchar('\n');
3078*8b26181fSAndroid Build Coastguard Worker 	free((char *)f.bf_insns);
3079*8b26181fSAndroid Build Coastguard Worker 	return 0;
3080*8b26181fSAndroid Build Coastguard Worker }
3081*8b26181fSAndroid Build Coastguard Worker 
3082*8b26181fSAndroid Build Coastguard Worker static void
opt_dump(opt_state_t * opt_state,struct icode * ic)3083*8b26181fSAndroid Build Coastguard Worker opt_dump(opt_state_t *opt_state, struct icode *ic)
3084*8b26181fSAndroid Build Coastguard Worker {
3085*8b26181fSAndroid Build Coastguard Worker 	int status;
3086*8b26181fSAndroid Build Coastguard Worker 	char errbuf[PCAP_ERRBUF_SIZE];
3087*8b26181fSAndroid Build Coastguard Worker 
3088*8b26181fSAndroid Build Coastguard Worker 	/*
3089*8b26181fSAndroid Build Coastguard Worker 	 * If the CFG, in DOT format, is requested, output it rather than
3090*8b26181fSAndroid Build Coastguard Worker 	 * the code that would be generated from that graph.
3091*8b26181fSAndroid Build Coastguard Worker 	 */
3092*8b26181fSAndroid Build Coastguard Worker 	if (pcap_print_dot_graph)
3093*8b26181fSAndroid Build Coastguard Worker 		status = dot_dump(ic, errbuf);
3094*8b26181fSAndroid Build Coastguard Worker 	else
3095*8b26181fSAndroid Build Coastguard Worker 		status = plain_dump(ic, errbuf);
3096*8b26181fSAndroid Build Coastguard Worker 	if (status == -1)
3097*8b26181fSAndroid Build Coastguard Worker 		opt_error(opt_state, "opt_dump: icode_to_fcode failed: %s", errbuf);
3098*8b26181fSAndroid Build Coastguard Worker }
3099*8b26181fSAndroid Build Coastguard Worker #endif
3100