233 lines
8.3 KiB
C
233 lines
8.3 KiB
C
/********************************************************************
|
|
** Copyright (c) 2018-2020 Guan Wenliang
|
|
** This file is part of the Berry default interpreter.
|
|
** skiars@qq.com, https://github.com/Skiars/berry
|
|
** See Copyright Notice in the LICENSE file or at
|
|
** https://github.com/Skiars/berry/blob/master/LICENSE
|
|
********************************************************************/
|
|
#include "be_object.h"
|
|
#include "be_module.h"
|
|
#include "be_string.h"
|
|
#include "be_vector.h"
|
|
#include "be_class.h"
|
|
#include "be_debug.h"
|
|
#include "be_map.h"
|
|
#include "be_vm.h"
|
|
#include "be_decoder.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#if BE_USE_SOLIDIFY_MODULE
|
|
|
|
#ifndef INST_BUF_SIZE
|
|
#define INST_BUF_SIZE 96
|
|
#endif
|
|
|
|
#define logbuf(...) snprintf(__lbuf, sizeof(__lbuf), __VA_ARGS__)
|
|
|
|
#define logfmt(...) \
|
|
do { \
|
|
char __lbuf[INST_BUF_SIZE]; \
|
|
logbuf(__VA_ARGS__); \
|
|
be_writestring(__lbuf); \
|
|
} while (0)
|
|
|
|
/* output only valid types for ktab, or NULL */
|
|
static const char * m_type_ktab(int type)
|
|
{
|
|
switch (type){
|
|
case BE_NIL: return "BE_NIL";
|
|
case BE_INT: return "BE_INT";
|
|
case BE_REAL: return "BE_REAL";
|
|
case BE_BOOL: return "BE_BOOL";
|
|
case BE_STRING: return "BE_STRING";
|
|
default: return NULL;
|
|
}
|
|
}
|
|
|
|
static void m_solidify_closure(bvm *vm, bclosure *cl, int builtins)
|
|
{
|
|
bproto *pr = cl->proto;
|
|
const char * func_name = str(pr->name);
|
|
const char * func_source = str(pr->source);
|
|
// logfmt("// == builtin_count %i\n", builtins);
|
|
|
|
// logfmt("// type %i, ", cl->type);
|
|
// logfmt("// marked %i, ", cl->marked);
|
|
// logfmt("// nupvals %i\n", cl->nupvals);
|
|
|
|
// logfmt("// PROTO:\n");
|
|
// logfmt("// type %i, ", pr->type);
|
|
// logfmt("// marked %i, ", pr->marked);
|
|
// logfmt("// nstack %i, ", pr->nstack);
|
|
// logfmt("// argcs %i, ", pr->argc);
|
|
// // logfmt("// varg %i\n", pr->varg);
|
|
|
|
// logfmt("// gray %p\n", (void*)pr->gray);
|
|
// logfmt("// upvals %p\n", (void*)pr->upvals);
|
|
// logfmt("// proto_tab %p (%i)\n", (void*)pr->ptab, pr->nproto);
|
|
|
|
// logfmt("// name %s\n", str(pr->name));
|
|
// logfmt("// source %s\n", str(pr->source));
|
|
|
|
// logfmt("\n");
|
|
|
|
// logfmt("// ktab %p (%i)\n", (void*)pr->ktab, pr->nconst);
|
|
// for (int i = 0; i < pr->nconst; i++) {
|
|
// logfmt("// const[%i] type %i (%s) %p", i, pr->ktab[i].type, be_vtype2str(&pr->ktab[i]), pr->ktab[i].v.p);
|
|
// if (pr->ktab[i].type == BE_STRING) {
|
|
// logfmt(" = '%s'", str(pr->ktab[i].v.s));
|
|
// }
|
|
// logfmt("\n");
|
|
// }
|
|
|
|
logfmt("\n");
|
|
logfmt("/********************************************************************\n");
|
|
logfmt("** Solidified function: %s\n", func_name);
|
|
logfmt("********************************************************************/\n\n");
|
|
|
|
/* create static strings for name and source */
|
|
logfmt("be_define_local_const_str(%s_str_name, \"%s\", %i, 0, %u, 0);\n",
|
|
func_name, func_name, be_strhash(pr->name), str_len(pr->name));
|
|
logfmt("be_define_local_const_str(%s_str_source, \"%s\", %i, 0, %u, 0);\n",
|
|
func_name, func_source, be_strhash(pr->source), str_len(pr->source));
|
|
|
|
/* create static strings first */
|
|
for (int i = 0; i < pr->nconst; i++) {
|
|
if (pr->ktab[i].type == BE_STRING) {
|
|
logfmt("be_define_local_const_str(%s_str_%i, \"",
|
|
func_name, i);
|
|
be_writestring(str(pr->ktab[i].v.s));
|
|
size_t len = strlen(str(pr->ktab[i].v.s));
|
|
if (len >= 255) {
|
|
be_raise(vm, "internal_error", "Strings greater than 255 chars not supported yet");
|
|
}
|
|
logfmt("\", %i, 0, %zu, 0);\n", be_strhash(pr->ktab[i].v.s), len >= 255 ? 255 : len);
|
|
}
|
|
}
|
|
logfmt("\n");
|
|
|
|
logfmt("static const bvalue %s_ktab[%i] = {\n", func_name, pr->nconst);
|
|
for (int k = 0; k < pr->nconst; k++) {
|
|
int type = pr->ktab[k].type;
|
|
const char *type_name = m_type_ktab(type);
|
|
if (type_name == NULL) {
|
|
char error[64];
|
|
snprintf(error, sizeof(error), "Unsupported type in function constants: %i", type);
|
|
be_raise(vm, "internal_error", error);
|
|
}
|
|
if (type == BE_STRING) {
|
|
logfmt(" { { .s=be_local_const_str(%s_str_%i) }, %s},\n", func_name, k, type_name);
|
|
} else if (type == BE_INT) {
|
|
logfmt(" { { .i=%" BE_INT_FMTLEN "i }, %s},\n", pr->ktab[k].v.i, type_name);
|
|
} else if (type == BE_REAL) {
|
|
#if BE_USE_SINGLE_FLOAT
|
|
logfmt(" { { .p=(void*)0x%08X }, %s},\n", (uint32_t) pr->ktab[k].v.p, type_name);
|
|
#else
|
|
logfmt(" { { .p=(void*)0x%016llX }, %s},\n", (uint64_t) pr->ktab[k].v.p, type_name);
|
|
#endif
|
|
} else if (type == BE_BOOL) {
|
|
logfmt(" { { .b=%i }, %s},\n", pr->ktab[k].v.b, type_name);
|
|
}
|
|
}
|
|
logfmt("};\n\n");
|
|
|
|
logfmt("static const uint32_t %s_code[%i] = {\n", func_name, pr->codesize);
|
|
for (int pc = 0; pc < pr->codesize; pc++) {
|
|
uint32_t ins = pr->code[pc];
|
|
logfmt(" 0x%04X, //", ins);
|
|
be_print_inst(ins, pc);
|
|
bopcode op = IGET_OP(ins);
|
|
if (op == OP_GETGBL || op == OP_SETGBL) {
|
|
// check if the global is in built-ins
|
|
int glb = IGET_Bx(ins);
|
|
if (glb > builtins) {
|
|
// not supported
|
|
logfmt("\n===== unsupported global G%d\n", glb);
|
|
be_raise(vm, "internal_error", "Unsupported access to non-builtin global");
|
|
}
|
|
}
|
|
}
|
|
logfmt("};\n\n");
|
|
|
|
logfmt("static const bproto %s_proto = {\n", func_name);
|
|
// bcommon_header
|
|
logfmt(" NULL, // bgcobject *next\n");
|
|
logfmt(" %i, // type\n", pr->type);
|
|
logfmt(" GC_CONST, // marked\n");
|
|
//
|
|
logfmt(" %i, // nstack\n", pr->nstack);
|
|
logfmt(" %i, // nupvals\n", pr->nupvals);
|
|
logfmt(" %i, // argc\n", pr->argc);
|
|
logfmt(" %i, // varg\n", pr->varg);
|
|
if (pr->nproto > 0) {
|
|
be_raise(vm, "internal_error", "unsupported non-null proto list");
|
|
}
|
|
logfmt(" NULL, // bgcobject *gray\n");
|
|
logfmt(" NULL, // bupvaldesc *upvals\n");
|
|
logfmt(" (bvalue*) &%s_ktab, // ktab\n", func_name);
|
|
logfmt(" NULL, // bproto **ptab\n");
|
|
logfmt(" (binstruction*) &%s_code, // code\n", func_name);
|
|
logfmt(" be_local_const_str(%s_str_name), // name\n", func_name);
|
|
logfmt(" %i, // codesize\n", pr->codesize);
|
|
logfmt(" %i, // nconst\n", pr->nconst);
|
|
logfmt(" %i, // nproto\n", pr->nproto);
|
|
logfmt(" be_local_const_str(%s_str_source), // source\n", func_name);
|
|
//
|
|
logfmt("#if BE_DEBUG_RUNTIME_INFO /* debug information */\n");
|
|
logfmt(" NULL, // lineinfo\n");
|
|
logfmt(" 0, // nlineinfo\n");
|
|
logfmt("#endif\n");
|
|
logfmt("#if BE_DEBUG_VAR_INFO\n");
|
|
logfmt(" NULL, // varinfo\n");
|
|
logfmt(" 0, // nvarinfo\n");
|
|
logfmt("#endif\n");
|
|
logfmt("};\n\n");
|
|
|
|
// closure
|
|
logfmt("static const bclosure %s_closure = {\n", func_name);
|
|
// bcommon_header
|
|
logfmt(" NULL, // bgcobject *next\n");
|
|
logfmt(" %i, // type\n", cl->type);
|
|
logfmt(" GC_CONST, // marked\n");
|
|
//
|
|
logfmt(" %i, // nupvals\n", cl->nupvals);
|
|
logfmt(" NULL, // bgcobject *gray\n");
|
|
logfmt(" (bproto*) &%s_proto, // proto\n", func_name);
|
|
logfmt(" { NULL } // upvals\n");
|
|
logfmt("};\n\n");
|
|
|
|
logfmt("/*******************************************************************/\n\n");
|
|
}
|
|
|
|
#define be_builtin_count(vm) \
|
|
be_vector_count(&(vm)->gbldesc.builtin.vlist)
|
|
|
|
static int m_dump(bvm *vm)
|
|
{
|
|
if (be_top(vm) >= 1) {
|
|
bvalue *v = be_indexof(vm, 1);
|
|
if (var_isclosure(v)) {
|
|
m_solidify_closure(vm, var_toobj(v), be_builtin_count(vm));
|
|
}
|
|
}
|
|
be_return_nil(vm);
|
|
}
|
|
|
|
#if !BE_USE_PRECOMPILED_OBJECT
|
|
be_native_module_attr_table(solidify) {
|
|
be_native_module_function("dump", m_dump),
|
|
};
|
|
|
|
be_define_native_module(solidify, NULL);
|
|
#else
|
|
/* @const_object_info_begin
|
|
module solidify (scope: global, depend: BE_USE_SOLIDIFY_MODULE) {
|
|
dump, func(m_dump)
|
|
}
|
|
@const_object_info_end */
|
|
#include "../generate/be_fixed_solidify.h"
|
|
#endif
|
|
|
|
#endif /* BE_USE_SOLIFIDY_MODULE */
|