Home | History | Annotate | Download | only in priv
      1 
      2 /*---------------------------------------------------------------*/
      3 /*--- begin                               host_generic_regs.h ---*/
      4 /*---------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2004-2017 OpenWorks LLP
     11       info (at) open-works.net
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     26    02110-1301, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 
     30    Neither the names of the U.S. Department of Energy nor the
     31    University of California nor the names of its contributors may be
     32    used to endorse or promote products derived from this software
     33    without prior written permission.
     34 */
     35 
     36 #ifndef __VEX_HOST_GENERIC_REGS_H
     37 #define __VEX_HOST_GENERIC_REGS_H
     38 
     39 #include "libvex_basictypes.h"
     40 
     41 
     42 /*---------------------------------------------------------*/
     43 /*--- Representing HOST REGISTERS                       ---*/
     44 /*---------------------------------------------------------*/
     45 
     46 /* Host registers.  Stuff to represent:
     47 
     48    - The register index.  This is a zero-based, sequential index that
     49      facilitates indexing into arrays or virtual or real registers.
     50      Virtual and real registers both have indices starting at zero.
     51      Interpreting a real register index requires having the host's
     52      RRegUniverse to hand.
     53 
     54    - The register's hardware encoding.  This applies only for real
     55      registers and should be zero for virtual registers.  This is the
     56      number as used in a target architecture encoding.
     57 
     58    - The register class
     59 
     60    - Whether or not the register is a virtual reg.
     61 
     62    Registers are sized so as to fit into 32 bits.
     63 
     64    Note that since the class field is never 1111b, no valid register
     65    can have the value INVALID_HREG.
     66 
     67    There are currently 6 register classes:
     68 
     69      int32 int64 float32 float64 simd64 simd128
     70 */
     71 
     72 /* Registers are represented as 32 bit integers, with the following layout:
     73 
     74    31     30..27  26..20  19..0
     75    isV:1  rc:4    enc:7   ix:20
     76 
     77    where
     78       UInt      ix:20;   // Zero based index
     79       UInt      enc:7;   // Hardware encoding number
     80       HRegClass rc:4;    // the register's HRegClass
     81       Bool      isV:1;   // is it a virtual register?
     82 
     83    The obvious thing to do here would be to use bitfields.  But gcc
     84    seems to have problems constant folding calls to mkHReg() with all
     85    4 parameters constant to a 32 bit number, when using bitfields.
     86    Hence the use of the traditional shift-and-mask by-hand bitfields
     87    instead.
     88 */
     89 typedef  struct { UInt u32; }  HReg;
     90 
     91 /* HRegClass describes host register classes which the instruction
     92    selectors can speak about.  We would not expect all of them to be
     93    available on any specific host.  For example on x86, the available
     94    classes are: Int32, Flt64, Vec128 only.
     95 
     96    IMPORTANT NOTE: host_generic_reg_alloc2.c needs how much space is
     97    needed to spill each class of register.  It allocates the following
     98    amount of space:
     99 
    100       HRcInt32     64 bits
    101       HRcInt64     64 bits
    102       HRcFlt32     64 bits
    103       HRcFlt64     128 bits (on x86 these are spilled by fstpt/fldt and
    104                              so won't fit in a 64-bit slot)
    105       HRcVec64     64 bits
    106       HRcVec128    128 bits
    107 
    108    If you add another regclass, you must remember to update
    109    host_generic_reg_alloc2.c accordingly.
    110 
    111    When adding entries to enum HRegClass, do not use any value > 14 or < 1.
    112 */
    113 typedef
    114    enum {
    115       HRcINVALID=1,   /* NOT A VALID REGISTER CLASS */
    116       HRcInt32=3,     /* 32-bit int */
    117       HRcInt64=4,     /* 64-bit int */
    118       HRcFlt32=5,     /* 32-bit float */
    119       HRcFlt64=6,     /* 64-bit float */
    120       HRcVec64=7,     /* 64-bit SIMD */
    121       HRcVec128=8     /* 128-bit SIMD */
    122    }
    123    HRegClass;
    124 
    125 extern void ppHRegClass ( HRegClass );
    126 
    127 
    128 /* Print an HReg in a generic (non-target-specific) way. */
    129 extern void ppHReg ( HReg );
    130 
    131 /* Construct.  The goal here is that compiler can fold this down to a
    132    constant in the case where the four arguments are constants, which
    133    is often the case. */
    134 static inline HReg mkHReg ( Bool virtual, HRegClass rc, UInt enc, UInt ix )
    135 {
    136    vassert(ix <= 0xFFFFF);
    137    vassert(enc <= 0x7F);
    138    vassert(((UInt)rc) <= 0xF);
    139    vassert(((UInt)virtual) <= 1);
    140    if (virtual) vassert(enc == 0);
    141    HReg r;
    142    r.u32 = ((((UInt)virtual) & 1)       << 31)  |
    143            ((((UInt)rc)      & 0xF)     << 27)  |
    144            ((((UInt)enc)     & 0x7F)    << 20)  |
    145            ((((UInt)ix)      & 0xFFFFF) << 0);
    146    return r;
    147 }
    148 
    149 static inline HRegClass hregClass ( HReg r )
    150 {
    151    HRegClass rc = (HRegClass)((r.u32 >> 27) & 0xF);
    152    vassert(rc >= HRcInt32 && rc <= HRcVec128);
    153    return rc;
    154 }
    155 
    156 static inline UInt hregIndex ( HReg r )
    157 {
    158    return r.u32 & 0xFFFFF;
    159 }
    160 
    161 static inline UInt hregEncoding ( HReg r )
    162 {
    163    return (r.u32 >> 20) & 0x7F;
    164 }
    165 
    166 static inline Bool hregIsVirtual ( HReg r )
    167 {
    168    return toBool((r.u32 >> 31) & 1);
    169 }
    170 
    171 static inline Bool sameHReg ( HReg r1, HReg r2 )
    172 {
    173    return toBool(r1.u32 == r2.u32);
    174 }
    175 
    176 static const HReg INVALID_HREG = { .u32 = 0xFFFFFFFF };
    177 
    178 static inline Bool hregIsInvalid ( HReg r )
    179 {
    180    return sameHReg(r, INVALID_HREG);
    181 }
    182 
    183 
    184 /*---------------------------------------------------------*/
    185 /*--- Real register Universes.                          ---*/
    186 /*---------------------------------------------------------*/
    187 
    188 /* A "Real Register Universe" is a read-only structure that contains
    189    all information about real registers on a given host.  It serves
    190    several purposes:
    191 
    192    * defines the mapping from real register indices to the registers
    193      themselves
    194 
    195    * defines the size of the initial section of that mapping that is
    196      available to the register allocator for use, so that the register
    197      allocator can treat the registers under its control as a zero
    198      based, contiguous array.  This is important for its efficiency.
    199 
    200    * gives meaning to RRegSets, which otherwise would merely be a
    201      bunch of bits.
    202 
    203    This is a big structure, but it's readonly, and we expect to
    204    allocate only one instance for each run of Valgrind.  It is sized
    205    so as to be able to deal with up to 64 real registers.  AFAICS none
    206    of the back ends actually mention more than 64, despite the fact
    207    that many of the host architectures have more than 64 registers
    208    when all classes are taken into consideration.
    209 */
    210 
    211 #define N_RREGUNIVERSE_REGS 64
    212 
    213 typedef
    214    struct {
    215       /* Total number of registers in this universe .. */
    216       UInt size;
    217       /* .. of which the first |allocable| are available to regalloc. */
    218       UInt allocable;
    219       /* The registers themselves.  All must be real registers, and
    220          all must have their index number (.s.ix) equal to the array
    221          index here, since this is the only place where we map index
    222          numbers to actual registers. */
    223       HReg regs[N_RREGUNIVERSE_REGS];
    224    }
    225    RRegUniverse;
    226 
    227 /* Nominally initialise (zero out) an RRegUniverse. */
    228 void RRegUniverse__init ( /*OUT*/RRegUniverse* );
    229 
    230 /* Check an RRegUniverse is valid, and assert if not.*/
    231 void RRegUniverse__check_is_sane ( const RRegUniverse* );
    232 
    233 /* Print an RRegUniverse, for debugging. */
    234 void RRegUniverse__show ( const RRegUniverse* );
    235 
    236 
    237 /*---------------------------------------------------------*/
    238 /*--- Real register sets.                               ---*/
    239 /*---------------------------------------------------------*/
    240 
    241 /* Represents sets of real registers.  |bitset| is interpreted in the
    242    context of |univ|.  That is, each bit index |i| in |bitset|
    243    corresponds to the register |univ->regs[i]|.  This relies
    244    entirely on the fact that N_RREGUNIVERSE_REGS <= 64. */
    245 typedef
    246    struct {
    247       ULong         bitset;
    248       RRegUniverse* univ;
    249    }
    250    RRegSet;
    251 
    252 
    253 /*---------------------------------------------------------*/
    254 /*--- Recording register usage (for reg-alloc)          ---*/
    255 /*---------------------------------------------------------*/
    256 
    257 typedef
    258    enum { HRmRead, HRmWrite, HRmModify }
    259    HRegMode;
    260 
    261 
    262 /* This isn't entirely general, and is specialised towards being fast,
    263    for the reg-alloc.  It represents real registers using a bitmask
    264    and can also represent up to four virtual registers, in an
    265    unordered array.  This is based on the observation that no
    266    instruction that we generate can mention more than four registers
    267    at once.
    268 */
    269 #define N_HREGUSAGE_VREGS 5
    270 
    271 typedef
    272    struct {
    273       /* The real registers.  The associated universe is not stored
    274          here -- callers will have to pass it around separately, as
    275          needed. */
    276       ULong    rRead;     /* real regs that are read */
    277       ULong    rWritten;  /* real regs that are written */
    278       /* The virtual registers. */
    279       HReg     vRegs[N_HREGUSAGE_VREGS];
    280       HRegMode vMode[N_HREGUSAGE_VREGS];
    281       UInt     n_vRegs;
    282    }
    283    HRegUsage;
    284 
    285 extern void ppHRegUsage ( const RRegUniverse*, HRegUsage* );
    286 
    287 static inline void initHRegUsage ( HRegUsage* tab )
    288 {
    289    tab->rRead    = 0;
    290    tab->rWritten = 0;
    291    tab->n_vRegs  = 0;
    292 }
    293 
    294 /* Add a register to a usage table.  Combine incoming read uses with
    295    existing write uses into a modify use, and vice versa.  Do not
    296    create duplicate entries -- each reg should only be mentioned once.
    297 */
    298 extern void addHRegUse ( HRegUsage*, HRegMode, HReg );
    299 
    300 extern Bool HRegUsage__contains ( const HRegUsage*, HReg );
    301 
    302 
    303 /*---------------------------------------------------------*/
    304 /*--- Indicating register remappings (for reg-alloc)    ---*/
    305 /*---------------------------------------------------------*/
    306 
    307 /* Note that such maps can only map virtual regs to real regs.
    308    addToHRegRenap will barf if given a pair not of that form.  As a
    309    result, no valid HRegRemap will bind a real reg to anything, and so
    310    if lookupHRegMap is given a real reg, it returns it unchanged.
    311    This is precisely the behaviour that the register allocator needs
    312    to impose its decisions on the instructions it processes.  */
    313 
    314 #define N_HREG_REMAP 6
    315 
    316 typedef
    317    struct {
    318       HReg orig       [N_HREG_REMAP];
    319       HReg replacement[N_HREG_REMAP];
    320       Int  n_used;
    321    }
    322    HRegRemap;
    323 
    324 extern void ppHRegRemap     ( HRegRemap* );
    325 extern void addToHRegRemap  ( HRegRemap*, HReg, HReg );
    326 extern HReg lookupHRegRemap ( HRegRemap*, HReg );
    327 
    328 static inline void initHRegRemap ( HRegRemap* map )
    329 {
    330    map->n_used = 0;
    331 }
    332 
    333 
    334 /*---------------------------------------------------------*/
    335 /*--- Abstract instructions                             ---*/
    336 /*---------------------------------------------------------*/
    337 
    338 /* A type is needed to refer to pointers to instructions of any
    339    target.  Defining it like this means that HInstr* can stand in for
    340    X86Instr*, ArmInstr*, etc. */
    341 
    342 typedef  void  HInstr;
    343 
    344 
    345 /* An expandable array of HInstr*'s.  Handy for insn selection and
    346    register allocation.  n_vregs indicates the number of virtual
    347    registers mentioned in the code, something that reg-alloc needs to
    348    know.  These are required to be numbered 0 .. n_vregs-1.
    349 */
    350 typedef
    351    struct {
    352       HInstr** arr;
    353       Int      arr_size;
    354       Int      arr_used;
    355       Int      n_vregs;
    356    }
    357    HInstrArray;
    358 
    359 extern HInstrArray* newHInstrArray ( void );
    360 
    361 /* Never call this directly.  It's the slow and incomplete path for
    362    addHInstr. */
    363 __attribute__((noinline))
    364 extern void addHInstr_SLOW ( HInstrArray*, HInstr* );
    365 
    366 static inline void addHInstr ( HInstrArray* ha, HInstr* instr )
    367 {
    368    if (LIKELY(ha->arr_used < ha->arr_size)) {
    369       ha->arr[ha->arr_used] = instr;
    370       ha->arr_used++;
    371    } else {
    372       addHInstr_SLOW(ha, instr);
    373    }
    374 }
    375 
    376 
    377 /*---------------------------------------------------------*/
    378 /*--- C-Call return-location descriptions               ---*/
    379 /*---------------------------------------------------------*/
    380 
    381 /* This is common to all back ends.  It describes where the return
    382    value from a C call is located.  This is important in the case that
    383    the call is conditional, since the return locations will need to be
    384    set to 0x555..555 in the case that the call does not happen. */
    385 
    386 typedef
    387    enum {
    388       RLPri_INVALID,   /* INVALID */
    389       RLPri_None,      /* no return value (a.k.a C "void") */
    390       RLPri_Int,       /* in the primary int return reg */
    391       RLPri_2Int,      /* in both primary and secondary int ret regs */
    392       RLPri_V128SpRel, /* 128-bit value, on the stack */
    393       RLPri_V256SpRel  /* 256-bit value, on the stack */
    394    }
    395    RetLocPrimary;
    396 
    397 typedef
    398    struct {
    399       /* Primary description */
    400       RetLocPrimary pri;
    401       /* For .pri == RLPri_V128SpRel or RLPri_V256SpRel only, gives
    402          the offset of the lowest addressed byte of the value,
    403          relative to the stack pointer.  For all other .how values,
    404          has no meaning and should be zero. */
    405       Int spOff;
    406    }
    407    RetLoc;
    408 
    409 extern void ppRetLoc ( RetLoc rloc );
    410 
    411 static inline RetLoc mk_RetLoc_simple ( RetLocPrimary pri ) {
    412    vassert(pri >= RLPri_INVALID && pri <= RLPri_2Int);
    413    return (RetLoc){pri, 0};
    414 }
    415 
    416 static inline RetLoc mk_RetLoc_spRel ( RetLocPrimary pri, Int off ) {
    417    vassert(pri >= RLPri_V128SpRel && pri <= RLPri_V256SpRel);
    418    return (RetLoc){pri, off};
    419 }
    420 
    421 static inline Bool is_sane_RetLoc ( RetLoc rloc ) {
    422    switch (rloc.pri) {
    423       case RLPri_None: case RLPri_Int: case RLPri_2Int:
    424          return rloc.spOff == 0;
    425       case RLPri_V128SpRel: case RLPri_V256SpRel:
    426          return True;
    427       default:
    428          return False;
    429    }
    430 }
    431 
    432 static inline RetLoc mk_RetLoc_INVALID ( void ) {
    433    return (RetLoc){RLPri_INVALID, 0};
    434 }
    435 
    436 static inline Bool is_RetLoc_INVALID ( RetLoc rl ) {
    437    return rl.pri == RLPri_INVALID && rl.spOff == 0;
    438 }
    439 
    440 
    441 /*---------------------------------------------------------*/
    442 /*--- Reg alloc: TODO: move somewhere else              ---*/
    443 /*---------------------------------------------------------*/
    444 
    445 extern
    446 HInstrArray* doRegisterAllocation (
    447 
    448    /* Incoming virtual-registerised code. */
    449    HInstrArray* instrs_in,
    450 
    451    /* The real-register universe to use.  This contains facts about
    452       real registers, one of which is the set of registers available
    453       for allocation. */
    454    const RRegUniverse* univ,
    455 
    456    /* Return True iff the given insn is a reg-reg move, in which
    457       case also return the src and dst regs. */
    458    Bool (*isMove) (const HInstr*, HReg*, HReg*),
    459 
    460    /* Get info about register usage in this insn. */
    461    void (*getRegUsage) (HRegUsage*, const HInstr*, Bool),
    462 
    463    /* Apply a reg-reg mapping to an insn. */
    464    void (*mapRegs) (HRegRemap*, HInstr*, Bool),
    465 
    466    /* Return insn(s) to spill/restore a real reg to a spill slot
    467       offset.  And optionally a function to do direct reloads. */
    468    void    (*genSpill) (  HInstr**, HInstr**, HReg, Int, Bool ),
    469    void    (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool ),
    470    HInstr* (*directReload) ( HInstr*, HReg, Short ),
    471    Int     guest_sizeB,
    472 
    473    /* For debug printing only. */
    474    void (*ppInstr) ( const HInstr*, Bool ),
    475    void (*ppReg) ( HReg ),
    476 
    477    /* 32/64bit mode */
    478    Bool mode64
    479 );
    480 
    481 
    482 #endif /* ndef __VEX_HOST_GENERIC_REGS_H */
    483 
    484 /*---------------------------------------------------------------*/
    485 /*---                                     host_generic_regs.h ---*/
    486 /*---------------------------------------------------------------*/
    487