gfx/graphite2/src/inc/Machine.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/graphite2/src/inc/Machine.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,197 @@
     1.4 +/*  GRAPHITE2 LICENSING
     1.5 +
     1.6 +    Copyright 2010, SIL International
     1.7 +    All rights reserved.
     1.8 +
     1.9 +    This library is free software; you can redistribute it and/or modify
    1.10 +    it under the terms of the GNU Lesser General Public License as published
    1.11 +    by the Free Software Foundation; either version 2.1 of License, or
    1.12 +    (at your option) any later version.
    1.13 +
    1.14 +    This program is distributed in the hope that it will be useful,
    1.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.17 +    Lesser General Public License for more details.
    1.18 +
    1.19 +    You should also have received a copy of the GNU Lesser General Public
    1.20 +    License along with this library in the file named "LICENSE".
    1.21 +    If not, write to the Free Software Foundation, 51 Franklin Street, 
    1.22 +    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
    1.23 +    internet at http://www.fsf.org/licenses/lgpl.html.
    1.24 +
    1.25 +Alternatively, the contents of this file may be used under the terms of the
    1.26 +Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
    1.27 +License, as published by the Free Software Foundation, either version 2
    1.28 +of the License or (at your option) any later version.
    1.29 +*/
    1.30 +// This general interpreter interface.
    1.31 +// Author: Tim Eves
    1.32 +
    1.33 +// Build one of direct_machine.cpp or call_machine.cpp to implement this 
    1.34 +// interface.
    1.35 +
    1.36 +#pragma once
    1.37 +#include <cstring>
    1.38 +#include <graphite2/Types.h>
    1.39 +#include "inc/Main.h"
    1.40 +
    1.41 +#if defined(__GNUC__)
    1.42 +#if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ * 10) < 430
    1.43 +#define     HOT
    1.44 +#if defined(__x86_64)
    1.45 +#define     REGPARM(n)      __attribute__((regparm(n)))
    1.46 +#else
    1.47 +#define     REGPARM(n)
    1.48 +#endif
    1.49 +#else
    1.50 +#define     HOT             __attribute__((hot))
    1.51 +#if defined(__x86_64)
    1.52 +#define     REGPARM(n)      __attribute__((hot, regparm(n)))
    1.53 +#else
    1.54 +#define     REGPARM(n)
    1.55 +#endif
    1.56 +#endif
    1.57 +#else
    1.58 +#define     HOT
    1.59 +#define     REGPARM(n)
    1.60 +#endif
    1.61 +
    1.62 +namespace graphite2 {
    1.63 +
    1.64 +// Forward declarations
    1.65 +class Segment;
    1.66 +class Slot;
    1.67 +class SlotMap;
    1.68 +
    1.69 +
    1.70 +namespace vm 
    1.71 +{
    1.72 +
    1.73 +
    1.74 +typedef void * instr;
    1.75 +typedef Slot * slotref;
    1.76 +
    1.77 +enum {VARARGS = 0xff, MAX_NAME_LEN=32};
    1.78 +
    1.79 +enum opcode {
    1.80 +    NOP = 0,
    1.81 +
    1.82 +    PUSH_BYTE,      PUSH_BYTEU,     PUSH_SHORT,     PUSH_SHORTU,    PUSH_LONG,
    1.83 +
    1.84 +    ADD,            SUB,            MUL,            DIV,
    1.85 +    MIN_,           MAX_,
    1.86 +    NEG,
    1.87 +    TRUNC8,         TRUNC16,
    1.88 +
    1.89 +    COND,
    1.90 +
    1.91 +    AND,            OR,             NOT,
    1.92 +    EQUAL,          NOT_EQ,
    1.93 +    LESS,           GTR,            LESS_EQ,        GTR_EQ,
    1.94 +
    1.95 +    NEXT,           NEXT_N,         COPY_NEXT,
    1.96 +    PUT_GLYPH_8BIT_OBS,              PUT_SUBS_8BIT_OBS,   PUT_COPY,
    1.97 +    INSERT,         DELETE,
    1.98 +    ASSOC,
    1.99 +    CNTXT_ITEM,
   1.100 +
   1.101 +    ATTR_SET,       ATTR_ADD,       ATTR_SUB,
   1.102 +    ATTR_SET_SLOT,
   1.103 +    IATTR_SET_SLOT,
   1.104 +    PUSH_SLOT_ATTR,                 PUSH_GLYPH_ATTR_OBS,
   1.105 +    PUSH_GLYPH_METRIC,              PUSH_FEAT,
   1.106 +    PUSH_ATT_TO_GATTR_OBS,          PUSH_ATT_TO_GLYPH_METRIC,
   1.107 +    PUSH_ISLOT_ATTR,
   1.108 +
   1.109 +    PUSH_IGLYPH_ATTR,    // not implemented
   1.110 +
   1.111 +    POP_RET,                        RET_ZERO,           RET_TRUE,
   1.112 +    IATTR_SET,                      IATTR_ADD,          IATTR_SUB,
   1.113 +    PUSH_PROC_STATE,                PUSH_VERSION,
   1.114 +    PUT_SUBS,                       PUT_SUBS2,          PUT_SUBS3,
   1.115 +    PUT_GLYPH,                      PUSH_GLYPH_ATTR,    PUSH_ATT_TO_GLYPH_ATTR,
   1.116 +    MAX_OPCODE,
   1.117 +    // private opcodes for internal use only, comes after all other on disk opcodes
   1.118 +    TEMP_COPY = MAX_OPCODE
   1.119 +};
   1.120 +
   1.121 +struct opcode_t 
   1.122 +{
   1.123 +    instr           impl[2];
   1.124 +    uint8           param_sz;
   1.125 +    char            name[MAX_NAME_LEN];
   1.126 +};
   1.127 +
   1.128 +
   1.129 +class Machine
   1.130 +{
   1.131 +public:
   1.132 +    typedef int32  stack_t;
   1.133 +    static size_t const STACK_ORDER  = 10,
   1.134 +                        STACK_MAX    = 1 << STACK_ORDER,
   1.135 +                        STACK_GUARD  = 2;
   1.136 +
   1.137 +    class Code;
   1.138 +
   1.139 +    enum status_t {
   1.140 +        finished = 0,
   1.141 +        stack_underflow,
   1.142 +        stack_not_empty,
   1.143 +        stack_overflow,
   1.144 +        slot_offset_out_bounds
   1.145 +    };
   1.146 +
   1.147 +    Machine(SlotMap &) throw();
   1.148 +    static const opcode_t *   getOpcodeTable() throw();
   1.149 +
   1.150 +    CLASS_NEW_DELETE;
   1.151 +
   1.152 +    SlotMap   & slotMap() const throw();
   1.153 +    status_t    status() const throw();
   1.154 +    operator bool () const throw();
   1.155 +
   1.156 +private:
   1.157 +    void    check_final_stack(const stack_t * const sp);
   1.158 +    stack_t run(const instr * program, const byte * data,
   1.159 +                slotref * & map) HOT;
   1.160 +
   1.161 +    SlotMap       & _map;
   1.162 +    stack_t         _stack[STACK_MAX + 2*STACK_GUARD];
   1.163 +    status_t        _status;
   1.164 +};
   1.165 +
   1.166 +inline Machine::Machine(SlotMap & map) throw()
   1.167 +: _map(map), _status(finished)
   1.168 +{
   1.169 +    // Initialise stack guard +1 entries as the stack pointer points to the
   1.170 +    //  current top of stack, hence the first push will never write entry 0.
   1.171 +    // Initialising the guard space like this is unnecessary and is only
   1.172 +    //  done to keep valgrind happy during fuzz testing.  Hopefully loop
   1.173 +    //  unrolling will flatten this.
   1.174 +    for (size_t n = STACK_GUARD + 1; n; --n)  _stack[n-1] = 0;
   1.175 +}
   1.176 +
   1.177 +inline SlotMap& Machine::slotMap() const throw()
   1.178 +{
   1.179 +    return _map;
   1.180 +}
   1.181 +
   1.182 +inline Machine::status_t Machine::status() const throw()
   1.183 +{
   1.184 +    return _status;
   1.185 +}
   1.186 +
   1.187 +inline void Machine::check_final_stack(const int32 * const sp)
   1.188 +{
   1.189 +    stack_t const * const base  = _stack + STACK_GUARD,
   1.190 +                  * const limit = base + STACK_MAX;
   1.191 +    if      (sp <  base)    _status = stack_underflow;       // This should be impossible now.
   1.192 +    else if (sp >= limit)   _status = stack_overflow;        // So should this.
   1.193 +    else if (sp != base)    _status = stack_not_empty;
   1.194 +}
   1.195 +
   1.196 +} // namespace vm
   1.197 +} // namespace graphite2
   1.198 +
   1.199 +
   1.200 +

mercurial