1*0bfacb9bSmrg /* Subroutines used for code generation for eBPF.
2*0bfacb9bSmrg    Copyright (C) 2019-2020 Free Software Foundation, Inc.
3*0bfacb9bSmrg 
4*0bfacb9bSmrg This file is part of GCC.
5*0bfacb9bSmrg 
6*0bfacb9bSmrg GCC is free software; you can redistribute it and/or modify
7*0bfacb9bSmrg it under the terms of the GNU General Public License as published by
8*0bfacb9bSmrg the Free Software Foundation; either version 3, or (at your option)
9*0bfacb9bSmrg any later version.
10*0bfacb9bSmrg 
11*0bfacb9bSmrg GCC is distributed in the hope that it will be useful,
12*0bfacb9bSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
13*0bfacb9bSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*0bfacb9bSmrg GNU General Public License for more details.
15*0bfacb9bSmrg 
16*0bfacb9bSmrg You should have received a copy of the GNU General Public License
17*0bfacb9bSmrg along with GCC; see the file COPYING3.  If not see
18*0bfacb9bSmrg <http://www.gnu.org/licenses/>.  */
19*0bfacb9bSmrg 
20*0bfacb9bSmrg #define IN_TARGET_CODE 1
21*0bfacb9bSmrg 
22*0bfacb9bSmrg #include "config.h"
23*0bfacb9bSmrg #include "system.h"
24*0bfacb9bSmrg #include "coretypes.h"
25*0bfacb9bSmrg #include "tm.h"
26*0bfacb9bSmrg #include "rtl.h"
27*0bfacb9bSmrg #include "regs.h"
28*0bfacb9bSmrg #include "insn-config.h"
29*0bfacb9bSmrg #include "insn-attr.h"
30*0bfacb9bSmrg #include "recog.h"
31*0bfacb9bSmrg #include "output.h"
32*0bfacb9bSmrg #include "alias.h"
33*0bfacb9bSmrg #include "tree.h"
34*0bfacb9bSmrg #include "stringpool.h"
35*0bfacb9bSmrg #include "attribs.h"
36*0bfacb9bSmrg #include "varasm.h"
37*0bfacb9bSmrg #include "stor-layout.h"
38*0bfacb9bSmrg #include "calls.h"
39*0bfacb9bSmrg #include "function.h"
40*0bfacb9bSmrg #include "explow.h"
41*0bfacb9bSmrg #include "memmodel.h"
42*0bfacb9bSmrg #include "emit-rtl.h"
43*0bfacb9bSmrg #include "reload.h"
44*0bfacb9bSmrg #include "tm_p.h"
45*0bfacb9bSmrg #include "target.h"
46*0bfacb9bSmrg #include "target-def.h"
47*0bfacb9bSmrg #include "basic-block.h"
48*0bfacb9bSmrg #include "expr.h"
49*0bfacb9bSmrg #include "optabs.h"
50*0bfacb9bSmrg #include "bitmap.h"
51*0bfacb9bSmrg #include "df.h"
52*0bfacb9bSmrg #include "c-family/c-common.h"
53*0bfacb9bSmrg #include "diagnostic.h"
54*0bfacb9bSmrg #include "builtins.h"
55*0bfacb9bSmrg #include "predict.h"
56*0bfacb9bSmrg #include "langhooks.h"
57*0bfacb9bSmrg 
58*0bfacb9bSmrg /* Per-function machine data.  */
59*0bfacb9bSmrg struct GTY(()) machine_function
60*0bfacb9bSmrg {
61*0bfacb9bSmrg   /* Number of bytes saved on the stack for local variables.  */
62*0bfacb9bSmrg   int local_vars_size;
63*0bfacb9bSmrg 
64*0bfacb9bSmrg   /* Number of bytes saved on the stack for callee-saved
65*0bfacb9bSmrg      registers.  */
66*0bfacb9bSmrg   int callee_saved_reg_size;
67*0bfacb9bSmrg };
68*0bfacb9bSmrg 
69*0bfacb9bSmrg /* Handle an attribute requiring a FUNCTION_DECL;
70*0bfacb9bSmrg    arguments as in struct attribute_spec.handler.  */
71*0bfacb9bSmrg 
72*0bfacb9bSmrg static tree
bpf_handle_fndecl_attribute(tree * node,tree name,tree args,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)73*0bfacb9bSmrg bpf_handle_fndecl_attribute (tree *node, tree name,
74*0bfacb9bSmrg 			     tree args,
75*0bfacb9bSmrg 			     int flags ATTRIBUTE_UNUSED,
76*0bfacb9bSmrg 			     bool *no_add_attrs)
77*0bfacb9bSmrg {
78*0bfacb9bSmrg   if (TREE_CODE (*node) != FUNCTION_DECL)
79*0bfacb9bSmrg     {
80*0bfacb9bSmrg       warning (OPT_Wattributes, "%qE attribute only applies to functions",
81*0bfacb9bSmrg 	       name);
82*0bfacb9bSmrg       *no_add_attrs = true;
83*0bfacb9bSmrg     }
84*0bfacb9bSmrg 
85*0bfacb9bSmrg   if (is_attribute_p ("kernel_helper", name))
86*0bfacb9bSmrg     {
87*0bfacb9bSmrg       if (args)
88*0bfacb9bSmrg 	{
89*0bfacb9bSmrg 	  tree cst = TREE_VALUE (args);
90*0bfacb9bSmrg 	  if (TREE_CODE (cst) != INTEGER_CST)
91*0bfacb9bSmrg 	    {
92*0bfacb9bSmrg 	      warning (OPT_Wattributes, "%qE attribute requires an integer argument",
93*0bfacb9bSmrg 		       name);
94*0bfacb9bSmrg 	      *no_add_attrs = true;
95*0bfacb9bSmrg 	    }
96*0bfacb9bSmrg 	}
97*0bfacb9bSmrg       else
98*0bfacb9bSmrg 	{
99*0bfacb9bSmrg 	  warning (OPT_Wattributes, "%qE requires an argument", name);
100*0bfacb9bSmrg 	  *no_add_attrs = true;
101*0bfacb9bSmrg 	}
102*0bfacb9bSmrg     }
103*0bfacb9bSmrg 
104*0bfacb9bSmrg   return NULL_TREE;
105*0bfacb9bSmrg }
106*0bfacb9bSmrg 
107*0bfacb9bSmrg /* Target-specific attributes.  */
108*0bfacb9bSmrg 
109*0bfacb9bSmrg static const struct attribute_spec bpf_attribute_table[] =
110*0bfacb9bSmrg {
111*0bfacb9bSmrg   /* Syntax: { name, min_len, max_len, decl_required, type_required,
112*0bfacb9bSmrg 	       function_type_required, affects_type_identity, handler,
113*0bfacb9bSmrg 	       exclude } */
114*0bfacb9bSmrg 
115*0bfacb9bSmrg  /* Attribute to mark function prototypes as kernel helpers.  */
116*0bfacb9bSmrg  { "kernel_helper", 1, 1, true, false, false, false,
117*0bfacb9bSmrg    bpf_handle_fndecl_attribute, NULL },
118*0bfacb9bSmrg 
119*0bfacb9bSmrg  /* The last attribute spec is set to be NULL.  */
120*0bfacb9bSmrg  { NULL,	0,  0, false, false, false, false, NULL, NULL }
121*0bfacb9bSmrg };
122*0bfacb9bSmrg 
123*0bfacb9bSmrg #undef TARGET_ATTRIBUTE_TABLE
124*0bfacb9bSmrg #define TARGET_ATTRIBUTE_TABLE bpf_attribute_table
125*0bfacb9bSmrg 
126*0bfacb9bSmrg /* Data structures for the eBPF specific built-ins.  */
127*0bfacb9bSmrg 
128*0bfacb9bSmrg /* Maximum number of arguments taken by a builtin function, plus
129*0bfacb9bSmrg    one.  */
130*0bfacb9bSmrg #define BPF_BUILTIN_MAX_ARGS 5
131*0bfacb9bSmrg 
132*0bfacb9bSmrg enum bpf_builtins
133*0bfacb9bSmrg {
134*0bfacb9bSmrg   BPF_BUILTIN_UNUSED = 0,
135*0bfacb9bSmrg   /* Built-ins for non-generic loads and stores.  */
136*0bfacb9bSmrg   BPF_BUILTIN_LOAD_BYTE,
137*0bfacb9bSmrg   BPF_BUILTIN_LOAD_HALF,
138*0bfacb9bSmrg   BPF_BUILTIN_LOAD_WORD,
139*0bfacb9bSmrg   BPF_BUILTIN_MAX,
140*0bfacb9bSmrg };
141*0bfacb9bSmrg 
142*0bfacb9bSmrg static GTY (()) tree bpf_builtins[(int) BPF_BUILTIN_MAX];
143*0bfacb9bSmrg 
144*0bfacb9bSmrg /* Initialize the per-function machine status.  */
145*0bfacb9bSmrg 
146*0bfacb9bSmrg static struct machine_function *
bpf_init_machine_status(void)147*0bfacb9bSmrg bpf_init_machine_status (void)
148*0bfacb9bSmrg {
149*0bfacb9bSmrg   /* Note this initializes all fields to 0, which is just OK for
150*0bfacb9bSmrg      us.  */
151*0bfacb9bSmrg   return ggc_cleared_alloc<machine_function> ();
152*0bfacb9bSmrg }
153*0bfacb9bSmrg 
154*0bfacb9bSmrg /* Override options and do some other initialization.  */
155*0bfacb9bSmrg 
156*0bfacb9bSmrg static void
bpf_option_override(void)157*0bfacb9bSmrg bpf_option_override (void)
158*0bfacb9bSmrg {
159*0bfacb9bSmrg   /* Set the initializer for the per-function status structure.  */
160*0bfacb9bSmrg   init_machine_status = bpf_init_machine_status;
161*0bfacb9bSmrg }
162*0bfacb9bSmrg 
163*0bfacb9bSmrg #undef TARGET_OPTION_OVERRIDE
164*0bfacb9bSmrg #define TARGET_OPTION_OVERRIDE bpf_option_override
165*0bfacb9bSmrg 
166*0bfacb9bSmrg /* Define target-specific CPP macros.  This function in used in the
167*0bfacb9bSmrg    definition of TARGET_CPU_CPP_BUILTINS in bpf.h */
168*0bfacb9bSmrg 
169*0bfacb9bSmrg #define builtin_define(TXT) cpp_define (pfile, TXT)
170*0bfacb9bSmrg 
171*0bfacb9bSmrg void
bpf_target_macros(cpp_reader * pfile)172*0bfacb9bSmrg bpf_target_macros (cpp_reader *pfile)
173*0bfacb9bSmrg {
174*0bfacb9bSmrg   builtin_define ("__BPF__");
175*0bfacb9bSmrg 
176*0bfacb9bSmrg   if (TARGET_BIG_ENDIAN)
177*0bfacb9bSmrg     builtin_define ("__BPF_BIG_ENDIAN__");
178*0bfacb9bSmrg   else
179*0bfacb9bSmrg     builtin_define ("__BPF_LITTLE_ENDIAN__");
180*0bfacb9bSmrg 
181*0bfacb9bSmrg   /* Define BPF_KERNEL_VERSION_CODE */
182*0bfacb9bSmrg   {
183*0bfacb9bSmrg     const char *version_code;
184*0bfacb9bSmrg     char *kernel_version_code;
185*0bfacb9bSmrg 
186*0bfacb9bSmrg     switch (bpf_kernel)
187*0bfacb9bSmrg       {
188*0bfacb9bSmrg       case LINUX_V4_0: version_code = "0x40000"; break;
189*0bfacb9bSmrg       case LINUX_V4_1: version_code = "0x40100"; break;
190*0bfacb9bSmrg       case LINUX_V4_2: version_code = "0x40200"; break;
191*0bfacb9bSmrg       case LINUX_V4_3: version_code = "0x40300"; break;
192*0bfacb9bSmrg       case LINUX_V4_4: version_code = "0x40400"; break;
193*0bfacb9bSmrg       case LINUX_V4_5: version_code = "0x40500"; break;
194*0bfacb9bSmrg       case LINUX_V4_6: version_code = "0x40600"; break;
195*0bfacb9bSmrg       case LINUX_V4_7: version_code = "0x40700"; break;
196*0bfacb9bSmrg       case LINUX_V4_8: version_code = "0x40800"; break;
197*0bfacb9bSmrg       case LINUX_V4_9: version_code = "0x40900"; break;
198*0bfacb9bSmrg       case LINUX_V4_10: version_code = "0x40a00"; break;
199*0bfacb9bSmrg       case LINUX_V4_11: version_code = "0x40b00"; break;
200*0bfacb9bSmrg       case LINUX_V4_12: version_code = "0x40c00"; break;
201*0bfacb9bSmrg       case LINUX_V4_13: version_code = "0x40d00"; break;
202*0bfacb9bSmrg       case LINUX_V4_14: version_code = "0x40e00"; break;
203*0bfacb9bSmrg       case LINUX_V4_15: version_code = "0x40f00"; break;
204*0bfacb9bSmrg       case LINUX_V4_16: version_code = "0x41000"; break;
205*0bfacb9bSmrg       case LINUX_V4_17: version_code = "0x42000"; break;
206*0bfacb9bSmrg       case LINUX_V4_18: version_code = "0x43000"; break;
207*0bfacb9bSmrg       case LINUX_V4_19: version_code = "0x44000"; break;
208*0bfacb9bSmrg       case LINUX_V4_20: version_code = "0x45000"; break;
209*0bfacb9bSmrg       case LINUX_V5_0: version_code = "0x50000"; break;
210*0bfacb9bSmrg       case LINUX_V5_1: version_code = "0x50100"; break;
211*0bfacb9bSmrg       case LINUX_V5_2: version_code = "0x50200"; break;
212*0bfacb9bSmrg       default:
213*0bfacb9bSmrg 	gcc_unreachable ();
214*0bfacb9bSmrg       }
215*0bfacb9bSmrg 
216*0bfacb9bSmrg     kernel_version_code = ACONCAT (("__BPF_KERNEL_VERSION_CODE__=",
217*0bfacb9bSmrg 				    version_code, NULL));
218*0bfacb9bSmrg     builtin_define (kernel_version_code);
219*0bfacb9bSmrg   }
220*0bfacb9bSmrg }
221*0bfacb9bSmrg 
222*0bfacb9bSmrg /* Return an RTX representing the place where a function returns or
223*0bfacb9bSmrg    receives a value of data type RET_TYPE, a tree node representing a
224*0bfacb9bSmrg    data type.  */
225*0bfacb9bSmrg 
226*0bfacb9bSmrg static rtx
bpf_function_value(const_tree ret_type,const_tree fntype_or_decl,bool outgoing ATTRIBUTE_UNUSED)227*0bfacb9bSmrg bpf_function_value (const_tree ret_type,
228*0bfacb9bSmrg 		    const_tree fntype_or_decl,
229*0bfacb9bSmrg 		    bool outgoing ATTRIBUTE_UNUSED)
230*0bfacb9bSmrg {
231*0bfacb9bSmrg   enum machine_mode mode;
232*0bfacb9bSmrg   int unsignedp;
233*0bfacb9bSmrg 
234*0bfacb9bSmrg   mode = TYPE_MODE (ret_type);
235*0bfacb9bSmrg   if (INTEGRAL_TYPE_P (ret_type))
236*0bfacb9bSmrg     mode = promote_function_mode (ret_type, mode, &unsignedp,
237*0bfacb9bSmrg 				  fntype_or_decl, 1);
238*0bfacb9bSmrg 
239*0bfacb9bSmrg   return gen_rtx_REG (mode, BPF_R0);
240*0bfacb9bSmrg }
241*0bfacb9bSmrg 
242*0bfacb9bSmrg #undef TARGET_FUNCTION_VALUE
243*0bfacb9bSmrg #define TARGET_FUNCTION_VALUE bpf_function_value
244*0bfacb9bSmrg 
245*0bfacb9bSmrg /* Return true if REGNO is the number of a hard register in which the
246*0bfacb9bSmrg    values of called function may come back.  */
247*0bfacb9bSmrg 
248*0bfacb9bSmrg static bool
bpf_function_value_regno_p(const unsigned int regno)249*0bfacb9bSmrg bpf_function_value_regno_p (const unsigned int regno)
250*0bfacb9bSmrg {
251*0bfacb9bSmrg   return (regno == BPF_R0);
252*0bfacb9bSmrg }
253*0bfacb9bSmrg 
254*0bfacb9bSmrg #undef TARGET_FUNCTION_VALUE_REGNO_P
255*0bfacb9bSmrg #define TARGET_FUNCTION_VALUE_REGNO_P bpf_function_value_regno_p
256*0bfacb9bSmrg 
257*0bfacb9bSmrg /* Compute the size of the function's stack frame, including the local
258*0bfacb9bSmrg    area and the register-save area.  */
259*0bfacb9bSmrg 
260*0bfacb9bSmrg static void
bpf_compute_frame_layout(void)261*0bfacb9bSmrg bpf_compute_frame_layout (void)
262*0bfacb9bSmrg {
263*0bfacb9bSmrg   int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
264*0bfacb9bSmrg   int padding_locals, regno;
265*0bfacb9bSmrg 
266*0bfacb9bSmrg   /* Set the space used in the stack by local variables.  This is
267*0bfacb9bSmrg      rounded up to respect the minimum stack alignment.  */
268*0bfacb9bSmrg   cfun->machine->local_vars_size = get_frame_size ();
269*0bfacb9bSmrg 
270*0bfacb9bSmrg   padding_locals = cfun->machine->local_vars_size % stack_alignment;
271*0bfacb9bSmrg   if (padding_locals)
272*0bfacb9bSmrg     padding_locals = stack_alignment - padding_locals;
273*0bfacb9bSmrg 
274*0bfacb9bSmrg   cfun->machine->local_vars_size += padding_locals;
275*0bfacb9bSmrg 
276*0bfacb9bSmrg   if (TARGET_XBPF)
277*0bfacb9bSmrg     {
278*0bfacb9bSmrg       /* Set the space used in the stack by callee-saved used
279*0bfacb9bSmrg 	 registers in the current function.  There is no need to round
280*0bfacb9bSmrg 	 up, since the registers are all 8 bytes wide.  */
281*0bfacb9bSmrg       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
282*0bfacb9bSmrg 	if ((df_regs_ever_live_p (regno)
283*0bfacb9bSmrg 	     && !call_used_or_fixed_reg_p (regno))
284*0bfacb9bSmrg 	    || (cfun->calls_alloca
285*0bfacb9bSmrg 		&& regno == STACK_POINTER_REGNUM))
286*0bfacb9bSmrg 	  cfun->machine->callee_saved_reg_size += 8;
287*0bfacb9bSmrg     }
288*0bfacb9bSmrg 
289*0bfacb9bSmrg   /* Check that the total size of the frame doesn't exceed the limit
290*0bfacb9bSmrg      imposed by eBPF.  */
291*0bfacb9bSmrg   if ((cfun->machine->local_vars_size
292*0bfacb9bSmrg        + cfun->machine->callee_saved_reg_size) > bpf_frame_limit)
293*0bfacb9bSmrg     {
294*0bfacb9bSmrg       static int stack_limit_exceeded = 0;
295*0bfacb9bSmrg 
296*0bfacb9bSmrg       if (!stack_limit_exceeded)
297*0bfacb9bSmrg 	error ("eBPF stack limit exceeded");
298*0bfacb9bSmrg       stack_limit_exceeded = 1;
299*0bfacb9bSmrg     }
300*0bfacb9bSmrg }
301*0bfacb9bSmrg 
302*0bfacb9bSmrg #undef TARGET_COMPUTE_FRAME_LAYOUT
303*0bfacb9bSmrg #define TARGET_COMPUTE_FRAME_LAYOUT bpf_compute_frame_layout
304*0bfacb9bSmrg 
305*0bfacb9bSmrg /* Expand to the instructions in a function prologue.  This function
306*0bfacb9bSmrg    is called when expanding the 'prologue' pattern in bpf.md.  */
307*0bfacb9bSmrg 
308*0bfacb9bSmrg void
bpf_expand_prologue(void)309*0bfacb9bSmrg bpf_expand_prologue (void)
310*0bfacb9bSmrg {
311*0bfacb9bSmrg   rtx insn;
312*0bfacb9bSmrg   HOST_WIDE_INT size;
313*0bfacb9bSmrg 
314*0bfacb9bSmrg   size = (cfun->machine->local_vars_size
315*0bfacb9bSmrg 	  + cfun->machine->callee_saved_reg_size);
316*0bfacb9bSmrg 
317*0bfacb9bSmrg   /* The BPF "hardware" provides a fresh new set of registers for each
318*0bfacb9bSmrg      called function, some of which are initialized to the values of
319*0bfacb9bSmrg      the arguments passed in the first five registers.  In doing so,
320*0bfacb9bSmrg      it saves the values of the registers of the caller, and restored
321*0bfacb9bSmrg      them upon returning.  Therefore, there is no need to save the
322*0bfacb9bSmrg      callee-saved registers here.  What is worse, the kernel
323*0bfacb9bSmrg      implementation refuses to run programs in which registers are
324*0bfacb9bSmrg      referred before being initialized.  */
325*0bfacb9bSmrg   if (TARGET_XBPF)
326*0bfacb9bSmrg     {
327*0bfacb9bSmrg       int regno;
328*0bfacb9bSmrg       int fp_offset = -cfun->machine->local_vars_size;
329*0bfacb9bSmrg 
330*0bfacb9bSmrg       /* Save callee-saved hard registes.  The register-save-area
331*0bfacb9bSmrg 	 starts right after the local variables.  */
332*0bfacb9bSmrg       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
333*0bfacb9bSmrg 	{
334*0bfacb9bSmrg 	  if ((df_regs_ever_live_p (regno)
335*0bfacb9bSmrg 	       && !call_used_or_fixed_reg_p (regno))
336*0bfacb9bSmrg 	      || (cfun->calls_alloca
337*0bfacb9bSmrg 		  && regno == STACK_POINTER_REGNUM))
338*0bfacb9bSmrg 	    {
339*0bfacb9bSmrg 	      rtx mem;
340*0bfacb9bSmrg 
341*0bfacb9bSmrg 	      if (!IN_RANGE (fp_offset, -1 - 0x7fff, 0x7fff))
342*0bfacb9bSmrg 		/* This has been already reported as an error in
343*0bfacb9bSmrg 		   bpf_compute_frame_layout. */
344*0bfacb9bSmrg 		break;
345*0bfacb9bSmrg 	      else
346*0bfacb9bSmrg 		{
347*0bfacb9bSmrg 		  mem = gen_frame_mem (DImode,
348*0bfacb9bSmrg 				       plus_constant (DImode,
349*0bfacb9bSmrg 						      hard_frame_pointer_rtx,
350*0bfacb9bSmrg 						      fp_offset - 8));
351*0bfacb9bSmrg 		  insn = emit_move_insn (mem, gen_rtx_REG (DImode, regno));
352*0bfacb9bSmrg 		  RTX_FRAME_RELATED_P (insn) = 1;
353*0bfacb9bSmrg 		  fp_offset -= 8;
354*0bfacb9bSmrg 		}
355*0bfacb9bSmrg 	    }
356*0bfacb9bSmrg 	}
357*0bfacb9bSmrg     }
358*0bfacb9bSmrg 
359*0bfacb9bSmrg   /* Set the stack pointer, if the function allocates space
360*0bfacb9bSmrg      dynamically.  Note that the value of %sp should be directly
361*0bfacb9bSmrg      derived from %fp, for the kernel verifier to track it as a stack
362*0bfacb9bSmrg      accessor.  */
363*0bfacb9bSmrg   if (cfun->calls_alloca)
364*0bfacb9bSmrg     {
365*0bfacb9bSmrg       insn = emit_move_insn (stack_pointer_rtx,
366*0bfacb9bSmrg 			     hard_frame_pointer_rtx);
367*0bfacb9bSmrg       RTX_FRAME_RELATED_P (insn) = 1;
368*0bfacb9bSmrg 
369*0bfacb9bSmrg       if (size > 0)
370*0bfacb9bSmrg 	{
371*0bfacb9bSmrg 	  insn = emit_insn (gen_rtx_SET (stack_pointer_rtx,
372*0bfacb9bSmrg 					 gen_rtx_PLUS (Pmode,
373*0bfacb9bSmrg 						       stack_pointer_rtx,
374*0bfacb9bSmrg 						       GEN_INT (-size))));
375*0bfacb9bSmrg 	  RTX_FRAME_RELATED_P (insn) = 1;
376*0bfacb9bSmrg 	}
377*0bfacb9bSmrg     }
378*0bfacb9bSmrg }
379*0bfacb9bSmrg 
380*0bfacb9bSmrg /* Expand to the instructions in a function epilogue.  This function
381*0bfacb9bSmrg    is called when expanding the 'epilogue' pattern in bpf.md.  */
382*0bfacb9bSmrg 
383*0bfacb9bSmrg void
bpf_expand_epilogue(void)384*0bfacb9bSmrg bpf_expand_epilogue (void)
385*0bfacb9bSmrg {
386*0bfacb9bSmrg   /* See note in bpf_expand_prologue for an explanation on why we are
387*0bfacb9bSmrg      not restoring callee-saved registers in BPF.  */
388*0bfacb9bSmrg   if (TARGET_XBPF)
389*0bfacb9bSmrg     {
390*0bfacb9bSmrg       rtx insn;
391*0bfacb9bSmrg       int regno;
392*0bfacb9bSmrg       int fp_offset = -cfun->machine->local_vars_size;
393*0bfacb9bSmrg 
394*0bfacb9bSmrg       /* Restore callee-saved hard registes from the stack.  */
395*0bfacb9bSmrg       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
396*0bfacb9bSmrg 	{
397*0bfacb9bSmrg 	  if ((df_regs_ever_live_p (regno)
398*0bfacb9bSmrg 	       && !call_used_or_fixed_reg_p (regno))
399*0bfacb9bSmrg 	      || (cfun->calls_alloca
400*0bfacb9bSmrg 		  && regno == STACK_POINTER_REGNUM))
401*0bfacb9bSmrg 	    {
402*0bfacb9bSmrg 	      rtx mem;
403*0bfacb9bSmrg 
404*0bfacb9bSmrg 	      if (!IN_RANGE (fp_offset, -1 - 0x7fff, 0x7fff))
405*0bfacb9bSmrg 		/* This has been already reported as an error in
406*0bfacb9bSmrg 		   bpf_compute_frame_layout. */
407*0bfacb9bSmrg 		break;
408*0bfacb9bSmrg 	      else
409*0bfacb9bSmrg 		{
410*0bfacb9bSmrg 		  mem = gen_frame_mem (DImode,
411*0bfacb9bSmrg 				       plus_constant (DImode,
412*0bfacb9bSmrg 						      hard_frame_pointer_rtx,
413*0bfacb9bSmrg 						      fp_offset - 8));
414*0bfacb9bSmrg 		  insn = emit_move_insn (gen_rtx_REG (DImode, regno), mem);
415*0bfacb9bSmrg 		  RTX_FRAME_RELATED_P (insn) = 1;
416*0bfacb9bSmrg 		  fp_offset -= 8;
417*0bfacb9bSmrg 		}
418*0bfacb9bSmrg 	    }
419*0bfacb9bSmrg 	}
420*0bfacb9bSmrg     }
421*0bfacb9bSmrg 
422*0bfacb9bSmrg   emit_jump_insn (gen_exit ());
423*0bfacb9bSmrg }
424*0bfacb9bSmrg 
425*0bfacb9bSmrg /* Return the initial difference between the specified pair of
426*0bfacb9bSmrg    registers.  The registers that can figure in FROM, and TO, are
427*0bfacb9bSmrg    specified by ELIMINABLE_REGS in bpf.h.
428*0bfacb9bSmrg 
429*0bfacb9bSmrg    This function is used in the definition of
430*0bfacb9bSmrg    INITIAL_ELIMINATION_OFFSET in bpf.h  */
431*0bfacb9bSmrg 
432*0bfacb9bSmrg HOST_WIDE_INT
bpf_initial_elimination_offset(int from,int to)433*0bfacb9bSmrg bpf_initial_elimination_offset (int from, int to)
434*0bfacb9bSmrg {
435*0bfacb9bSmrg   HOST_WIDE_INT ret;
436*0bfacb9bSmrg 
437*0bfacb9bSmrg   if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
438*0bfacb9bSmrg     ret = (cfun->machine->local_vars_size
439*0bfacb9bSmrg 	   + cfun->machine->callee_saved_reg_size);
440*0bfacb9bSmrg   else if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
441*0bfacb9bSmrg     ret = 0;
442*0bfacb9bSmrg   else
443*0bfacb9bSmrg     gcc_unreachable ();
444*0bfacb9bSmrg 
445*0bfacb9bSmrg   return ret;
446*0bfacb9bSmrg }
447*0bfacb9bSmrg 
448*0bfacb9bSmrg /* Return the number of consecutive hard registers, starting at
449*0bfacb9bSmrg    register number REGNO, required to hold a value of mode MODE.  */
450*0bfacb9bSmrg 
451*0bfacb9bSmrg static unsigned int
bpf_hard_regno_nregs(unsigned int regno ATTRIBUTE_UNUSED,enum machine_mode mode)452*0bfacb9bSmrg bpf_hard_regno_nregs (unsigned int regno ATTRIBUTE_UNUSED,
453*0bfacb9bSmrg 		      enum machine_mode mode)
454*0bfacb9bSmrg {
455*0bfacb9bSmrg   return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
456*0bfacb9bSmrg }
457*0bfacb9bSmrg 
458*0bfacb9bSmrg #undef TARGET_HARD_REGNO_NREGS
459*0bfacb9bSmrg #define TARGET_HARD_REGNO_NREGS bpf_hard_regno_nregs
460*0bfacb9bSmrg 
461*0bfacb9bSmrg /* Return true if it is permissible to store a value of mode MODE in
462*0bfacb9bSmrg    hard register number REGNO, or in several registers starting with
463*0bfacb9bSmrg    that one.  */
464*0bfacb9bSmrg 
465*0bfacb9bSmrg static bool
bpf_hard_regno_mode_ok(unsigned int regno ATTRIBUTE_UNUSED,enum machine_mode mode)466*0bfacb9bSmrg bpf_hard_regno_mode_ok (unsigned int regno ATTRIBUTE_UNUSED,
467*0bfacb9bSmrg 			enum machine_mode mode)
468*0bfacb9bSmrg {
469*0bfacb9bSmrg   switch (mode)
470*0bfacb9bSmrg     {
471*0bfacb9bSmrg     case E_SImode:
472*0bfacb9bSmrg     case E_DImode:
473*0bfacb9bSmrg     case E_HImode:
474*0bfacb9bSmrg     case E_QImode:
475*0bfacb9bSmrg     case E_TImode:
476*0bfacb9bSmrg     case E_SFmode:
477*0bfacb9bSmrg     case E_DFmode:
478*0bfacb9bSmrg       return true;
479*0bfacb9bSmrg     default:
480*0bfacb9bSmrg       return false;
481*0bfacb9bSmrg     }
482*0bfacb9bSmrg }
483*0bfacb9bSmrg 
484*0bfacb9bSmrg #undef TARGET_HARD_REGNO_MODE_OK
485*0bfacb9bSmrg #define TARGET_HARD_REGNO_MODE_OK bpf_hard_regno_mode_ok
486*0bfacb9bSmrg 
487*0bfacb9bSmrg /* Return true if a function must have and use a frame pointer.  */
488*0bfacb9bSmrg 
489*0bfacb9bSmrg static bool
bpf_frame_pointer_required(void)490*0bfacb9bSmrg bpf_frame_pointer_required (void)
491*0bfacb9bSmrg {
492*0bfacb9bSmrg   /* We do not have a stack pointer, so we absolutely depend on the
493*0bfacb9bSmrg      frame-pointer in order to access the stack... and fishes walk and
494*0bfacb9bSmrg      pigs fly glglgl */
495*0bfacb9bSmrg   return true;
496*0bfacb9bSmrg }
497*0bfacb9bSmrg 
498*0bfacb9bSmrg #undef TARGET_FRAME_POINTER_REQUIRED
499*0bfacb9bSmrg #define TARGET_FRAME_POINTER_REQUIRED bpf_frame_pointer_required
500*0bfacb9bSmrg 
501*0bfacb9bSmrg /* Return `true' if the given RTX X is a valid base for an indirect
502*0bfacb9bSmrg    memory access.  STRICT has the same meaning than in
503*0bfacb9bSmrg    bpf_legitimate_address_p.  */
504*0bfacb9bSmrg 
505*0bfacb9bSmrg static inline bool
bpf_address_base_p(rtx x,bool strict)506*0bfacb9bSmrg bpf_address_base_p (rtx x, bool strict)
507*0bfacb9bSmrg {
508*0bfacb9bSmrg   return (GET_CODE (x) == REG
509*0bfacb9bSmrg 	  && (REGNO (x) < 11
510*0bfacb9bSmrg 	      || (!strict && REGNO (x) >= FIRST_PSEUDO_REGISTER)));
511*0bfacb9bSmrg }
512*0bfacb9bSmrg 
513*0bfacb9bSmrg /* Return true if X (a RTX) is a legitimate memory address on the
514*0bfacb9bSmrg    target machine for a memory operand of mode MODE.  */
515*0bfacb9bSmrg 
516*0bfacb9bSmrg static bool
bpf_legitimate_address_p(machine_mode mode ATTRIBUTE_UNUSED,rtx x,bool strict)517*0bfacb9bSmrg bpf_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
518*0bfacb9bSmrg 			  rtx x,
519*0bfacb9bSmrg 			  bool strict)
520*0bfacb9bSmrg {
521*0bfacb9bSmrg   switch (GET_CODE (x))
522*0bfacb9bSmrg     {
523*0bfacb9bSmrg     case REG:
524*0bfacb9bSmrg       return bpf_address_base_p (x, strict);
525*0bfacb9bSmrg 
526*0bfacb9bSmrg     case PLUS:
527*0bfacb9bSmrg       {
528*0bfacb9bSmrg 	/* Accept (PLUS ADDR_BASE CONST_INT), provided CONST_INT fits
529*0bfacb9bSmrg 	   in a signed 16-bit.
530*0bfacb9bSmrg 
531*0bfacb9bSmrg 	   Note that LABEL_REF and SYMBOL_REF are not allowed in
532*0bfacb9bSmrg 	   REG+IMM addresses, because it is almost certain they will
533*0bfacb9bSmrg 	   overload the offset field.  */
534*0bfacb9bSmrg 
535*0bfacb9bSmrg 	rtx x0 = XEXP (x, 0);
536*0bfacb9bSmrg 	rtx x1 = XEXP (x, 1);
537*0bfacb9bSmrg 
538*0bfacb9bSmrg 	if (bpf_address_base_p (x0, strict) && GET_CODE (x1) == CONST_INT)
539*0bfacb9bSmrg 	  return IN_RANGE (INTVAL (x1), -1 - 0x7fff, 0x7fff);
540*0bfacb9bSmrg 
541*0bfacb9bSmrg 	break;
542*0bfacb9bSmrg       }
543*0bfacb9bSmrg     default:
544*0bfacb9bSmrg       break;
545*0bfacb9bSmrg     }
546*0bfacb9bSmrg 
547*0bfacb9bSmrg   return false;
548*0bfacb9bSmrg }
549*0bfacb9bSmrg 
550*0bfacb9bSmrg #undef TARGET_LEGITIMATE_ADDRESS_P
551*0bfacb9bSmrg #define TARGET_LEGITIMATE_ADDRESS_P bpf_legitimate_address_p
552*0bfacb9bSmrg 
553*0bfacb9bSmrg /* Describe the relative costs of RTL expressions.  Return true when
554*0bfacb9bSmrg    all subexpressions of X have been processed, and false when
555*0bfacb9bSmrg    `rtx_cost' should recurse.  */
556*0bfacb9bSmrg 
557*0bfacb9bSmrg static bool
bpf_rtx_costs(rtx x ATTRIBUTE_UNUSED,enum machine_mode mode ATTRIBUTE_UNUSED,int outer_code ATTRIBUTE_UNUSED,int opno ATTRIBUTE_UNUSED,int * total ATTRIBUTE_UNUSED,bool speed ATTRIBUTE_UNUSED)558*0bfacb9bSmrg bpf_rtx_costs (rtx x ATTRIBUTE_UNUSED,
559*0bfacb9bSmrg 	       enum machine_mode mode ATTRIBUTE_UNUSED,
560*0bfacb9bSmrg 	       int outer_code ATTRIBUTE_UNUSED,
561*0bfacb9bSmrg 	       int opno ATTRIBUTE_UNUSED,
562*0bfacb9bSmrg                int *total ATTRIBUTE_UNUSED,
563*0bfacb9bSmrg 	       bool speed ATTRIBUTE_UNUSED)
564*0bfacb9bSmrg {
565*0bfacb9bSmrg   /* To be written.  */
566*0bfacb9bSmrg   return false;
567*0bfacb9bSmrg }
568*0bfacb9bSmrg 
569*0bfacb9bSmrg #undef TARGET_RTX_COSTS
570*0bfacb9bSmrg #define TARGET_RTX_COSTS bpf_rtx_costs
571*0bfacb9bSmrg 
572*0bfacb9bSmrg /* Return true if an argument at the position indicated by CUM should
573*0bfacb9bSmrg    be passed by reference.  If the hook returns true, a copy of that
574*0bfacb9bSmrg    argument is made in memory and a pointer to the argument is passed
575*0bfacb9bSmrg    instead of the argument itself.  */
576*0bfacb9bSmrg 
577*0bfacb9bSmrg static bool
bpf_pass_by_reference(cumulative_args_t cum ATTRIBUTE_UNUSED,const function_arg_info & arg)578*0bfacb9bSmrg bpf_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
579*0bfacb9bSmrg 		       const function_arg_info &arg)
580*0bfacb9bSmrg {
581*0bfacb9bSmrg   unsigned num_bytes = arg.type_size_in_bytes ();
582*0bfacb9bSmrg 
583*0bfacb9bSmrg   /* Pass aggregates and values bigger than 5 words by reference.
584*0bfacb9bSmrg      Everything else is passed by copy.  */
585*0bfacb9bSmrg   return (arg.aggregate_type_p () || (num_bytes > 8*5));
586*0bfacb9bSmrg }
587*0bfacb9bSmrg 
588*0bfacb9bSmrg #undef TARGET_PASS_BY_REFERENCE
589*0bfacb9bSmrg #define TARGET_PASS_BY_REFERENCE bpf_pass_by_reference
590*0bfacb9bSmrg 
591*0bfacb9bSmrg /* Return a RTX indicating whether a function argument is passed in a
592*0bfacb9bSmrg    register and if so, which register.  */
593*0bfacb9bSmrg 
594*0bfacb9bSmrg static rtx
bpf_function_arg(cumulative_args_t ca,const function_arg_info & arg)595*0bfacb9bSmrg bpf_function_arg (cumulative_args_t ca, const function_arg_info &arg)
596*0bfacb9bSmrg {
597*0bfacb9bSmrg   CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
598*0bfacb9bSmrg 
599*0bfacb9bSmrg   if (*cum < 5)
600*0bfacb9bSmrg     return gen_rtx_REG (arg.mode, *cum + 1);
601*0bfacb9bSmrg   else
602*0bfacb9bSmrg     /* An error will be emitted for this in
603*0bfacb9bSmrg        bpf_function_arg_advance.  */
604*0bfacb9bSmrg     return NULL_RTX;
605*0bfacb9bSmrg }
606*0bfacb9bSmrg 
607*0bfacb9bSmrg #undef TARGET_FUNCTION_ARG
608*0bfacb9bSmrg #define TARGET_FUNCTION_ARG bpf_function_arg
609*0bfacb9bSmrg 
610*0bfacb9bSmrg /* Update the summarizer variable pointed by CA to advance past an
611*0bfacb9bSmrg    argument in the argument list.  */
612*0bfacb9bSmrg 
613*0bfacb9bSmrg static void
bpf_function_arg_advance(cumulative_args_t ca,const function_arg_info & arg)614*0bfacb9bSmrg bpf_function_arg_advance (cumulative_args_t ca,
615*0bfacb9bSmrg 			  const function_arg_info &arg)
616*0bfacb9bSmrg {
617*0bfacb9bSmrg   CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
618*0bfacb9bSmrg   unsigned num_bytes = arg.type_size_in_bytes ();
619*0bfacb9bSmrg   unsigned num_words = CEIL (num_bytes, UNITS_PER_WORD);
620*0bfacb9bSmrg 
621*0bfacb9bSmrg   if (*cum <= 5 && *cum + num_words > 5)
622*0bfacb9bSmrg     error ("too many function arguments for eBPF");
623*0bfacb9bSmrg 
624*0bfacb9bSmrg   *cum += num_words;
625*0bfacb9bSmrg }
626*0bfacb9bSmrg 
627*0bfacb9bSmrg #undef TARGET_FUNCTION_ARG_ADVANCE
628*0bfacb9bSmrg #define TARGET_FUNCTION_ARG_ADVANCE bpf_function_arg_advance
629*0bfacb9bSmrg 
630*0bfacb9bSmrg /* Output the assembly code for a constructor.  Since eBPF doesn't
631*0bfacb9bSmrg    support indirect calls, constructors are not supported.  */
632*0bfacb9bSmrg 
633*0bfacb9bSmrg static void
bpf_output_constructor(rtx symbol,int priority ATTRIBUTE_UNUSED)634*0bfacb9bSmrg bpf_output_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
635*0bfacb9bSmrg {
636*0bfacb9bSmrg   tree decl = SYMBOL_REF_DECL (symbol);
637*0bfacb9bSmrg 
638*0bfacb9bSmrg   if (decl)
639*0bfacb9bSmrg     sorry_at (DECL_SOURCE_LOCATION (decl),
640*0bfacb9bSmrg 	      "no constructors");
641*0bfacb9bSmrg   else
642*0bfacb9bSmrg     sorry ("no constructors");
643*0bfacb9bSmrg }
644*0bfacb9bSmrg 
645*0bfacb9bSmrg #undef TARGET_ASM_CONSTRUCTOR
646*0bfacb9bSmrg #define TARGET_ASM_CONSTRUCTOR bpf_output_constructor
647*0bfacb9bSmrg 
648*0bfacb9bSmrg /* Output the assembly code for a destructor.  Since eBPF doesn't
649*0bfacb9bSmrg    support indirect calls, destructors are not supported.  */
650*0bfacb9bSmrg 
651*0bfacb9bSmrg static void
bpf_output_destructor(rtx symbol,int priority ATTRIBUTE_UNUSED)652*0bfacb9bSmrg bpf_output_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
653*0bfacb9bSmrg {
654*0bfacb9bSmrg   tree decl = SYMBOL_REF_DECL (symbol);
655*0bfacb9bSmrg 
656*0bfacb9bSmrg   if (decl)
657*0bfacb9bSmrg     sorry_at (DECL_SOURCE_LOCATION (decl),
658*0bfacb9bSmrg 	      "no destructors");
659*0bfacb9bSmrg   else
660*0bfacb9bSmrg     sorry ("no destructors");
661*0bfacb9bSmrg }
662*0bfacb9bSmrg 
663*0bfacb9bSmrg #undef TARGET_ASM_DESTRUCTOR
664*0bfacb9bSmrg #define TARGET_ASM_DESTRUCTOR bpf_output_destructor
665*0bfacb9bSmrg 
666*0bfacb9bSmrg /* Return the appropriate instruction to CALL to a function.  TARGET
667*0bfacb9bSmrg    is an RTX denoting the address of the called function.
668*0bfacb9bSmrg 
669*0bfacb9bSmrg    The main purposes of this function are:
670*0bfacb9bSmrg    - To reject indirect CALL instructions, which are not supported by
671*0bfacb9bSmrg      eBPF.
672*0bfacb9bSmrg    - To recognize calls to kernel helper functions and emit the
673*0bfacb9bSmrg      corresponding CALL N instruction.
674*0bfacb9bSmrg 
675*0bfacb9bSmrg    This function is called from the expansion of the 'call' pattern in
676*0bfacb9bSmrg    bpf.md.  */
677*0bfacb9bSmrg 
678*0bfacb9bSmrg const char *
bpf_output_call(rtx target)679*0bfacb9bSmrg bpf_output_call (rtx target)
680*0bfacb9bSmrg {
681*0bfacb9bSmrg   rtx xops[1];
682*0bfacb9bSmrg 
683*0bfacb9bSmrg   switch (GET_CODE (target))
684*0bfacb9bSmrg     {
685*0bfacb9bSmrg     case CONST_INT:
686*0bfacb9bSmrg       output_asm_insn ("call\t%0", &target);
687*0bfacb9bSmrg       break;
688*0bfacb9bSmrg     case SYMBOL_REF:
689*0bfacb9bSmrg       {
690*0bfacb9bSmrg 	tree decl = SYMBOL_REF_DECL (target);
691*0bfacb9bSmrg 	tree attr;
692*0bfacb9bSmrg 
693*0bfacb9bSmrg 	if (decl
694*0bfacb9bSmrg 	    && (attr = lookup_attribute ("kernel_helper",
695*0bfacb9bSmrg 					 DECL_ATTRIBUTES (decl))))
696*0bfacb9bSmrg 	  {
697*0bfacb9bSmrg 	    tree attr_args = TREE_VALUE (attr);
698*0bfacb9bSmrg 
699*0bfacb9bSmrg 	    xops[0] = GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (attr_args)));
700*0bfacb9bSmrg 	    output_asm_insn ("call\t%0", xops);
701*0bfacb9bSmrg 	  }
702*0bfacb9bSmrg 	else
703*0bfacb9bSmrg 	  output_asm_insn ("call\t%0", &target);
704*0bfacb9bSmrg 
705*0bfacb9bSmrg 	break;
706*0bfacb9bSmrg       }
707*0bfacb9bSmrg     default:
708*0bfacb9bSmrg       if (TARGET_XBPF)
709*0bfacb9bSmrg 	output_asm_insn ("call\t%0", &target);
710*0bfacb9bSmrg       else
711*0bfacb9bSmrg 	{
712*0bfacb9bSmrg 	  error ("indirect call in function, which are not supported by eBPF");
713*0bfacb9bSmrg 	  output_asm_insn ("call 0", NULL);
714*0bfacb9bSmrg 	}
715*0bfacb9bSmrg       break;
716*0bfacb9bSmrg     }
717*0bfacb9bSmrg 
718*0bfacb9bSmrg   return "";
719*0bfacb9bSmrg }
720*0bfacb9bSmrg 
721*0bfacb9bSmrg /* Print an instruction operand.  This function is called in the macro
722*0bfacb9bSmrg    PRINT_OPERAND defined in bpf.h */
723*0bfacb9bSmrg 
724*0bfacb9bSmrg void
bpf_print_operand(FILE * file,rtx op,int code ATTRIBUTE_UNUSED)725*0bfacb9bSmrg bpf_print_operand (FILE *file, rtx op, int code ATTRIBUTE_UNUSED)
726*0bfacb9bSmrg {
727*0bfacb9bSmrg   switch (GET_CODE (op))
728*0bfacb9bSmrg     {
729*0bfacb9bSmrg     case REG:
730*0bfacb9bSmrg       fprintf (file, "%s", reg_names[REGNO (op)]);
731*0bfacb9bSmrg       break;
732*0bfacb9bSmrg     case MEM:
733*0bfacb9bSmrg       output_address (GET_MODE (op), XEXP (op, 0));
734*0bfacb9bSmrg       break;
735*0bfacb9bSmrg     case CONST_DOUBLE:
736*0bfacb9bSmrg       if (CONST_DOUBLE_HIGH (op))
737*0bfacb9bSmrg 	fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
738*0bfacb9bSmrg 		 CONST_DOUBLE_HIGH (op), CONST_DOUBLE_LOW (op));
739*0bfacb9bSmrg       else if (CONST_DOUBLE_LOW (op) < 0)
740*0bfacb9bSmrg 	fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (op));
741*0bfacb9bSmrg       else
742*0bfacb9bSmrg 	fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (op));
743*0bfacb9bSmrg       break;
744*0bfacb9bSmrg     default:
745*0bfacb9bSmrg       output_addr_const (file, op);
746*0bfacb9bSmrg     }
747*0bfacb9bSmrg }
748*0bfacb9bSmrg 
749*0bfacb9bSmrg /* Print an operand which is an address.  This function should handle
750*0bfacb9bSmrg    any legit address, as accepted by bpf_legitimate_address_p, and
751*0bfacb9bSmrg    also addresses that are valid in CALL instructions.
752*0bfacb9bSmrg 
753*0bfacb9bSmrg    This function is called in the PRINT_OPERAND_ADDRESS macro defined
754*0bfacb9bSmrg    in bpf.h */
755*0bfacb9bSmrg 
756*0bfacb9bSmrg void
bpf_print_operand_address(FILE * file,rtx addr)757*0bfacb9bSmrg bpf_print_operand_address (FILE *file, rtx addr)
758*0bfacb9bSmrg {
759*0bfacb9bSmrg   switch (GET_CODE (addr))
760*0bfacb9bSmrg     {
761*0bfacb9bSmrg     case REG:
762*0bfacb9bSmrg       fprintf (file, "[%s+0]", reg_names[REGNO (addr)]);
763*0bfacb9bSmrg       break;
764*0bfacb9bSmrg     case PLUS:
765*0bfacb9bSmrg       {
766*0bfacb9bSmrg 	rtx op0 = XEXP (addr, 0);
767*0bfacb9bSmrg 	rtx op1 = XEXP (addr, 1);
768*0bfacb9bSmrg 
769*0bfacb9bSmrg 	if (GET_CODE (op0) == REG && GET_CODE (op1) == CONST_INT)
770*0bfacb9bSmrg 	  {
771*0bfacb9bSmrg 	    fprintf (file, "[%s+", reg_names[REGNO (op0)]);
772*0bfacb9bSmrg 	    output_addr_const (file, op1);
773*0bfacb9bSmrg 	    fputs ("]", file);
774*0bfacb9bSmrg 	  }
775*0bfacb9bSmrg 	else
776*0bfacb9bSmrg 	  fatal_insn ("invalid address in operand", addr);
777*0bfacb9bSmrg 	break;
778*0bfacb9bSmrg       }
779*0bfacb9bSmrg     case MEM:
780*0bfacb9bSmrg       /* Fallthrough.  */
781*0bfacb9bSmrg     case LABEL_REF:
782*0bfacb9bSmrg       /* Fallthrough.  */
783*0bfacb9bSmrg       fatal_insn ("unsupported operand", addr);
784*0bfacb9bSmrg       break;
785*0bfacb9bSmrg     default:
786*0bfacb9bSmrg       output_addr_const (file, addr);
787*0bfacb9bSmrg       break;
788*0bfacb9bSmrg     }
789*0bfacb9bSmrg }
790*0bfacb9bSmrg 
791*0bfacb9bSmrg /* Add a BPF builtin function with NAME, CODE and TYPE.  Return
792*0bfacb9bSmrg    the function decl or NULL_TREE if the builtin was not added.  */
793*0bfacb9bSmrg 
794*0bfacb9bSmrg static tree
def_builtin(const char * name,enum bpf_builtins code,tree type)795*0bfacb9bSmrg def_builtin (const char *name, enum bpf_builtins code, tree type)
796*0bfacb9bSmrg {
797*0bfacb9bSmrg   tree t
798*0bfacb9bSmrg     = add_builtin_function (name, type, code, BUILT_IN_MD, NULL, NULL_TREE);
799*0bfacb9bSmrg 
800*0bfacb9bSmrg   bpf_builtins[code] = t;
801*0bfacb9bSmrg   return t;
802*0bfacb9bSmrg }
803*0bfacb9bSmrg 
804*0bfacb9bSmrg /* Define machine-specific built-in functions.  */
805*0bfacb9bSmrg 
806*0bfacb9bSmrg static void
bpf_init_builtins(void)807*0bfacb9bSmrg bpf_init_builtins (void)
808*0bfacb9bSmrg {
809*0bfacb9bSmrg   tree ullt = long_long_unsigned_type_node;
810*0bfacb9bSmrg 
811*0bfacb9bSmrg   /* Built-ins for BPF_LD_ABS and BPF_LD_IND instructions.  */
812*0bfacb9bSmrg 
813*0bfacb9bSmrg   def_builtin ("__builtin_bpf_load_byte", BPF_BUILTIN_LOAD_BYTE,
814*0bfacb9bSmrg 	       build_function_type_list (ullt, ullt, 0));
815*0bfacb9bSmrg   def_builtin ("__builtin_bpf_load_half", BPF_BUILTIN_LOAD_HALF,
816*0bfacb9bSmrg 	       build_function_type_list (ullt, ullt, 0));
817*0bfacb9bSmrg   def_builtin ("__builtin_bpf_load_word", BPF_BUILTIN_LOAD_WORD,
818*0bfacb9bSmrg 	       build_function_type_list (ullt, ullt, 0));
819*0bfacb9bSmrg }
820*0bfacb9bSmrg 
821*0bfacb9bSmrg #undef TARGET_INIT_BUILTINS
822*0bfacb9bSmrg #define TARGET_INIT_BUILTINS bpf_init_builtins
823*0bfacb9bSmrg 
824*0bfacb9bSmrg /* Expand a call to a BPF-specific built-in function that was set up
825*0bfacb9bSmrg    with bpf_init_builtins.  */
826*0bfacb9bSmrg 
827*0bfacb9bSmrg static rtx
bpf_expand_builtin(tree exp,rtx target ATTRIBUTE_UNUSED,rtx subtarget ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED,int ignore ATTRIBUTE_UNUSED)828*0bfacb9bSmrg bpf_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
829*0bfacb9bSmrg 		    rtx subtarget ATTRIBUTE_UNUSED,
830*0bfacb9bSmrg 		    machine_mode mode ATTRIBUTE_UNUSED,
831*0bfacb9bSmrg 		    int ignore ATTRIBUTE_UNUSED)
832*0bfacb9bSmrg {
833*0bfacb9bSmrg   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
834*0bfacb9bSmrg   int code = DECL_MD_FUNCTION_CODE (fndecl);
835*0bfacb9bSmrg 
836*0bfacb9bSmrg   if (code == BPF_BUILTIN_LOAD_BYTE
837*0bfacb9bSmrg       || code == BPF_BUILTIN_LOAD_HALF
838*0bfacb9bSmrg       || code == BPF_BUILTIN_LOAD_WORD)
839*0bfacb9bSmrg     {
840*0bfacb9bSmrg       /* Expand an indirect load from the sk_buff in the context.
841*0bfacb9bSmrg 	 There is just one argument to the builtin, which is the
842*0bfacb9bSmrg 	 offset.
843*0bfacb9bSmrg 
844*0bfacb9bSmrg 	 We try first to expand a ldabs* instruction.  In case this
845*0bfacb9bSmrg 	 fails, we try a ldind* instruction.  */
846*0bfacb9bSmrg 
847*0bfacb9bSmrg       enum insn_code abs_icode
848*0bfacb9bSmrg 	= (code == BPF_BUILTIN_LOAD_BYTE ? CODE_FOR_ldabsb
849*0bfacb9bSmrg 	   : code == BPF_BUILTIN_LOAD_HALF ? CODE_FOR_ldabsh
850*0bfacb9bSmrg 	   : CODE_FOR_ldabsw);
851*0bfacb9bSmrg 
852*0bfacb9bSmrg       enum insn_code ind_icode
853*0bfacb9bSmrg 	= (code == BPF_BUILTIN_LOAD_BYTE ? CODE_FOR_ldindb
854*0bfacb9bSmrg 	   : code == BPF_BUILTIN_LOAD_HALF ? CODE_FOR_ldindh
855*0bfacb9bSmrg 	   : CODE_FOR_ldindw);
856*0bfacb9bSmrg 
857*0bfacb9bSmrg       tree offset_arg = CALL_EXPR_ARG (exp, 0);
858*0bfacb9bSmrg       struct expand_operand ops[2];
859*0bfacb9bSmrg 
860*0bfacb9bSmrg       create_input_operand (&ops[0], expand_normal (offset_arg),
861*0bfacb9bSmrg 			    TYPE_MODE (TREE_TYPE (offset_arg)));
862*0bfacb9bSmrg       create_input_operand (&ops[1], const0_rtx, SImode);
863*0bfacb9bSmrg 
864*0bfacb9bSmrg       if (!maybe_expand_insn (abs_icode, 2, ops)
865*0bfacb9bSmrg 	  && !maybe_expand_insn (ind_icode, 2, ops))
866*0bfacb9bSmrg 	{
867*0bfacb9bSmrg 	  error ("invalid argument to built-in function");
868*0bfacb9bSmrg 	  return gen_rtx_REG (ops[0].mode, BPF_R0);
869*0bfacb9bSmrg 	}
870*0bfacb9bSmrg 
871*0bfacb9bSmrg       /* The result of the load is in R0.  */
872*0bfacb9bSmrg       return gen_rtx_REG (ops[0].mode, BPF_R0);
873*0bfacb9bSmrg     }
874*0bfacb9bSmrg 
875*0bfacb9bSmrg   gcc_unreachable ();
876*0bfacb9bSmrg }
877*0bfacb9bSmrg 
878*0bfacb9bSmrg #undef TARGET_EXPAND_BUILTIN
879*0bfacb9bSmrg #define TARGET_EXPAND_BUILTIN bpf_expand_builtin
880*0bfacb9bSmrg 
881*0bfacb9bSmrg /* Initialize target-specific function library calls.  This is mainly
882*0bfacb9bSmrg    used to call library-provided soft-fp operations, since eBPF
883*0bfacb9bSmrg    doesn't support floating-point in "hardware".  */
884*0bfacb9bSmrg 
885*0bfacb9bSmrg static void
bpf_init_libfuncs(void)886*0bfacb9bSmrg bpf_init_libfuncs (void)
887*0bfacb9bSmrg {
888*0bfacb9bSmrg   set_conv_libfunc (sext_optab, DFmode, SFmode,
889*0bfacb9bSmrg 		    "__bpf_extendsfdf2");
890*0bfacb9bSmrg   set_conv_libfunc (trunc_optab, SFmode, DFmode,
891*0bfacb9bSmrg 		    "__bpf_truncdfsf2");
892*0bfacb9bSmrg   set_conv_libfunc (sfix_optab, SImode, DFmode,
893*0bfacb9bSmrg 		    "__bpf_fix_truncdfsi");
894*0bfacb9bSmrg   set_conv_libfunc (sfloat_optab, DFmode, SImode,
895*0bfacb9bSmrg 		    "__bpf_floatsidf");
896*0bfacb9bSmrg   set_conv_libfunc (ufloat_optab, DFmode, SImode,
897*0bfacb9bSmrg 		    "__bpf_floatunsidf");
898*0bfacb9bSmrg }
899*0bfacb9bSmrg 
900*0bfacb9bSmrg #undef TARGET_INIT_LIBFUNCS
901*0bfacb9bSmrg #define TARGET_INIT_LIBFUNCS bpf_init_libfuncs
902*0bfacb9bSmrg 
903*0bfacb9bSmrg /* Define the mechanism that will be used for describing frame unwind
904*0bfacb9bSmrg    information to the debugger.  In eBPF it is not possible to unwind
905*0bfacb9bSmrg    frames.  */
906*0bfacb9bSmrg 
907*0bfacb9bSmrg static enum unwind_info_type
bpf_debug_unwind_info()908*0bfacb9bSmrg bpf_debug_unwind_info ()
909*0bfacb9bSmrg {
910*0bfacb9bSmrg   return UI_NONE;
911*0bfacb9bSmrg }
912*0bfacb9bSmrg 
913*0bfacb9bSmrg #undef TARGET_DEBUG_UNWIND_INFO
914*0bfacb9bSmrg #define TARGET_DEBUG_UNWIND_INFO bpf_debug_unwind_info
915*0bfacb9bSmrg 
916*0bfacb9bSmrg /* Output assembly directives to assemble data of various sized and
917*0bfacb9bSmrg    alignments.  */
918*0bfacb9bSmrg 
919*0bfacb9bSmrg #undef TARGET_ASM_BYTE_OP
920*0bfacb9bSmrg #define TARGET_ASM_BYTE_OP "\t.byte\t"
921*0bfacb9bSmrg #undef TARGET_ASM_ALIGNED_HI_OP
922*0bfacb9bSmrg #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
923*0bfacb9bSmrg #undef TARGET_ASM_ALIGNED_SI_OP
924*0bfacb9bSmrg #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
925*0bfacb9bSmrg #undef TARGET_ASM_ALIGNED_DI_OP
926*0bfacb9bSmrg #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
927*0bfacb9bSmrg 
928*0bfacb9bSmrg /* Finally, build the GCC target.  */
929*0bfacb9bSmrg 
930*0bfacb9bSmrg struct gcc_target targetm = TARGET_INITIALIZER;
931*0bfacb9bSmrg 
932*0bfacb9bSmrg #include "gt-bpf.h"
933