Print this page
11972 resync smatch

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/smatch/src/linearize.h
          +++ new/usr/src/tools/smatch/src/linearize.h
   1    1  #ifndef LINEARIZE_H
   2    2  #define LINEARIZE_H
   3    3  
   4    4  #include "lib.h"
   5    5  #include "allocate.h"
   6    6  #include "token.h"
        7 +#include "opcode.h"
   7    8  #include "parse.h"
   8    9  #include "symbol.h"
       10 +#include "ptrmap.h"
   9   11  
  10   12  struct instruction;
  11      -DECLARE_PTR_LIST(pseudo_ptr_list, pseudo_t);
  12   13  
  13   14  struct pseudo_user {
  14   15          struct instruction *insn;
  15   16          pseudo_t *userp;
  16   17  };
  17   18  
  18   19  DECLARE_ALLOCATOR(pseudo_user);
  19   20  DECLARE_PTR_LIST(pseudo_user_list, struct pseudo_user);
       21 +DECLARE_PTRMAP(phi_map, struct symbol *, pseudo_t);
  20   22  
  21   23  
  22   24  enum pseudo_type {
  23   25          PSEUDO_VOID,
       26 +        PSEUDO_UNDEF,
  24   27          PSEUDO_REG,
  25   28          PSEUDO_SYM,
  26   29          PSEUDO_VAL,
  27   30          PSEUDO_ARG,
  28   31          PSEUDO_PHI,
  29   32  };
  30   33  
  31   34  struct pseudo {
  32   35          int nr;
  33      -        int size:16;    /* OP_SETVAL only */
  34      -        enum pseudo_type type:8;
       36 +        enum pseudo_type type;
  35   37          struct pseudo_user_list *users;
  36   38          struct ident *ident;
  37   39          union {
  38   40                  struct symbol *sym;
  39   41                  struct instruction *def;
  40   42                  long long value;
  41   43          };
  42   44          void *priv;
  43   45  };
  44   46  
  45   47  extern struct pseudo void_pseudo;
  46   48  
  47   49  #define VOID (&void_pseudo)
  48   50  
       51 +static inline bool is_zero(pseudo_t pseudo)
       52 +{
       53 +        return pseudo->type == PSEUDO_VAL && pseudo->value == 0;
       54 +}
       55 +
       56 +static inline bool is_nonzero(pseudo_t pseudo)
       57 +{
       58 +        return pseudo->type == PSEUDO_VAL && pseudo->value != 0;
       59 +}
       60 +
       61 +
  49   62  struct multijmp {
  50   63          struct basic_block *target;
  51      -        int begin, end;
       64 +        long long begin, end;
  52   65  };
  53   66  
  54   67  struct asm_constraint {
  55   68          pseudo_t pseudo;
  56   69          const char *constraint;
  57   70          const struct ident *ident;
  58   71  };
  59   72  
  60   73  DECLARE_ALLOCATOR(asm_constraint);
  61   74  DECLARE_PTR_LIST(asm_constraint_list, struct asm_constraint);
  62   75  
  63   76  struct asm_rules {
  64   77          struct asm_constraint_list *inputs;
  65   78          struct asm_constraint_list *outputs;
  66   79          struct asm_constraint_list *clobbers;
  67   80  };
  68   81  
  69   82  DECLARE_ALLOCATOR(asm_rules);
  70   83  
  71   84  struct instruction {
  72      -        unsigned opcode:8,
       85 +        unsigned opcode:7,
       86 +                 tainted:1,
  73   87                   size:24;
  74   88          struct basic_block *bb;
  75   89          struct position pos;
  76   90          struct symbol *type;
       91 +        pseudo_t target;
  77   92          union {
  78      -                pseudo_t target;
  79      -                pseudo_t cond;          /* for branch and switch */
  80      -        };
  81      -        union {
  82   93                  struct /* entrypoint */ {
  83   94                          struct pseudo_list *arg_list;
  84   95                  };
  85   96                  struct /* branch */ {
       97 +                        pseudo_t cond;
  86   98                          struct basic_block *bb_true, *bb_false;
  87   99                  };
  88  100                  struct /* switch */ {
      101 +                        pseudo_t _cond;
  89  102                          struct multijmp_list *multijmp_list;
  90  103                  };
  91  104                  struct /* phi_node */ {
      105 +                        pseudo_t phi_var;               // used for SSA conversion
  92  106                          struct pseudo_list *phi_list;
      107 +                        unsigned int used:1;
  93  108                  };
  94  109                  struct /* phi source */ {
  95  110                          pseudo_t phi_src;
  96  111                          struct instruction_list *phi_users;
  97  112                  };
  98  113                  struct /* unops */ {
  99  114                          pseudo_t src;
 100  115                          struct symbol *orig_type;       /* casts */
 101      -                        unsigned int offset;            /* memops */
 102  116                  };
      117 +                struct /* memops */ {
      118 +                        pseudo_t addr;                  /* alias .src */
      119 +                        unsigned int offset;
      120 +                        unsigned int is_volatile:1;
      121 +                };
 103  122                  struct /* binops and sel */ {
 104  123                          pseudo_t src1, src2, src3;
 105  124                  };
 106  125                  struct /* slice */ {
 107  126                          pseudo_t base;
 108  127                          unsigned from, len;
 109  128                  };
 110  129                  struct /* setval */ {
 111      -                        pseudo_t symbol;                /* Subtle: same offset as "src" !! */
 112  130                          struct expression *val;
 113  131                  };
      132 +                struct /* setfval */ {
      133 +                        long double fvalue;
      134 +                };
 114  135                  struct /* call */ {
 115  136                          pseudo_t func;
 116  137                          struct pseudo_list *arguments;
 117      -                        struct symbol *fntype;
      138 +                        struct symbol_list *fntypes;
 118  139                  };
 119  140                  struct /* context */ {
 120  141                          int increment;
 121  142                          int check;
 122  143                          struct expression *context_expr;
 123  144                  };
 124  145                  struct /* asm */ {
 125  146                          const char *string;
 126  147                          struct asm_rules *asm_rules;
 127  148                  };
 128  149          };
 129  150  };
 130  151  
 131      -enum opcode {
 132      -        OP_BADOP,
 133      -
 134      -        /* Entry */
 135      -        OP_ENTRY,
 136      -
 137      -        /* Terminator */
 138      -        OP_TERMINATOR,
 139      -        OP_RET = OP_TERMINATOR,
 140      -        OP_BR,
 141      -        OP_CBR,
 142      -        OP_SWITCH,
 143      -        OP_INVOKE,
 144      -        OP_COMPUTEDGOTO,
 145      -        OP_UNWIND,
 146      -        OP_TERMINATOR_END = OP_UNWIND,
 147      -        
 148      -        /* Binary */
 149      -        OP_BINARY,
 150      -        OP_ADD = OP_BINARY,
 151      -        OP_SUB,
 152      -        OP_MULU, OP_MULS,
 153      -        OP_DIVU, OP_DIVS,
 154      -        OP_MODU, OP_MODS,
 155      -        OP_SHL,
 156      -        OP_LSR, OP_ASR,
 157      -        
 158      -        /* Logical */
 159      -        OP_AND,
 160      -        OP_OR,
 161      -        OP_XOR,
 162      -        OP_AND_BOOL,
 163      -        OP_OR_BOOL,
 164      -        OP_BINARY_END = OP_OR_BOOL,
 165      -
 166      -        /* Binary comparison */
 167      -        OP_BINCMP,
 168      -        OP_SET_EQ = OP_BINCMP,
 169      -        OP_SET_NE,
 170      -        OP_SET_LE,
 171      -        OP_SET_GE,
 172      -        OP_SET_LT,
 173      -        OP_SET_GT,
 174      -        OP_SET_B,
 175      -        OP_SET_A,
 176      -        OP_SET_BE,
 177      -        OP_SET_AE,
 178      -        OP_BINCMP_END = OP_SET_AE,
 179      -
 180      -        /* Uni */
 181      -        OP_NOT,
 182      -        OP_NEG,
 183      -
 184      -        /* Select - three input values */
 185      -        OP_SEL,
 186      -        
 187      -        /* Memory */
 188      -        OP_MALLOC,
 189      -        OP_FREE,
 190      -        OP_ALLOCA,
 191      -        OP_LOAD,
 192      -        OP_STORE,
 193      -        OP_SETVAL,
 194      -        OP_SYMADDR,
 195      -        OP_GET_ELEMENT_PTR,
 196      -
 197      -        /* Other */
 198      -        OP_PHI,
 199      -        OP_PHISOURCE,
 200      -        OP_CAST,
 201      -        OP_SCAST,
 202      -        OP_FPCAST,
 203      -        OP_PTRCAST,
 204      -        OP_INLINED_CALL,
 205      -        OP_CALL,
 206      -        OP_VANEXT,
 207      -        OP_VAARG,
 208      -        OP_SLICE,
 209      -        OP_SNOP,
 210      -        OP_LNOP,
 211      -        OP_NOP,
 212      -        OP_DEATHNOTE,
 213      -        OP_ASM,
 214      -
 215      -        /* Sparse tagging (line numbers, context, whatever) */
 216      -        OP_CONTEXT,
 217      -        OP_RANGE,
 218      -
 219      -        /* Needed to translate SSA back to normal form */
 220      -        OP_COPY,
 221      -};
 222      -
 223  152  struct basic_block_list;
 224  153  struct instruction_list;
 225  154  
 226  155  struct basic_block {
 227  156          struct position pos;
 228  157          unsigned long generation;
 229      -        int context;
      158 +        union {
      159 +                int context;
      160 +                int postorder_nr;       /* postorder number */
      161 +                int dom_level;          /* level in the dominance tree */
      162 +        };
 230  163          struct entrypoint *ep;
 231  164          struct basic_block_list *parents; /* sources */
 232  165          struct basic_block_list *children; /* destinations */
 233  166          struct instruction_list *insns; /* Linear list of instructions */
      167 +        struct basic_block *idom;       /* link to the immediate dominator */
      168 +        struct basic_block_list *doms;  /* list of BB idominated by this one */
      169 +        struct phi_map *phi_map;
 234  170          struct pseudo_list *needs, *defines;
 235  171          union {
 236  172                  unsigned int nr;        /* unique id for label's names */
 237  173                  void *priv;
 238  174          };
 239  175  };
 240  176  
 241  177  
      178 +//
      179 +// return the opcode of the instruction defining ``SRC`` if existing
      180 +// and OP_BADOP if not. It also assigns the defining instruction
      181 +// to ``DEF``.
      182 +#define DEF_OPCODE(DEF, SRC)    \
      183 +        (((SRC)->type == PSEUDO_REG && (DEF = (SRC)->def)) ? DEF->opcode : OP_BADOP)
      184 +
      185 +
 242  186  static inline void add_bb(struct basic_block_list **list, struct basic_block *bb)
 243  187  {
 244  188          add_ptr_list(list, bb);
 245  189  }
 246  190  
 247  191  static inline void add_instruction(struct instruction_list **list, struct instruction *insn)
 248  192  {
 249  193          add_ptr_list(list, insn);
 250  194  }
 251  195  
