2 * builtin evaluation & expansion.
4 * Copyright (C) 2003 Transmeta Corp.
5 * 2003-2004 Linus Torvalds
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #include "expression.h"
29 #include "compat/bswap.h"
31 static int evaluate_to_int_const_expr(struct expression
*expr
)
33 expr
->ctype
= &int_ctype
;
34 expr
->flags
|= CEF_SET_ICE
;
38 static int evaluate_pure_unop(struct expression
*expr
)
40 struct expression
*arg
= first_expression(expr
->args
);
41 int flags
= arg
->flags
;
44 * Allow such functions with a constant integer expression
45 * argument to be treated as a *constant* integer.
46 * This allow us to use them in switch() { case ...:
48 flags
|= (flags
& CEF_ICE
) ? CEF_SET_INT
: 0;
54 static int evaluate_expect(struct expression
*expr
)
56 /* Should we evaluate it to return the type of the first argument? */
57 expr
->ctype
= &int_ctype
;
61 static int arguments_choose(struct expression
*expr
)
63 struct expression_list
*arglist
= expr
->args
;
64 struct expression
*arg
;
67 FOR_EACH_PTR (arglist
, arg
) {
68 if (!evaluate_expression(arg
))
71 } END_FOR_EACH_PTR(arg
);
73 sparse_error(expr
->pos
,
74 "not enough arguments for __builtin_choose_expr");
77 sparse_error(expr
->pos
,
78 "too many arguments for __builtin_choose_expr");
84 static int evaluate_choose(struct expression
*expr
)
86 struct expression_list
*list
= expr
->args
;
87 struct expression
*arg
, *args
[3];
90 /* there will be exactly 3; we'd already verified that */
91 FOR_EACH_PTR(list
, arg
) {
93 } END_FOR_EACH_PTR(arg
);
95 *expr
= get_expression_value(args
[0]) ? *args
[1] : *args
[2];
100 static int expand_expect(struct expression
*expr
, int cost
)
102 struct expression
*arg
= first_ptr_list((struct ptr_list
*) expr
->args
);
110 * __builtin_warning() has type "int" and always returns 1,
111 * so that you can use it in conditionals or whatever
113 static int expand_warning(struct expression
*expr
, int cost
)
115 struct expression
*arg
;
116 struct expression_list
*arglist
= expr
->args
;
118 FOR_EACH_PTR (arglist
, arg
) {
120 * Constant strings get printed out as a warning. By the
121 * time we get here, the EXPR_STRING has been fully
122 * evaluated, so by now it's an anonymous symbol with a
123 * string initializer.
125 * Just for the heck of it, allow any constant string
128 if (arg
->type
== EXPR_SYMBOL
) {
129 struct symbol
*sym
= arg
->symbol
;
130 if (sym
->initializer
&& sym
->initializer
->type
== EXPR_STRING
) {
131 struct string
*string
= sym
->initializer
->string
;
132 warning(expr
->pos
, "%*s", string
->length
-1, string
->data
);
138 * Any other argument is a conditional. If it's
139 * non-constant, or it is false, we exit and do
140 * not print any warning.
142 if (arg
->type
!= EXPR_VALUE
)
146 } END_FOR_EACH_PTR(arg
);
148 expr
->type
= EXPR_VALUE
;
154 /* The arguments are constant if the cost of all of them is zero */
155 static int expand_constant_p(struct expression
*expr
, int cost
)
157 expr
->type
= EXPR_VALUE
;
163 /* The arguments are safe, if their cost is less than SIDE_EFFECTS */
164 static int expand_safe_p(struct expression
*expr
, int cost
)
166 expr
->type
= EXPR_VALUE
;
167 expr
->value
= (cost
< SIDE_EFFECTS
);
172 static struct symbol_op constant_p_op
= {
173 .evaluate
= evaluate_to_int_const_expr
,
174 .expand
= expand_constant_p
177 static struct symbol_op safe_p_op
= {
178 .evaluate
= evaluate_to_int_const_expr
,
179 .expand
= expand_safe_p
182 static struct symbol_op warning_op
= {
183 .evaluate
= evaluate_to_int_const_expr
,
184 .expand
= expand_warning
187 static struct symbol_op expect_op
= {
188 .evaluate
= evaluate_expect
,
189 .expand
= expand_expect
192 static struct symbol_op choose_op
= {
193 .evaluate
= evaluate_choose
,
194 .args
= arguments_choose
,
197 /* The argument is constant and valid if the cost is zero */
198 static int expand_bswap(struct expression
*expr
, int cost
)
200 struct expression
*arg
;
206 /* the arguments number & type have already been checked */
207 arg
= first_expression(expr
->args
);
208 val
= get_expression_value_silent(arg
);
209 switch (expr
->ctype
->bit_size
) {
210 case 16: expr
->value
= bswap16(val
); break;
211 case 32: expr
->value
= bswap32(val
); break;
212 case 64: expr
->value
= bswap64(val
); break;
213 default: /* impossible error */
217 expr
->type
= EXPR_VALUE
;
222 static struct symbol_op bswap_op
= {
223 .evaluate
= evaluate_pure_unop
,
224 .expand
= expand_bswap
,
231 static struct symbol builtin_fn_type
= { .type
= SYM_FN
/* , .variadic =1 */ };
232 static struct sym_init
{
234 struct symbol
*base_type
;
235 unsigned int modifiers
;
236 struct symbol_op
*op
;
237 } builtins_table
[] = {
238 { "__builtin_constant_p", &builtin_fn_type
, MOD_TOPLEVEL
, &constant_p_op
},
239 { "__builtin_safe_p", &builtin_fn_type
, MOD_TOPLEVEL
, &safe_p_op
},
240 { "__builtin_warning", &builtin_fn_type
, MOD_TOPLEVEL
, &warning_op
},
241 { "__builtin_expect", &builtin_fn_type
, MOD_TOPLEVEL
, &expect_op
},
242 { "__builtin_choose_expr", &builtin_fn_type
, MOD_TOPLEVEL
, &choose_op
},
243 { "__builtin_bswap16", NULL
, MOD_TOPLEVEL
, &bswap_op
},
244 { "__builtin_bswap32", NULL
, MOD_TOPLEVEL
, &bswap_op
},
245 { "__builtin_bswap64", NULL
, MOD_TOPLEVEL
, &bswap_op
},
249 void init_builtins(int stream
)
251 struct sym_init
*ptr
;
253 builtin_fn_type
.variadic
= 1;
254 for (ptr
= builtins_table
; ptr
->name
; ptr
++) {
256 sym
= create_symbol(stream
, ptr
->name
, SYM_NODE
, NS_SYMBOL
);
257 sym
->ctype
.base_type
= ptr
->base_type
;
258 sym
->ctype
.modifiers
= ptr
->modifiers
;