mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
frame layout refactor
This commit is contained in:
@@ -23,11 +23,18 @@ struct symbol_table {
|
|||||||
struct bytecode {
|
struct bytecode {
|
||||||
uint16_t* code;
|
uint16_t* code;
|
||||||
int codelen;
|
int codelen;
|
||||||
int framesize;
|
|
||||||
|
int nlocals;
|
||||||
|
int nclosures;
|
||||||
|
|
||||||
json_t* constants;
|
json_t* constants;
|
||||||
struct symbol_table* globals;
|
struct symbol_table* globals;
|
||||||
|
|
||||||
|
struct bytecode* subfunctions;
|
||||||
|
int nsubfunctions;
|
||||||
};
|
};
|
||||||
|
|
||||||
void dump_disassembly(struct bytecode* code);
|
void dump_disassembly(struct bytecode* code);
|
||||||
void dump_operation(struct bytecode* bc, uint16_t* op);
|
void dump_operation(struct bytecode* bc, uint16_t* op);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -274,7 +274,8 @@ struct bytecode* block_compile(struct symbol_table* syms, block b) {
|
|||||||
}
|
}
|
||||||
free(stack_height);
|
free(stack_height);
|
||||||
bc->constants = constant_pool;
|
bc->constants = constant_pool;
|
||||||
bc->framesize = maxvar + 2; // FIXME: frames of size zero?
|
bc->nlocals = maxvar + 2; // FIXME: frames of size zero?
|
||||||
|
bc->nclosures = 0;
|
||||||
bc->globals = syms;
|
bc->globals = syms;
|
||||||
return bc;
|
return bc;
|
||||||
}
|
}
|
||||||
|
|||||||
110
c/execute.c
110
c/execute.c
@@ -10,6 +10,7 @@
|
|||||||
#include "compile.h"
|
#include "compile.h"
|
||||||
|
|
||||||
#include "forkable_stack.h"
|
#include "forkable_stack.h"
|
||||||
|
#include "frame_layout.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -52,34 +53,19 @@ typedef struct {
|
|||||||
stackval sv;
|
stackval sv;
|
||||||
} data_stk_elem;
|
} data_stk_elem;
|
||||||
|
|
||||||
data_stk_elem* stk_push_frame(int n) {
|
|
||||||
return forkable_stack_push(&data_stk, sizeof(data_stk_elem) * n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stk_pop_frame(int n) {
|
|
||||||
forkable_stack_pop(&data_stk, sizeof(data_stk_elem) * n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stk_push(stackval val) {
|
void stk_push(stackval val) {
|
||||||
data_stk_elem* s = stk_push_frame(1);
|
data_stk_elem* s = forkable_stack_push(&data_stk, sizeof(data_stk_elem));
|
||||||
s->sv = val;
|
s->sv = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
stackval stk_pop() {
|
stackval stk_pop() {
|
||||||
data_stk_elem* s = forkable_stack_peek(&data_stk, sizeof(data_stk_elem));
|
data_stk_elem* s = forkable_stack_peek(&data_stk);
|
||||||
stackval sv = s->sv;
|
stackval sv = s->sv;
|
||||||
forkable_stack_pop(&data_stk, sizeof(data_stk_elem));
|
forkable_stack_pop(&data_stk);
|
||||||
return sv;
|
return sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct forkable_stack frame_stk;
|
||||||
typedef struct {
|
|
||||||
FORKABLE_STACK_HEADER;
|
|
||||||
struct bytecode* bc;
|
|
||||||
data_stk_elem* fp;
|
|
||||||
uint16_t* pc;
|
|
||||||
} call_stk_elem;
|
|
||||||
struct forkable_stack call_stk;
|
|
||||||
|
|
||||||
|
|
||||||
struct forkpoint {
|
struct forkpoint {
|
||||||
@@ -93,20 +79,20 @@ struct forkable_stack fork_stk;
|
|||||||
void stack_save(){
|
void stack_save(){
|
||||||
struct forkpoint* fork = forkable_stack_push(&fork_stk, sizeof(struct forkpoint));
|
struct forkpoint* fork = forkable_stack_push(&fork_stk, sizeof(struct forkpoint));
|
||||||
forkable_stack_save(&data_stk, &fork->saved_data_stack);
|
forkable_stack_save(&data_stk, &fork->saved_data_stack);
|
||||||
forkable_stack_save(&call_stk, &fork->saved_call_stack);
|
forkable_stack_save(&frame_stk, &fork->saved_call_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stack_switch() {
|
void stack_switch() {
|
||||||
struct forkpoint* fork = forkable_stack_peek(&fork_stk, sizeof(struct forkpoint));
|
struct forkpoint* fork = forkable_stack_peek(&fork_stk);
|
||||||
forkable_stack_switch(&data_stk, &fork->saved_data_stack);
|
forkable_stack_switch(&data_stk, &fork->saved_data_stack);
|
||||||
forkable_stack_switch(&call_stk, &fork->saved_call_stack);
|
forkable_stack_switch(&frame_stk, &fork->saved_call_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stack_restore(){
|
void stack_restore(){
|
||||||
struct forkpoint* fork = forkable_stack_peek(&fork_stk, sizeof(struct forkpoint));
|
struct forkpoint* fork = forkable_stack_peek(&fork_stk);
|
||||||
forkable_stack_restore(&data_stk, &fork->saved_data_stack);
|
forkable_stack_restore(&data_stk, &fork->saved_data_stack);
|
||||||
forkable_stack_restore(&call_stk, &fork->saved_call_stack);
|
forkable_stack_restore(&frame_stk, &fork->saved_call_stack);
|
||||||
forkable_stack_pop(&fork_stk, sizeof(struct forkpoint));
|
forkable_stack_pop(&fork_stk);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define stack_push stk_push
|
#define stack_push stk_push
|
||||||
@@ -115,29 +101,31 @@ void stack_restore(){
|
|||||||
#define ON_BACKTRACK(op) ((op)+NUM_OPCODES)
|
#define ON_BACKTRACK(op) ((op)+NUM_OPCODES)
|
||||||
|
|
||||||
json_t* jq_next() {
|
json_t* jq_next() {
|
||||||
assert(!forkable_stack_empty(&call_stk));
|
|
||||||
call_stk_elem* ctx = forkable_stack_peek(&call_stk, sizeof(call_stk_elem));
|
|
||||||
struct bytecode* bc = ctx->bc;
|
|
||||||
uint16_t* pc = ctx->pc;
|
|
||||||
data_stk_elem* fp = ctx->fp;
|
|
||||||
json_t* cpool = bc->constants;
|
|
||||||
|
|
||||||
json_t* cfunc_input[MAX_CFUNCTION_ARGS] = {0};
|
json_t* cfunc_input[MAX_CFUNCTION_ARGS] = {0};
|
||||||
json_t* cfunc_output[MAX_CFUNCTION_ARGS] = {0};
|
json_t* cfunc_output[MAX_CFUNCTION_ARGS] = {0};
|
||||||
|
|
||||||
|
|
||||||
|
assert(!forkable_stack_empty(&frame_stk));
|
||||||
|
uint16_t* pc = *frame_current_pc(&frame_stk);
|
||||||
|
|
||||||
int backtracking = 0;
|
int backtracking = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
*frame_current_pc(&frame_stk) = pc;
|
||||||
dump_operation(bc, pc);
|
dump_operation(frame_current_bytecode(&frame_stk), pc);
|
||||||
|
|
||||||
uint16_t opcode = *pc++;
|
uint16_t opcode = *pc++;
|
||||||
|
|
||||||
printf("\t");
|
printf("\t");
|
||||||
const struct opcode_description* opdesc = opcode_describe(opcode);
|
const struct opcode_description* opdesc = opcode_describe(opcode);
|
||||||
data_stk_elem* param = forkable_stack_peek(&data_stk, sizeof(data_stk_elem));
|
data_stk_elem* param;
|
||||||
for (int i=0; i<opdesc->stack_in; i++) {
|
for (int i=0; i<opdesc->stack_in; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
param = forkable_stack_peek(&data_stk);
|
||||||
|
} else {
|
||||||
|
param = forkable_stack_peek_next(&data_stk, param);
|
||||||
|
}
|
||||||
json_dumpf(param->sv.value, stdout, JSON_ENCODE_ANY);
|
json_dumpf(param->sv.value, stdout, JSON_ENCODE_ANY);
|
||||||
if (i < opdesc->stack_in-1) printf(" | ");
|
if (i < opdesc->stack_in-1) printf(" | ");
|
||||||
param = forkable_stack_peek_next(&data_stk, param, sizeof(data_stk_elem));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backtracking) {
|
if (backtracking) {
|
||||||
@@ -152,7 +140,7 @@ json_t* jq_next() {
|
|||||||
default: assert(0 && "invalid instruction");
|
default: assert(0 && "invalid instruction");
|
||||||
|
|
||||||
case LOADK: {
|
case LOADK: {
|
||||||
json_t* v = json_array_get(cpool, *pc++);
|
json_t* v = json_array_get(frame_current_bytecode(&frame_stk)->constants, *pc++);
|
||||||
assert(v);
|
assert(v);
|
||||||
stack_push(stackval_replace(stack_pop(), v));
|
stack_push(stackval_replace(stack_pop(), v));
|
||||||
break;
|
break;
|
||||||
@@ -205,17 +193,19 @@ json_t* jq_next() {
|
|||||||
|
|
||||||
case LOADV: {
|
case LOADV: {
|
||||||
uint16_t v = *pc++;
|
uint16_t v = *pc++;
|
||||||
stack_push(stackval_replace(stack_pop(), fp[v].sv.value));
|
json_t** var = frame_local_var(frame_current(&frame_stk), v);
|
||||||
|
stack_push(stackval_replace(stack_pop(), *var));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case STOREV: {
|
case STOREV: {
|
||||||
uint16_t v = *pc++;
|
uint16_t v = *pc++;
|
||||||
|
json_t** var = frame_local_var(frame_current(&frame_stk), v);
|
||||||
stackval val = stack_pop();
|
stackval val = stack_pop();
|
||||||
printf("V%d = ", v);
|
printf("V%d = ", v);
|
||||||
json_dumpf(val.value, stdout, JSON_ENCODE_ANY);
|
json_dumpf(val.value, stdout, JSON_ENCODE_ANY);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
fp[v].sv.value = val.value;
|
*var = val.value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,10 +267,7 @@ json_t* jq_next() {
|
|||||||
stack_save();
|
stack_save();
|
||||||
stack_push(array);
|
stack_push(array);
|
||||||
stack_push(stackval_root(json_integer(idx+1)));
|
stack_push(stackval_root(json_integer(idx+1)));
|
||||||
call_stk_elem* ctx = forkable_stack_push(&call_stk, sizeof(call_stk_elem));
|
frame_push_backtrack(&frame_stk, frame_current_bytecode(&frame_stk), pc - 1);
|
||||||
ctx->bc = bc;
|
|
||||||
ctx->fp = fp;
|
|
||||||
ctx->pc = pc - 1;
|
|
||||||
stack_switch();
|
stack_switch();
|
||||||
|
|
||||||
stackval sv = {json_array_get(array.value, idx),
|
stackval sv = {json_array_get(array.value, idx),
|
||||||
@@ -296,22 +283,15 @@ json_t* jq_next() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
stack_restore();
|
stack_restore();
|
||||||
call_stk_elem* ctx = forkable_stack_peek(&call_stk, sizeof(call_stk_elem));
|
pc = *frame_current_pc(&frame_stk);
|
||||||
bc = ctx->bc;
|
frame_pop(&frame_stk);
|
||||||
pc = ctx->pc;
|
|
||||||
fp = ctx->fp;
|
|
||||||
cpool = bc->constants;
|
|
||||||
forkable_stack_pop(&call_stk, sizeof(call_stk_elem));
|
|
||||||
backtracking = 1;
|
backtracking = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FORK: {
|
case FORK: {
|
||||||
stack_save();
|
stack_save();
|
||||||
call_stk_elem* ctx = forkable_stack_push(&call_stk, sizeof(call_stk_elem));
|
frame_push_backtrack(&frame_stk, frame_current_bytecode(&frame_stk), pc - 1);
|
||||||
ctx->bc = bc;
|
|
||||||
ctx->fp = fp;
|
|
||||||
ctx->pc = pc - 1;
|
|
||||||
stack_switch();
|
stack_switch();
|
||||||
pc++; // skip offset this time
|
pc++; // skip offset this time
|
||||||
break;
|
break;
|
||||||
@@ -324,17 +304,14 @@ json_t* jq_next() {
|
|||||||
|
|
||||||
case YIELD: {
|
case YIELD: {
|
||||||
json_t* value = stack_pop().value;
|
json_t* value = stack_pop().value;
|
||||||
call_stk_elem* ctx = forkable_stack_push(&call_stk, sizeof(call_stk_elem));
|
*frame_current_pc(&frame_stk) = pc;
|
||||||
ctx->bc = bc;
|
|
||||||
ctx->fp = fp;
|
|
||||||
ctx->pc = pc;
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CALL_BUILTIN_1_1: {
|
case CALL_BUILTIN_1_1: {
|
||||||
stackval top = stack_pop();
|
stackval top = stack_pop();
|
||||||
cfunc_input[0] = top.value;
|
cfunc_input[0] = top.value;
|
||||||
struct cfunction* func = &bc->globals->cfunctions[*pc++];
|
struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++];
|
||||||
printf(" call %s\n", func->name);
|
printf(" call %s\n", func->name);
|
||||||
func->fptr(cfunc_input, cfunc_output);
|
func->fptr(cfunc_input, cfunc_output);
|
||||||
stack_push(stackval_replace(top, cfunc_output[0]));
|
stack_push(stackval_replace(top, cfunc_output[0]));
|
||||||
@@ -348,13 +325,19 @@ json_t* jq_next() {
|
|||||||
cfunc_input[0] = top.value;
|
cfunc_input[0] = top.value;
|
||||||
cfunc_input[1] = a;
|
cfunc_input[1] = a;
|
||||||
cfunc_input[2] = b;
|
cfunc_input[2] = b;
|
||||||
struct cfunction* func = &bc->globals->cfunctions[*pc++];
|
struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++];
|
||||||
printf(" call %s\n", func->name);
|
printf(" call %s\n", func->name);
|
||||||
func->fptr(cfunc_input, cfunc_output);
|
func->fptr(cfunc_input, cfunc_output);
|
||||||
stack_push(stackval_replace(top, cfunc_output[0]));
|
stack_push(stackval_replace(top, cfunc_output[0]));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
case CALL_1_1: {
|
||||||
|
uint16_t nargs = *pc++;
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,16 +346,11 @@ json_t* jq_next() {
|
|||||||
|
|
||||||
void jq_init(struct bytecode* bc, json_t* input) {
|
void jq_init(struct bytecode* bc, json_t* input) {
|
||||||
forkable_stack_init(&data_stk, sizeof(stackval) * 100); // FIXME: lower this number, see if it breaks
|
forkable_stack_init(&data_stk, sizeof(stackval) * 100); // FIXME: lower this number, see if it breaks
|
||||||
forkable_stack_init(&call_stk, 1024); // FIXME: lower this number, see if it breaks
|
forkable_stack_init(&frame_stk, 1024); // FIXME: lower this number, see if it breaks
|
||||||
forkable_stack_init(&fork_stk, 1024); // FIXME: lower this number, see if it breaks
|
forkable_stack_init(&fork_stk, 1024); // FIXME: lower this number, see if it breaks
|
||||||
|
|
||||||
data_stk_elem* frame = stk_push_frame(bc->framesize);
|
|
||||||
|
|
||||||
stack_push(stackval_root(input));
|
stack_push(stackval_root(input));
|
||||||
call_stk_elem* ctx = forkable_stack_push(&call_stk, sizeof(call_stk_elem));
|
frame_push(&frame_stk, bc);
|
||||||
ctx->pc = bc->code;
|
|
||||||
ctx->bc = bc;
|
|
||||||
ctx->fp = frame;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_program(struct bytecode* bc) {
|
void run_program(struct bytecode* bc) {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#ifndef FORKABLE_STACK_H
|
||||||
|
#define FORKABLE_STACK_H
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -65,21 +67,21 @@ static void* forkable_stack_push(struct forkable_stack* s, size_t size) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* forkable_stack_peek(struct forkable_stack* s, size_t size) {
|
static void* forkable_stack_peek(struct forkable_stack* s) {
|
||||||
assert(!forkable_stack_empty(s));
|
assert(!forkable_stack_empty(s));
|
||||||
forkable_stack_check(s);
|
forkable_stack_check(s);
|
||||||
return (void*)(s->stk + s->pos);
|
return (void*)(s->stk + s->pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* forkable_stack_peek_next(struct forkable_stack* s, void* top, size_t size) {
|
static void* forkable_stack_peek_next(struct forkable_stack* s, void* top) {
|
||||||
forkable_stack_check(s);
|
forkable_stack_check(s);
|
||||||
struct forkable_stack_header* elem = top;
|
struct forkable_stack_header* elem = top;
|
||||||
return (void*)(s->stk + elem->next);
|
return (void*)(s->stk + elem->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void forkable_stack_pop(struct forkable_stack* s, size_t size) {
|
static void forkable_stack_pop(struct forkable_stack* s) {
|
||||||
forkable_stack_check(s);
|
forkable_stack_check(s);
|
||||||
struct forkable_stack_header* elem = forkable_stack_peek(s, size);
|
struct forkable_stack_header* elem = forkable_stack_peek(s);
|
||||||
s->pos = elem->next;
|
s->pos = elem->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,3 +116,4 @@ static void forkable_stack_restore(struct forkable_stack* s, struct forkable_sta
|
|||||||
s->savedlimit = state->prevlimit;
|
s->savedlimit = state->prevlimit;
|
||||||
forkable_stack_check(s);
|
forkable_stack_check(s);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
81
c/frame_layout.h
Normal file
81
c/frame_layout.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#ifndef FRAME_LAYOUT_H
|
||||||
|
#include "forkable_stack.h"
|
||||||
|
#include "bytecode.h"
|
||||||
|
#include <jansson.h>
|
||||||
|
|
||||||
|
struct closure {
|
||||||
|
struct bytecode* bc;
|
||||||
|
uint16_t* pc;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union frame_elem {
|
||||||
|
FORKABLE_STACK_HEADER;
|
||||||
|
struct closure closure;
|
||||||
|
json_t* jsonval;
|
||||||
|
} *frame_ptr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Frame layout
|
||||||
|
* fr[0] - FORKABLE_STACK_HEADER (next pointer)
|
||||||
|
* fr[1] - self (used to store return addresses, etc)
|
||||||
|
* fr[2...nclosures+2] - closure params
|
||||||
|
* fr[nclosures+2..nclosures+nlocals+2] - local variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int frame_size(struct bytecode* bc) {
|
||||||
|
return sizeof(union frame_elem) * (bc->nclosures + bc->nlocals + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct closure* frame_self(frame_ptr fr) {
|
||||||
|
return &fr[1].closure;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct closure* frame_closure_arg(frame_ptr fr, int closure) {
|
||||||
|
assert(closure >= 0);
|
||||||
|
assert(closure < frame_self(fr)->bc->nclosures);
|
||||||
|
return &fr[2+closure].closure;
|
||||||
|
}
|
||||||
|
|
||||||
|
static json_t** frame_local_var(frame_ptr fr, int var) {
|
||||||
|
assert(var >= 0);
|
||||||
|
assert(var < frame_self(fr)->bc->nlocals);
|
||||||
|
return &fr[2 + frame_self(fr)->bc->nclosures + var].jsonval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static frame_ptr frame_current(struct forkable_stack* stk) {
|
||||||
|
frame_ptr fp = forkable_stack_peek(stk);
|
||||||
|
struct bytecode* bc = frame_self(fp)->bc;
|
||||||
|
assert(frame_self(fp)->pc >= bc->code && frame_self(fp)->pc < bc->code + bc->codelen);
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bytecode* frame_current_bytecode(struct forkable_stack* stk) {
|
||||||
|
return frame_self(frame_current(stk))->bc;
|
||||||
|
}
|
||||||
|
static uint16_t** frame_current_pc(struct forkable_stack* stk) {
|
||||||
|
return &frame_self(frame_current(stk))->pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void frame_push(struct forkable_stack* stk, struct bytecode* bc) {
|
||||||
|
frame_ptr fp = forkable_stack_push(stk, frame_size(bc));
|
||||||
|
frame_self(fp)->bc = bc;
|
||||||
|
frame_self(fp)->pc = bc->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void frame_push_backtrack(struct forkable_stack* stk,
|
||||||
|
struct bytecode* bc, uint16_t* pc) {
|
||||||
|
frame_ptr fp = forkable_stack_push(stk, sizeof(union frame_elem) * 2);
|
||||||
|
frame_self(fp)->bc = bc;
|
||||||
|
frame_self(fp)->pc = pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void frame_pop(struct forkable_stack* stk) {
|
||||||
|
forkable_stack_pop(stk);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#define VARIABLE (OP_HAS_IMMEDIATE | OP_HAS_VARIABLE)
|
#define VARIABLE (OP_HAS_IMMEDIATE | OP_HAS_VARIABLE)
|
||||||
#define BRANCH (OP_HAS_IMMEDIATE | OP_HAS_BRANCH)
|
#define BRANCH (OP_HAS_IMMEDIATE | OP_HAS_BRANCH)
|
||||||
#define CFUNC (OP_HAS_IMMEDIATE | OP_HAS_SYMBOL | OP_HAS_CFUNC)
|
#define CFUNC (OP_HAS_IMMEDIATE | OP_HAS_SYMBOL | OP_HAS_CFUNC)
|
||||||
|
#define UFUNC (OP_HAS_IMMEDIATE | OP_HAS_UFUNC)
|
||||||
|
|
||||||
#define OP(name, imm, in, out) \
|
#define OP(name, imm, in, out) \
|
||||||
{name, #name, imm, in, out},
|
{name, #name, imm, in, out},
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ enum {
|
|||||||
OP_HAS_VARIABLE = 4,
|
OP_HAS_VARIABLE = 4,
|
||||||
OP_HAS_BRANCH = 8,
|
OP_HAS_BRANCH = 8,
|
||||||
OP_HAS_SYMBOL = 16,
|
OP_HAS_SYMBOL = 16,
|
||||||
OP_HAS_CFUNC = 32
|
OP_HAS_CFUNC = 32,
|
||||||
|
OP_HAS_UFUNC = 64,
|
||||||
};
|
};
|
||||||
struct opcode_description {
|
struct opcode_description {
|
||||||
opcode op;
|
opcode op;
|
||||||
|
|||||||
@@ -16,3 +16,5 @@ OP(INSERT, NONE, 4, 2)
|
|||||||
|
|
||||||
OP(CALL_BUILTIN_1_1, CFUNC, 1, 1)
|
OP(CALL_BUILTIN_1_1, CFUNC, 1, 1)
|
||||||
OP(CALL_BUILTIN_3_1, CFUNC, 3, 1)
|
OP(CALL_BUILTIN_3_1, CFUNC, 3, 1)
|
||||||
|
|
||||||
|
OP(CALL_1_1, UFUNC, 1, 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user