1 /*
   2  * builtin evaluation & expansion.
   3  *
   4  * Copyright (C) 2003 Transmeta Corp.
   5  *               2003-2004 Linus Torvalds
   6  *
   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:
  13  *
  14  * The above copyright notice and this permission notice shall be included in
  15  * all copies or substantial portions of the Software.
  16  *
  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
  23  * THE SOFTWARE.
  24  */
  25 
  26 #include "expression.h"
  27 #include "expand.h"
  28 #include "symbol.h"
  29 #include "compat/bswap.h"
  30 
  31 static int evaluate_to_int_const_expr(struct expression *expr)
  32 {
  33         expr->ctype = &int_ctype;
  34         expr->flags |= CEF_SET_ICE;
  35         return 1;
  36 }
  37 
  38 static int evaluate_pure_unop(struct expression *expr)
  39 {
  40         struct expression *arg = first_expression(expr->args);
  41         int flags = arg->flags;
  42 
  43         /*
  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 ...:
  47          */
  48         flags |= (flags & CEF_ICE) ? CEF_SET_INT : 0;
  49         expr->flags = flags;
  50         return 1;
  51 }
  52 
  53 
  54 static int evaluate_expect(struct expression *expr)
  55 {
  56         /* Should we evaluate it to return the type of the first argument? */
  57         expr->ctype = &int_ctype;
  58         return 1;
  59 }
  60 
  61 static int arguments_choose(struct expression *expr)
  62 {
  63         struct expression_list *arglist = expr->args;
  64         struct expression *arg;
  65         int i = 0;
  66 
  67         FOR_EACH_PTR (arglist, arg) {
  68                 if (!evaluate_expression(arg))
  69                         return 0;
  70                 i++;
  71         } END_FOR_EACH_PTR(arg);
  72         if (i < 3) {
  73                 sparse_error(expr->pos,
  74                              "not enough arguments for __builtin_choose_expr");
  75                 return 0;
  76         } if (i > 3) {
  77                 sparse_error(expr->pos,
  78                              "too many arguments for __builtin_choose_expr");
  79                 return 0;
  80         }
  81         return 1;
  82 }
  83 
  84 static int evaluate_choose(struct expression *expr)
  85 {
  86         struct expression_list *list = expr->args;
  87         struct expression *arg, *args[3];
  88         int n = 0;
  89 
  90         /* there will be exactly 3; we'd already verified that */
  91         FOR_EACH_PTR(list, arg) {
  92                 args[n++] = arg;
  93         } END_FOR_EACH_PTR(arg);
  94 
  95         *expr = get_expression_value(args[0]) ? *args[1] : *args[2];
  96 
  97         return 1;
  98 }
  99 
 100 static int expand_expect(struct expression *expr, int cost)
 101 {
 102         struct expression *arg = first_ptr_list((struct ptr_list *) expr->args);
 103 
 104         if (arg)
 105                 *expr = *arg;
 106         return 0;
 107 }
 108 
 109 /*
 110  * __builtin_warning() has type "int" and always returns 1,
 111  * so that you can use it in conditionals or whatever
 112  */
 113 static int expand_warning(struct expression *expr, int cost)
 114 {
 115         struct expression *arg;
 116         struct expression_list *arglist = expr->args;
 117 
 118         FOR_EACH_PTR (arglist, arg) {
 119                 /*
 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.
 124                  *
 125                  * Just for the heck of it, allow any constant string
 126                  * symbol.
 127                  */
 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);
 133                         }
 134                         continue;
 135                 }
 136 
 137                 /*
 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.
 141                  */
 142                 if (arg->type != EXPR_VALUE)
 143                         goto out;
 144                 if (!arg->value)
 145                         goto out;
 146         } END_FOR_EACH_PTR(arg);
 147 out:
 148         expr->type = EXPR_VALUE;
 149         expr->value = 1;
 150         expr->taint = 0;
 151         return 0;
 152 }
 153 
 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)
 156 {
 157         expr->type = EXPR_VALUE;
 158         expr->value = !cost;
 159         expr->taint = 0;
 160         return 0;
 161 }
 162 
 163 /* The arguments are safe, if their cost is less than SIDE_EFFECTS */
 164 static int expand_safe_p(struct expression *expr, int cost)
 165 {
 166         expr->type = EXPR_VALUE;
 167         expr->value = (cost < SIDE_EFFECTS);
 168         expr->taint = 0;
 169         return 0;
 170 }
 171 
 172 static struct symbol_op constant_p_op = {
 173         .evaluate = evaluate_to_int_const_expr,
 174         .expand = expand_constant_p
 175 };
 176 
 177 static struct symbol_op safe_p_op = {
 178         .evaluate = evaluate_to_int_const_expr,
 179         .expand = expand_safe_p
 180 };
 181 
 182 static struct symbol_op warning_op = {
 183         .evaluate = evaluate_to_int_const_expr,
 184         .expand = expand_warning
 185 };
 186 
 187 static struct symbol_op expect_op = {
 188         .evaluate = evaluate_expect,
 189         .expand = expand_expect
 190 };
 191 
 192 static struct symbol_op choose_op = {
 193         .evaluate = evaluate_choose,
 194         .args = arguments_choose,
 195 };
 196 
 197 /* The argument is constant and valid if the cost is zero */
 198 static int expand_bswap(struct expression *expr, int cost)
 199 {
 200         struct expression *arg;
 201         long long val;
 202 
 203         if (cost)
 204                 return cost;
 205 
 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 */
 214                 return SIDE_EFFECTS;
 215         }
 216 
 217         expr->type = EXPR_VALUE;
 218         expr->taint = 0;
 219         return 0;
 220 }
 221 
 222 static struct symbol_op bswap_op = {
 223         .evaluate = evaluate_pure_unop,
 224         .expand = expand_bswap,
 225 };
 226 
 227 
 228 /*
 229  * Builtin functions
 230  */
 231 static struct symbol builtin_fn_type = { .type = SYM_FN /* , .variadic =1 */ };
 232 static struct sym_init {
 233         const char *name;
 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 },
 246         { NULL,         NULL,           0 }
 247 };
 248 
 249 void init_builtins(int stream)
 250 {
 251         struct sym_init *ptr;
 252 
 253         builtin_fn_type.variadic = 1;
 254         for (ptr = builtins_table; ptr->name; ptr++) {
 255                 struct symbol *sym;
 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;
 259                 sym->op = ptr->op;
 260         }
 261 }