Path: blob/master/thirdparty/graphite/src/inc/Machine.h
9906 views
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later1// Copyright 2010, SIL International, All rights reserved.23// This general interpreter interface.4// Author: Tim Eves56// Build one of direct_machine.cpp or call_machine.cpp to implement this7// interface.89#pragma once10#include <cstring>11#include <limits>12#include <graphite2/Types.h>13#include "inc/Main.h"1415#if defined(__GNUC__)16#if defined(__clang__) || (__GNUC__ * 100 + __GNUC_MINOR__ * 10) < 43017#define HOT18#if defined(__x86_64)19#define REGPARM(n) __attribute__((regparm(n)))20#else21#define REGPARM(n)22#endif23#else24#define HOT __attribute__((hot))25#if defined(__x86_64)26#define REGPARM(n) __attribute__((hot, regparm(n)))27#else28#define REGPARM(n)29#endif30#endif31#else32#define HOT33#define REGPARM(n)34#endif3536#if defined(__MINGW32__)37// MinGW's <limits> at some point includes winnt.h which #define's a38// DELETE macro, which conflicts with enum opcode below, so we undefine39// it here.40#undef DELETE41#endif4243namespace graphite2 {4445// Forward declarations46class Segment;47class Slot;48class SlotMap;495051namespace vm52{535455typedef void * instr;56typedef Slot * slotref;5758enum {VARARGS = 0xff, MAX_NAME_LEN=32};5960enum opcode {61NOP = 0,6263PUSH_BYTE, PUSH_BYTEU, PUSH_SHORT, PUSH_SHORTU, PUSH_LONG,6465ADD, SUB, MUL, DIV,66MIN_, MAX_,67NEG,68TRUNC8, TRUNC16,6970COND,7172AND, OR, NOT,73EQUAL, NOT_EQ,74LESS, GTR, LESS_EQ, GTR_EQ,7576NEXT, NEXT_N, COPY_NEXT,77PUT_GLYPH_8BIT_OBS, PUT_SUBS_8BIT_OBS, PUT_COPY,78INSERT, DELETE,79ASSOC,80CNTXT_ITEM,8182ATTR_SET, ATTR_ADD, ATTR_SUB,83ATTR_SET_SLOT,84IATTR_SET_SLOT,85PUSH_SLOT_ATTR, PUSH_GLYPH_ATTR_OBS,86PUSH_GLYPH_METRIC, PUSH_FEAT,87PUSH_ATT_TO_GATTR_OBS, PUSH_ATT_TO_GLYPH_METRIC,88PUSH_ISLOT_ATTR,8990PUSH_IGLYPH_ATTR, // not implemented9192POP_RET, RET_ZERO, RET_TRUE,93IATTR_SET, IATTR_ADD, IATTR_SUB,94PUSH_PROC_STATE, PUSH_VERSION,95PUT_SUBS, PUT_SUBS2, PUT_SUBS3,96PUT_GLYPH, PUSH_GLYPH_ATTR, PUSH_ATT_TO_GLYPH_ATTR,97BITOR, BITAND, BITNOT,98BITSET, SET_FEAT,99MAX_OPCODE,100// private opcodes for internal use only, comes after all other on disk opcodes101TEMP_COPY = MAX_OPCODE102};103104struct opcode_t105{106instr impl[2];107uint8 param_sz;108char name[MAX_NAME_LEN];109};110111112class Machine113{114public:115typedef int32 stack_t;116static size_t const STACK_ORDER = 10,117STACK_MAX = 1 << STACK_ORDER,118STACK_GUARD = 2;119120class Code;121122enum status_t {123finished = 0,124stack_underflow,125stack_not_empty,126stack_overflow,127slot_offset_out_bounds,128died_early129};130131Machine(SlotMap &) throw();132static const opcode_t * getOpcodeTable() throw();133134CLASS_NEW_DELETE;135136SlotMap & slotMap() const throw();137status_t status() const throw();138// operator bool () const throw();139140private:141void check_final_stack(const stack_t * const sp);142stack_t run(const instr * program, const byte * data,143slotref * & map) HOT;144145SlotMap & _map;146stack_t _stack[STACK_MAX + 2*STACK_GUARD];147status_t _status;148};149150inline Machine::Machine(SlotMap & map) throw()151: _map(map), _status(finished)152{153// Initialise stack guard +1 entries as the stack pointer points to the154// current top of stack, hence the first push will never write entry 0.155// Initialising the guard space like this is unnecessary and is only156// done to keep valgrind happy during fuzz testing. Hopefully loop157// unrolling will flatten this.158for (size_t n = STACK_GUARD + 1; n; --n) _stack[n-1] = 0;159}160161inline SlotMap& Machine::slotMap() const throw()162{163return _map;164}165166inline Machine::status_t Machine::status() const throw()167{168return _status;169}170171inline void Machine::check_final_stack(const stack_t * const sp)172{173if (_status != finished) return;174175stack_t const * const base = _stack + STACK_GUARD,176* const limit = base + STACK_MAX;177if (sp < base) _status = stack_underflow; // This should be impossible now.178else if (sp >= limit) _status = stack_overflow; // So should this.179else if (sp != base) _status = stack_not_empty;180}181182} // namespace vm183} // namespace graphite2184185186