Path: blob/master/thirdparty/graphite/src/call_machine.cpp
9902 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 call threaded interpreter implmentation for machine.h4// Author: Tim Eves56// Build either this interpreter or the direct_machine implementation.7// The call threaded interpreter is portable across compilers and8// architectures as well as being useful to debug (you can set breakpoints on9// opcodes) but is slower that the direct threaded interpreter by a factor of 21011#include <cassert>12#include <cstring>13#include <graphite2/Segment.h>14#include "inc/Machine.h"15#include "inc/Segment.h"16#include "inc/Slot.h"17#include "inc/Rule.h"1819// Disable the unused parameter warning as th compiler is mistaken since dp20// is always updated (even if by 0) on every opcode.21#ifdef __GNUC__22#pragma GCC diagnostic ignored "-Wunused-parameter"23#endif2425#define registers const byte * & dp, vm::Machine::stack_t * & sp, \26vm::Machine::stack_t * const sb, regbank & reg2728// These are required by opcodes.h and should not be changed29#define STARTOP(name) bool name(registers) REGPARM(4);\30bool name(registers) {31#define ENDOP return (sp - sb)/Machine::STACK_MAX==0; \32}3334#define EXIT(status) { push(status); return false; }3536// This is required by opcode_table.h37#define do_(name) instr(name)383940using namespace graphite2;41using namespace vm;4243struct regbank {44slotref is;45slotref * map;46SlotMap & smap;47slotref * const map_base;48const instr * & ip;49uint8 direction;50int8 flags;51Machine::status_t & status;52};5354typedef bool (* ip_t)(registers);5556// Pull in the opcode definitions57// We pull these into a private namespace so these otherwise common names dont58// pollute the toplevel namespace.59namespace {60#define smap reg.smap61#define seg smap.segment62#define is reg.is63#define ip reg.ip64#define map reg.map65#define mapb reg.map_base66#define flags reg.flags67#define dir reg.direction68#define status reg.status6970#include "inc/opcodes.h"7172#undef smap73#undef seg74#undef is75#undef ip76#undef map77#undef mapb78#undef flags79#undef dir80}8182Machine::stack_t Machine::run(const instr * program,83const byte * data,84slotref * & map)8586{87assert(program != 0);8889// Declare virtual machine registers90const instr * ip = program-1;91const byte * dp = data;92stack_t * sp = _stack + Machine::STACK_GUARD,93* const sb = sp;94regbank reg = {*map, map, _map, _map.begin()+_map.context(), ip, _map.dir(), 0, _status};9596// Run the program97while ((reinterpret_cast<ip_t>(*++ip))(dp, sp, sb, reg)) {}98const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0;99100check_final_stack(sp);101map = reg.map;102*map = reg.is;103return ret;104}105106// Pull in the opcode table107namespace {108#include "inc/opcode_table.h"109}110111const opcode_t * Machine::getOpcodeTable() throw()112{113return opcode_table;114}115116117