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"
30 static int evaluate_to_integer(struct expression
*expr
)
32 expr
->ctype
= &int_ctype
;
36 static int evaluate_expect(struct expression
*expr
)
38 /* Should we evaluate it to return the type of the first argument? */
39 expr
->ctype
= &int_ctype
;
43 static int arguments_choose(struct expression
*expr
)
45 struct expression_list
*arglist
= expr
->args
;
46 struct expression
*arg
;
49 FOR_EACH_PTR (arglist
, arg
) {
50 if (!evaluate_expression(arg
))
53 } END_FOR_EACH_PTR(arg
);
55 sparse_error(expr
->pos
,
56 "not enough arguments for __builtin_choose_expr");
59 sparse_error(expr
->pos
,
60 "too many arguments for __builtin_choose_expr");
66 static int evaluate_choose(struct expression
*expr
)
68 struct expression_list
*list
= expr
->args
;
69 struct expression
*arg
, *args
[3];
72 /* there will be exactly 3; we'd already verified that */
73 FOR_EACH_PTR(list
, arg
) {
75 } END_FOR_EACH_PTR(arg
);
77 *expr
= get_expression_value(args
[0]) ? *args
[1] : *args
[2];
82 static int expand_expect(struct expression
*expr
, int cost
)
84 struct expression
*arg
= first_ptr_list((struct ptr_list
*) expr
->args
);
92 * __builtin_warning() has type "int" and always returns 1,
93 * so that you can use it in conditionals or whatever
95 static int expand_warning(struct expression
*expr
, int cost
)
97 struct expression
*arg
;
98 struct expression_list
*arglist
= expr
->args
;
100 FOR_EACH_PTR (arglist
, arg
) {
102 * Constant strings get printed out as a warning. By the
103 * time we get here, the EXPR_STRING has been fully
104 * evaluated, so by now it's an anonymous symbol with a
105 * string initializer.
107 * Just for the heck of it, allow any constant string
110 if (arg
->type
== EXPR_SYMBOL
) {
111 struct symbol
*sym
= arg
->symbol
;
112 if (sym
->initializer
&& sym
->initializer
->type
== EXPR_STRING
) {
113 struct string
*string
= sym
->initializer
->string
;
114 warning(expr
->pos
, "%*s", string
->length
-1, string
->data
);
120 * Any other argument is a conditional. If it's
121 * non-constant, or it is false, we exit and do
122 * not print any warning.
124 if (arg
->type
!= EXPR_VALUE
)
128 } END_FOR_EACH_PTR(arg
);
130 expr
->type
= EXPR_VALUE
;
136 /* The arguments are constant if the cost of all of them is zero */
137 static int expand_constant_p(struct expression
*expr
, int cost
)
139 expr
->type
= EXPR_VALUE
;
145 /* The arguments are safe, if their cost is less than SIDE_EFFECTS */
146 static int expand_safe_p(struct expression
*expr
, int cost
)
148 expr
->type
= EXPR_VALUE
;
149 expr
->value
= (cost
< SIDE_EFFECTS
);
154 static struct symbol_op constant_p_op
= {
155 .evaluate
= evaluate_to_integer
,
156 .expand
= expand_constant_p
159 static struct symbol_op safe_p_op
= {
160 .evaluate
= evaluate_to_integer
,
161 .expand
= expand_safe_p
164 static struct symbol_op warning_op
= {
165 .evaluate
= evaluate_to_integer
,
166 .expand
= expand_warning
169 static struct symbol_op expect_op
= {
170 .evaluate
= evaluate_expect
,
171 .expand
= expand_expect
174 static struct symbol_op choose_op
= {
175 .evaluate
= evaluate_choose
,
176 .args
= arguments_choose
,
179 /* The argument is constant and valid if the cost is zero */
180 static int expand_bswap(struct expression
*expr
, int cost
)
187 /* the arguments number & type have already been checked */
188 val
= const_expression_value(first_expression(expr
->args
));
189 switch (expr
->ctype
->bit_size
) {
190 case 16: expr
->value
= __builtin_bswap16(val
); break;
191 case 32: expr
->value
= __builtin_bswap32(val
); break;
192 case 64: expr
->value
= __builtin_bswap64(val
); break;
193 default: /* impossible error */
197 expr
->type
= EXPR_VALUE
;
202 static struct symbol_op bswap_op
= {
203 .expand
= expand_bswap
,
210 static struct symbol builtin_fn_type
= { .type
= SYM_FN
/* , .variadic =1 */ };
211 static struct sym_init
{
213 struct symbol
*base_type
;
214 unsigned int modifiers
;
215 struct symbol_op
*op
;
216 } builtins_table
[] = {
217 { "__builtin_constant_p", &builtin_fn_type
, MOD_TOPLEVEL
, &constant_p_op
},
218 { "__builtin_safe_p", &builtin_fn_type
, MOD_TOPLEVEL
, &safe_p_op
},
219 { "__builtin_warning", &builtin_fn_type
, MOD_TOPLEVEL
, &warning_op
},
220 { "__builtin_expect", &builtin_fn_type
, MOD_TOPLEVEL
, &expect_op
},
221 { "__builtin_choose_expr", &builtin_fn_type
, MOD_TOPLEVEL
, &choose_op
},
222 { "__builtin_bswap16", NULL
, MOD_TOPLEVEL
, &bswap_op
},
223 { "__builtin_bswap32", NULL
, MOD_TOPLEVEL
, &bswap_op
},
224 { "__builtin_bswap64", NULL
, MOD_TOPLEVEL
, &bswap_op
},
228 void init_builtins(int stream
)
230 struct sym_init
*ptr
;
232 builtin_fn_type
.variadic
= 1;
233 for (ptr
= builtins_table
; ptr
->name
; ptr
++) {
235 sym
= create_symbol(stream
, ptr
->name
, SYM_NODE
, NS_SYMBOL
);
236 sym
->ctype
.base_type
= ptr
->base_type
;
237 sym
->ctype
.modifiers
= ptr
->modifiers
;