↓ open down ↓ 5 lines elided ↑ open up ↑
 257  201  static inline pseudo_t *add_pseudo(struct pseudo_list **list, pseudo_t pseudo)
 258  202  {
 259  203          return add_ptr_list(list, pseudo);
 260  204  }
 261  205  
 262  206  static inline int remove_pseudo(struct pseudo_list **list, pseudo_t pseudo)
 263  207  {
 264  208          return delete_ptr_list_entry((struct ptr_list **)list, pseudo, 0) != 0;
 265  209  }
 266  210  
      211 +static inline int pseudo_in_list(struct pseudo_list *list, pseudo_t pseudo)
      212 +{
      213 +        return lookup_ptr_list_entry((struct ptr_list *)list, pseudo);
      214 +}
      215 +
 267  216  static inline int bb_terminated(struct basic_block *bb)
 268  217  {
 269  218          struct instruction *insn;
 270  219          if (!bb)
 271  220                  return 0;
 272  221          insn = last_instruction(bb->insns);
 273  222          return insn && insn->opcode >= OP_TERMINATOR
 274  223                      && insn->opcode <= OP_TERMINATOR_END;
 275  224  }
 276  225  
 277  226  static inline int bb_reachable(struct basic_block *bb)
 278  227  {
 279  228          return bb != NULL;
 280  229  }
 281  230  
 282      -static inline void add_pseudo_ptr(pseudo_t *ptr, struct pseudo_ptr_list **list)
      231 +static inline int lookup_bb(struct basic_block_list *list, struct basic_block *bb)
 283  232  {
 284      -        add_ptr_list(list, ptr);
      233 +        return lookup_ptr_list_entry((struct ptr_list *)list, bb);
 285  234  }
 286  235  
      236 +
 287  237  static inline void add_pseudo_user_ptr(struct pseudo_user *user, struct pseudo_user_list **list)
 288  238  {
 289  239          add_ptr_list(list, user);
 290  240  }
 291  241  
 292  242  static inline int has_use_list(pseudo_t p)
 293  243  {
 294      -        return (p && p->type != PSEUDO_VOID && p->type != PSEUDO_VAL);
      244 +        return (p && p->type != PSEUDO_VOID && p->type != PSEUDO_UNDEF && p->type != PSEUDO_VAL);
 295  245  }
 296  246  
      247 +static inline int pseudo_user_list_size(struct pseudo_user_list *list)
      248 +{
      249 +        return ptr_list_size((struct ptr_list *)list);
      250 +}
      251 +
      252 +static inline bool pseudo_user_list_empty(struct pseudo_user_list *list)
      253 +{
      254 +        return ptr_list_empty((struct ptr_list *)list);
      255 +}
      256 +
      257 +static inline int has_users(pseudo_t p)
      258 +{
      259 +        return !pseudo_user_list_empty(p->users);
      260 +}
      261 +
      262 +static inline bool multi_users(pseudo_t p)
      263 +{
      264 +        return ptr_list_multiple((struct ptr_list *)(p->users));
      265 +}
      266 +
      267 +static inline int nbr_users(pseudo_t p)
      268 +{
      269 +        return pseudo_user_list_size(p->users);
      270 +}
      271 +
 297  272  static inline struct pseudo_user *alloc_pseudo_user(struct instruction *insn, pseudo_t *pp)
 298  273  {
 299  274          struct pseudo_user *user = __alloc_pseudo_user(0);
 300  275          user->userp = pp;
 301  276          user->insn = insn;
 302  277          return user;
 303  278  }
 304  279  
 305  280  static inline void use_pseudo(struct instruction *insn, pseudo_t p, pseudo_t *pp)
 306  281  {
↓ open down ↓ 13 lines elided ↑ open up ↑
 320  295          replace_ptr_list_entry((struct ptr_list **)list, old, new, count);
 321  296  }
 322  297  
 323  298  struct entrypoint {
 324  299          struct symbol *name;
 325  300          struct symbol_list *syms;
 326  301          struct pseudo_list *accesses;
 327  302          struct basic_block_list *bbs;
 328  303          struct basic_block *active;
 329  304          struct instruction *entry;
      305 +        unsigned int dom_levels;        /* max levels in the dom tree */
 330  306  };
 331  307  
 332  308  extern void insert_select(struct basic_block *bb, struct instruction *br, struct instruction *phi, pseudo_t if_true, pseudo_t if_false);
 333  309  extern void insert_branch(struct basic_block *bb, struct instruction *br, struct basic_block *target);
 334  310  
 335      -pseudo_t alloc_phi(struct basic_block *source, pseudo_t pseudo, int size);
      311 +struct instruction *alloc_phisrc(pseudo_t pseudo, struct symbol *type);
      312 +struct instruction *alloc_phi_node(struct basic_block *bb, struct symbol *type, struct ident *ident);
      313 +struct instruction *insert_phi_node(struct basic_block *bb, struct symbol *var);
      314 +void add_phi_node(struct basic_block *bb, struct instruction *phi_node);
      315 +
      316 +pseudo_t alloc_phi(struct basic_block *source, pseudo_t pseudo, struct symbol *type);
 336  317  pseudo_t alloc_pseudo(struct instruction *def);
 337      -pseudo_t value_pseudo(struct symbol *type, long long val);
 338      -unsigned int value_size(long long value);
      318 +pseudo_t value_pseudo(long long val);
      319 +pseudo_t undef_pseudo(void);
 339  320  
 340  321  struct entrypoint *linearize_symbol(struct symbol *sym);
 341  322  int unssa(struct entrypoint *ep);
 342  323  void show_entry(struct entrypoint *ep);
 343  324  const char *show_pseudo(pseudo_t pseudo);
 344  325  void show_bb(struct basic_block *bb);
 345  326  const char *show_instruction(struct instruction *insn);
      327 +const char *show_label(struct basic_block *bb);
 346  328  
 347  329  #endif /* LINEARIZE_H */
 348  330  
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX