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_integer(struct expression
*expr
)
33 expr
->ctype
= &int_ctype
;
37 static int evaluate_expect(struct expression
*expr
)
39 /* Should we evaluate it to return the type of the first argument? */
40 expr
->ctype
= &int_ctype
;
44 static int arguments_choose(struct expression
*expr
)
46 struct expression_list
*arglist
= expr
->args
;
47 struct expression
*arg
;
50 FOR_EACH_PTR (arglist
, arg
) {
51 if (!evaluate_expression(arg
))
54 } END_FOR_EACH_PTR(arg
);
56 sparse_error(expr
->pos
,
57 "not enough arguments for __builtin_choose_expr");
60 sparse_error(expr
->pos
,
61 "too many arguments for __builtin_choose_expr");
67 static int evaluate_choose(struct expression
*expr
)
69 struct expression_list
*list
= expr
->args
;
70 struct expression
*arg
, *args
[3];
73 /* there will be exactly 3; we'd already verified that */
74 FOR_EACH_PTR(list
, arg
) {
76 } END_FOR_EACH_PTR(arg
);
78 *expr
= get_expression_value(args
[0]) ? *args
[1] : *args
[2];
83 static int expand_expect(struct expression
*expr
, int cost
)
85 struct expression
*arg
= first_ptr_list((struct ptr_list
*) expr
->args
);
93 * __builtin_warning() has type "int" and always returns 1,
94 * so that you can use it in conditionals or whatever
96 static int expand_warning(struct expression
*expr
, int cost
)
98 struct expression
*arg
;
99 struct expression_list
*arglist
= expr
->args
;
101 FOR_EACH_PTR (arglist
, arg
) {
103 * Constant strings get printed out as a warning. By the
104 * time we get here, the EXPR_STRING has been fully
105 * evaluated, so by now it's an anonymous symbol with a
106 * string initializer.
108 * Just for the heck of it, allow any constant string
111 if (arg
->type
== EXPR_SYMBOL
) {
112 struct symbol
*sym
= arg
->symbol
;
113 if (sym
->initializer
&& sym
->initializer
->type
== EXPR_STRING
) {
114 struct string
*string
= sym
->initializer
->string
;
115 warning(expr
->pos
, "%*s", string
->length
-1, string
->data
);
121 * Any other argument is a conditional. If it's
122 * non-constant, or it is false, we exit and do
123 * not print any warning.
125 if (arg
->type
!= EXPR_VALUE
)
129 } END_FOR_EACH_PTR(arg
);
131 expr
->type
= EXPR_VALUE
;
137 /* The arguments are constant if the cost of all of them is zero */
138 static int expand_constant_p(struct expression
*expr
, int cost
)
140 expr
->type
= EXPR_VALUE
;
146 /* The arguments are safe, if their cost is less than SIDE_EFFECTS */
147 static int expand_safe_p(struct expression
*expr
, int cost
)
149 expr
->type
= EXPR_VALUE
;
150 expr
->value
= (cost
< SIDE_EFFECTS
);
155 static struct symbol_op constant_p_op
= {
156 .evaluate
= evaluate_to_integer
,
157 .expand
= expand_constant_p
160 static struct symbol_op safe_p_op
= {
161 .evaluate
= evaluate_to_integer
,
162 .expand
= expand_safe_p
165 static struct symbol_op warning_op
= {
166 .evaluate
= evaluate_to_integer
,
167 .expand
= expand_warning
170 static struct symbol_op expect_op
= {
171 .evaluate
= evaluate_expect
,
172 .expand
= expand_expect
175 static struct symbol_op choose_op
= {
176 .evaluate
= evaluate_choose
,
177 .args
= arguments_choose
,
180 /* The argument is constant and valid if the cost is zero */
181 static int expand_bswap(struct expression
*expr
, int cost
)
183 struct expression
*arg
;
189 /* the arguments number & type have already been checked */
190 arg
= first_expression(expr
->args
);
191 val
= get_expression_value_silent(arg
);
192 switch (expr
->ctype
->bit_size
) {
193 case 16: expr
->value
= bswap16(val
); break;
194 case 32: expr
->value
= bswap32(val
); break;
195 case 64: expr
->value
= bswap64(val
); break;
196 default: /* impossible error */
200 expr
->type
= EXPR_VALUE
;
205 static struct symbol_op bswap_op
= {
206 .expand
= expand_bswap
,
213 static struct symbol builtin_fn_type
= { .type
= SYM_FN
/* , .variadic =1 */ };
214 static struct sym_init
{
216 struct symbol
*base_type
;
217 unsigned int modifiers
;
218 struct symbol_op
*op
;
219 } builtins_table
[] = {
220 { "__builtin_constant_p", &builtin_fn_type
, MOD_TOPLEVEL
, &constant_p_op
},
221 { "__builtin_safe_p", &builtin_fn_type
, MOD_TOPLEVEL
, &safe_p_op
},
222 { "__builtin_warning", &builtin_fn_type
, MOD_TOPLEVEL
, &warning_op
},
223 { "__builtin_expect", &builtin_fn_type
, MOD_TOPLEVEL
, &expect_op
},
224 { "__builtin_choose_expr", &builtin_fn_type
, MOD_TOPLEVEL
, &choose_op
},
225 { "__builtin_bswap16", NULL
, MOD_TOPLEVEL
, &bswap_op
},
226 { "__builtin_bswap32", NULL
, MOD_TOPLEVEL
, &bswap_op
},
227 { "__builtin_bswap64", NULL
, MOD_TOPLEVEL
, &bswap_op
},
231 void init_builtins(int stream
)
233 struct sym_init
*ptr
;
235 builtin_fn_type
.variadic
= 1;
236 for (ptr
= builtins_table
; ptr
->name
; ptr
++) {
238 sym
= create_symbol(stream
, ptr
->name
, SYM_NODE
, NS_SYMBOL
);
239 sym
->ctype
.base_type
= ptr
->base_type
;
240 sym
->ctype
.modifiers
= ptr
->modifiers
;