✨ split opcode to nasal_opcode.h
This commit is contained in:
parent
4e17de909a
commit
3852ce23a3
3
makefile
3
makefile
|
@ -5,6 +5,7 @@ SRC=\
|
||||||
nasal_ast.h\
|
nasal_ast.h\
|
||||||
nasal_err.h\
|
nasal_err.h\
|
||||||
nasal_builtin.h\
|
nasal_builtin.h\
|
||||||
|
nasal_opcode.h\
|
||||||
nasal_opt.h\
|
nasal_opt.h\
|
||||||
nasal_codegen.h\
|
nasal_codegen.h\
|
||||||
nasal_gc.h\
|
nasal_gc.h\
|
||||||
|
@ -65,9 +66,7 @@ test:nasal
|
||||||
@ ./nasal -e test/qrcode.nas
|
@ ./nasal -e test/qrcode.nas
|
||||||
@ ./nasal -t -d test/quick_sort.nas
|
@ ./nasal -t -d test/quick_sort.nas
|
||||||
@ ./nasal -e test/scalar.nas hello world
|
@ ./nasal -e test/scalar.nas hello world
|
||||||
@ ./nasal -t test/snake.nas --skip
|
|
||||||
@ ./nasal -e test/trait.nas
|
@ ./nasal -e test/trait.nas
|
||||||
@ ./nasal -t test/tetris.nas --skip
|
|
||||||
@ ./nasal -t -d test/turingmachine.nas
|
@ ./nasal -t -d test/turingmachine.nas
|
||||||
@ ./nasal -d test/wavecollapse.nas
|
@ ./nasal -d test/wavecollapse.nas
|
||||||
@ ./nasal test/word_collector.nas test/md5compare.nas
|
@ ./nasal test/word_collector.nas test/md5compare.nas
|
||||||
|
|
204
nasal_codegen.h
204
nasal_codegen.h
|
@ -2,212 +2,13 @@
|
||||||
|
|
||||||
#include "nasal_err.h"
|
#include "nasal_err.h"
|
||||||
#include "nasal_builtin.h"
|
#include "nasal_builtin.h"
|
||||||
|
#include "nasal_opcode.h"
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
enum op_code_type:u8 {
|
|
||||||
op_exit, // stop the virtual machine
|
|
||||||
op_intg, // global scope size, set stack top
|
|
||||||
op_intl, // local scope size
|
|
||||||
op_loadg, // load global value
|
|
||||||
op_loadl, // load local value
|
|
||||||
op_loadu, // load upvalue
|
|
||||||
op_pnum, // push constant number to the stack
|
|
||||||
op_pnil, // push constant nil to the stack
|
|
||||||
op_pstr, // push constant string to the stack
|
|
||||||
op_newv, // push new vector with initial values from stack
|
|
||||||
op_newh, // push new hash to the stack
|
|
||||||
op_newf, // push new function to the stack
|
|
||||||
op_happ, // hash append
|
|
||||||
op_para, // normal parameter
|
|
||||||
op_deft, // default parameter
|
|
||||||
op_dyn, // dynamic parameter
|
|
||||||
op_lnot, // ! logical negation
|
|
||||||
op_usub, // - negation
|
|
||||||
op_bnot, // ~ bitwise not static_cast<i32>
|
|
||||||
op_btor, // | bitwise or
|
|
||||||
op_btxor, // ^ bitwise xor
|
|
||||||
op_btand, // & bitwise and
|
|
||||||
op_add, // +
|
|
||||||
op_sub, // -
|
|
||||||
op_mul, // *
|
|
||||||
op_div, // /
|
|
||||||
op_lnk, // ~
|
|
||||||
op_addc, // + const
|
|
||||||
op_subc, // - const
|
|
||||||
op_mulc, // * const
|
|
||||||
op_divc, // / const
|
|
||||||
op_lnkc, // ~ const
|
|
||||||
op_addeq, // += maybe pop stack top
|
|
||||||
op_subeq, // -= maybe pop stack top
|
|
||||||
op_muleq, // *= maybe pop stack top
|
|
||||||
op_diveq, // /= maybe pop stack top
|
|
||||||
op_lnkeq, // ~= maybe pop stack top
|
|
||||||
op_btandeq,// &= maybe pop stack top
|
|
||||||
op_btoreq, // |= maybe pop stack top
|
|
||||||
op_btxoreq,// ^= maybe pop stack top
|
|
||||||
op_addeqc, // += const don't pop stack top
|
|
||||||
op_subeqc, // -= const don't pop stack top
|
|
||||||
op_muleqc, // *= const don't pop stack top
|
|
||||||
op_diveqc, // /= const don't pop stack top
|
|
||||||
op_lnkeqc, // ~= const don't pop stack top
|
|
||||||
op_addecp, // += const and pop stack top
|
|
||||||
op_subecp, // -= const and pop stack top
|
|
||||||
op_mulecp, // *= const and pop stack top
|
|
||||||
op_divecp, // /= const and pop stack top
|
|
||||||
op_lnkecp, // ~= concat const string and pop stack top
|
|
||||||
op_meq, // = maybe pop stack top
|
|
||||||
op_eq, // ==
|
|
||||||
op_neq, // !=
|
|
||||||
op_less, // <
|
|
||||||
op_leq, // <=
|
|
||||||
op_grt, // >
|
|
||||||
op_geq, // >=
|
|
||||||
op_lessc, // < const
|
|
||||||
op_leqc, // <= const
|
|
||||||
op_grtc, // > const
|
|
||||||
op_geqc, // >= const
|
|
||||||
op_pop, // pop a value out of stack top
|
|
||||||
op_jmp, // jump absolute address with no condition
|
|
||||||
op_jt, // used in operator and/or,jmp when condition is true and DO NOT POP
|
|
||||||
op_jf, // used in conditional/loop,jmp when condition is false and POP STACK
|
|
||||||
op_cnt, // add counter for forindex/foreach
|
|
||||||
op_findex, // index counter on the top of forindex_stack plus 1
|
|
||||||
op_feach, // index counter on the top of forindex_stack plus 1 and get the value in vector
|
|
||||||
op_callg, // get value in global scope
|
|
||||||
op_calll, // get value in local scope
|
|
||||||
op_upval, // get upvalue in closure, high 16 as the index of upval, low 16 as the index of local
|
|
||||||
op_callv, // call vec[index]
|
|
||||||
op_callvi, // call vec[immediate] (used in multi-assign/multi-define)
|
|
||||||
op_callh, // call hash.label
|
|
||||||
op_callfv, // call function(vector as parameters)
|
|
||||||
op_callfh, // call function(hash as parameters)
|
|
||||||
op_callb, // call builtin-function
|
|
||||||
op_slcbeg, // begin of slice like: vec[1,2,3:6,0,-1]
|
|
||||||
op_slcend, // end of slice
|
|
||||||
op_slc, // slice like vec[1]
|
|
||||||
op_slc2, // slice like vec[nil:10]
|
|
||||||
op_mcallg, // get memory space of value in global scope
|
|
||||||
op_mcalll, // get memory space of value in local scope
|
|
||||||
op_mupval, // get memory space of value in closure
|
|
||||||
op_mcallv, // get memory space of vec[index]
|
|
||||||
op_mcallh, // get memory space of hash.label
|
|
||||||
op_ret // return
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* opname[]={
|
|
||||||
"exit ","intg ","intl ","loadg ",
|
|
||||||
"loadl ","loadu ","pnum ","pnil ",
|
|
||||||
"pstr ","newv ","newh ","newf ",
|
|
||||||
"happ ","para ","def ","dyn ",
|
|
||||||
"lnot ","usub ","bnot ","btor ",
|
|
||||||
"btxor ","btand ","add ","sub ",
|
|
||||||
"mult ","div ","lnk ","addc ",
|
|
||||||
"subc ","multc ","divc ","lnkc ",
|
|
||||||
"addeq ","subeq ","muleq ","diveq ",
|
|
||||||
"lnkeq ","bandeq","boreq ","bxoreq",
|
|
||||||
"addeqc","subeqc","muleqc","diveqc",
|
|
||||||
"lnkeqc","addecp","subecp","mulecp",
|
|
||||||
"divecp","lnkecp","meq ","eq ",
|
|
||||||
"neq ","less ","leq ","grt ",
|
|
||||||
"geq ","lessc ","leqc ","grtc ",
|
|
||||||
"geqc ","pop ","jmp ","jt ",
|
|
||||||
"jf ","cnt ","findx ","feach ",
|
|
||||||
"callg ","calll ","upval ","callv ",
|
|
||||||
"callvi","callh ","callfv","callfh",
|
|
||||||
"callb ","slcbeg","slcend","slc ",
|
|
||||||
"slc2 ","mcallg","mcalll","mupval",
|
|
||||||
"mcallv","mcallh","ret "
|
|
||||||
};
|
|
||||||
|
|
||||||
struct opcode {
|
|
||||||
u8 op; // opcode
|
|
||||||
u16 fidx; // source code file index
|
|
||||||
u32 num; // immediate num
|
|
||||||
u32 line; // location line of source code
|
|
||||||
opcode(u8 o=op_exit,u16 f=0,u32 n=0,u32 l=0):
|
|
||||||
op(o),fidx(f),num(n),line(l) {}
|
|
||||||
opcode& operator=(const opcode& tmp) = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class codestream {
|
|
||||||
private:
|
|
||||||
opcode code;
|
|
||||||
const u32 index;
|
|
||||||
const f64* nums;
|
|
||||||
const string* strs;
|
|
||||||
const string* files;
|
|
||||||
public:
|
|
||||||
codestream(const opcode& c,const u32 i,const f64* n,const string* s,const string* f=nullptr):
|
|
||||||
code(c.op,c.fidx,c.num,c.line),index(i),nums(n),strs(s),files(f) {}
|
|
||||||
friend std::ostream& operator<<(std::ostream& out,const codestream& ins) {
|
|
||||||
u8 op=ins.code.op;
|
|
||||||
u32 num=ins.code.num;
|
|
||||||
out<<std::hex<<"0x"
|
|
||||||
<<std::setw(6)<<std::setfill('0')<<ins.index<<" "
|
|
||||||
<<std::setw(2)<<std::setfill('0')<<(u32)op<<" "
|
|
||||||
<<std::setw(2)<<std::setfill('0')<<((num>>16)&0xff)<<" "
|
|
||||||
<<std::setw(2)<<std::setfill('0')<<((num>>8)&0xff)<<" "
|
|
||||||
<<std::setw(2)<<std::setfill('0')<<(num&0xff)<<" "
|
|
||||||
<<opname[op]<<" "<<std::dec;
|
|
||||||
switch(op) {
|
|
||||||
case op_addeq: case op_subeq: case op_muleq: case op_diveq:
|
|
||||||
case op_lnkeq: case op_meq: case op_btandeq: case op_btoreq:
|
|
||||||
case op_btxoreq:
|
|
||||||
out<<std::hex<<"0x"<<num<<std::dec
|
|
||||||
<<" sp-"<<num;break;
|
|
||||||
case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc:
|
|
||||||
out<<std::hex<<"0x"<<num<<std::dec
|
|
||||||
<<" ("<<ins.nums[num]<<")";break;
|
|
||||||
case op_lnkeqc:
|
|
||||||
out<<std::hex<<"0x"<<num<<std::dec<<" (\""
|
|
||||||
<<rawstr(ins.strs[num],16)<<"\")";break;
|
|
||||||
case op_addecp:case op_subecp:case op_mulecp:case op_divecp:
|
|
||||||
out<<std::hex<<"0x"<<num<<std::dec
|
|
||||||
<<" ("<<ins.nums[num]<<") sp-1";break;
|
|
||||||
case op_lnkecp:
|
|
||||||
out<<std::hex<<"0x"<<num<<std::dec<<" (\""
|
|
||||||
<<rawstr(ins.strs[num],16)<<"\") sp-1";break;
|
|
||||||
case op_addc: case op_subc: case op_mulc: case op_divc:
|
|
||||||
case op_lessc: case op_leqc: case op_grtc: case op_geqc:
|
|
||||||
case op_pnum:
|
|
||||||
out<<std::hex<<"0x"<<num<<std::dec<<" ("
|
|
||||||
<<ins.nums[num]<<")";break;
|
|
||||||
case op_callvi:case op_newv: case op_callfv:
|
|
||||||
case op_intg: case op_intl:
|
|
||||||
case op_findex:case op_feach:
|
|
||||||
case op_newf: case op_jmp: case op_jt: case op_jf:
|
|
||||||
case op_callg: case op_mcallg: case op_loadg:
|
|
||||||
case op_calll: case op_mcalll: case op_loadl:
|
|
||||||
out<<std::hex<<"0x"<<num<<std::dec;break;
|
|
||||||
case op_callb:
|
|
||||||
out<<std::hex<<"0x"<<num<<" <"<<builtin[num].name
|
|
||||||
<<"@0x"<<(u64)builtin[num].func<<std::dec<<">";break;
|
|
||||||
case op_upval: case op_mupval: case op_loadu:
|
|
||||||
out<<std::hex<<"0x"<<((num>>16)&0xffff)
|
|
||||||
<<"[0x"<<(num&0xffff)<<"]"<<std::dec;break;
|
|
||||||
case op_happ: case op_pstr:
|
|
||||||
case op_lnkc:
|
|
||||||
case op_callh: case op_mcallh:
|
|
||||||
case op_para: case op_deft: case op_dyn:
|
|
||||||
out<<std::hex<<"0x"<<num<<std::dec
|
|
||||||
<<" (\""<<rawstr(ins.strs[num],16)<<"\")";break;
|
|
||||||
default:
|
|
||||||
if (ins.files) {
|
|
||||||
out<<std::hex<<"0x"<<num<<std::dec;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ins.files) {
|
|
||||||
out<<" ("<<ins.files[ins.code.fidx]<<":"<<ins.code.line<<")";
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class codegen {
|
class codegen {
|
||||||
private:
|
private:
|
||||||
u16 fileindex;
|
u16 fileindex;
|
||||||
|
@ -1245,6 +1046,7 @@ void codegen::print() {
|
||||||
|
|
||||||
// print code
|
// print code
|
||||||
std::cout<<"\n";
|
std::cout<<"\n";
|
||||||
|
codestream::set(num_res.data(),str_res.data());
|
||||||
for(u32 i=0;i<code.size();++i) {
|
for(u32 i=0;i<code.size();++i) {
|
||||||
// print opcode index, opcode name, opcode immediate number
|
// print opcode index, opcode name, opcode immediate number
|
||||||
const opcode& c=code[i];
|
const opcode& c=code[i];
|
||||||
|
@ -1271,6 +1073,6 @@ void codegen::print() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// output bytecode
|
// output bytecode
|
||||||
std::cout<<" "<<codestream(c,i,num_res.data(),str_res.data())<<"\n";
|
std::cout<<" "<<codestream(c,i)<<"\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "nasal_import.h"
|
#include "nasal_import.h"
|
||||||
#include "nasal_err.h"
|
#include "nasal_err.h"
|
||||||
|
#include "nasal_opcode.h"
|
||||||
#include "nasal_vm.h"
|
#include "nasal_vm.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -115,10 +116,11 @@ void debugger::stepinfo() {
|
||||||
std::cout<<"next bytecode:\n";
|
std::cout<<"next bytecode:\n";
|
||||||
begin=(pc>>3)==0?0:((pc>>3)<<3);
|
begin=(pc>>3)==0?0:((pc>>3)<<3);
|
||||||
end=(1+(pc>>3))<<3;
|
end=(1+(pc>>3))<<3;
|
||||||
|
codestream::set(cnum,cstr,files);
|
||||||
for(u32 i=begin;i<end && bytecode[i].op!=op_exit;++i) {
|
for(u32 i=begin;i<end && bytecode[i].op!=op_exit;++i) {
|
||||||
std::cout
|
std::cout
|
||||||
<<(i==pc?back_white:reset)<<(i==pc?"--> ":" ")
|
<<(i==pc?back_white:reset)<<(i==pc?"--> ":" ")
|
||||||
<<codestream(bytecode[i],i,cnum,cstr,files)
|
<<codestream(bytecode[i],i)
|
||||||
<<reset<<"\n";
|
<<reset<<"\n";
|
||||||
}
|
}
|
||||||
stackinfo(10);
|
stackinfo(10);
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "nasal.h"
|
||||||
|
#include "nasal_builtin.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
enum op_code_type:u8 {
|
||||||
|
op_exit, // stop the virtual machine
|
||||||
|
op_intg, // global scope size, set stack top
|
||||||
|
op_intl, // local scope size
|
||||||
|
op_loadg, // load global value
|
||||||
|
op_loadl, // load local value
|
||||||
|
op_loadu, // load upvalue
|
||||||
|
op_pnum, // push constant number to the stack
|
||||||
|
op_pnil, // push constant nil to the stack
|
||||||
|
op_pstr, // push constant string to the stack
|
||||||
|
op_newv, // push new vector with initial values from stack
|
||||||
|
op_newh, // push new hash to the stack
|
||||||
|
op_newf, // push new function to the stack
|
||||||
|
op_happ, // hash append
|
||||||
|
op_para, // normal parameter
|
||||||
|
op_deft, // default parameter
|
||||||
|
op_dyn, // dynamic parameter
|
||||||
|
op_lnot, // ! logical negation
|
||||||
|
op_usub, // - negation
|
||||||
|
op_bnot, // ~ bitwise not static_cast<i32>
|
||||||
|
op_btor, // | bitwise or
|
||||||
|
op_btxor, // ^ bitwise xor
|
||||||
|
op_btand, // & bitwise and
|
||||||
|
op_add, // +
|
||||||
|
op_sub, // -
|
||||||
|
op_mul, // *
|
||||||
|
op_div, // /
|
||||||
|
op_lnk, // ~
|
||||||
|
op_addc, // + const
|
||||||
|
op_subc, // - const
|
||||||
|
op_mulc, // * const
|
||||||
|
op_divc, // / const
|
||||||
|
op_lnkc, // ~ const
|
||||||
|
op_addeq, // += maybe pop stack top
|
||||||
|
op_subeq, // -= maybe pop stack top
|
||||||
|
op_muleq, // *= maybe pop stack top
|
||||||
|
op_diveq, // /= maybe pop stack top
|
||||||
|
op_lnkeq, // ~= maybe pop stack top
|
||||||
|
op_btandeq,// &= maybe pop stack top
|
||||||
|
op_btoreq, // |= maybe pop stack top
|
||||||
|
op_btxoreq,// ^= maybe pop stack top
|
||||||
|
op_addeqc, // += const don't pop stack top
|
||||||
|
op_subeqc, // -= const don't pop stack top
|
||||||
|
op_muleqc, // *= const don't pop stack top
|
||||||
|
op_diveqc, // /= const don't pop stack top
|
||||||
|
op_lnkeqc, // ~= const don't pop stack top
|
||||||
|
op_addecp, // += const and pop stack top
|
||||||
|
op_subecp, // -= const and pop stack top
|
||||||
|
op_mulecp, // *= const and pop stack top
|
||||||
|
op_divecp, // /= const and pop stack top
|
||||||
|
op_lnkecp, // ~= concat const string and pop stack top
|
||||||
|
op_meq, // = maybe pop stack top
|
||||||
|
op_eq, // ==
|
||||||
|
op_neq, // !=
|
||||||
|
op_less, // <
|
||||||
|
op_leq, // <=
|
||||||
|
op_grt, // >
|
||||||
|
op_geq, // >=
|
||||||
|
op_lessc, // < const
|
||||||
|
op_leqc, // <= const
|
||||||
|
op_grtc, // > const
|
||||||
|
op_geqc, // >= const
|
||||||
|
op_pop, // pop a value out of stack top
|
||||||
|
op_jmp, // jump absolute address with no condition
|
||||||
|
op_jt, // used in operator and/or,jmp when condition is true and DO NOT POP
|
||||||
|
op_jf, // used in conditional/loop,jmp when condition is false and POP STACK
|
||||||
|
op_cnt, // add counter for forindex/foreach
|
||||||
|
op_findex, // index counter on the top of forindex_stack plus 1
|
||||||
|
op_feach, // index counter on the top of forindex_stack plus 1 and get the value in vector
|
||||||
|
op_callg, // get value in global scope
|
||||||
|
op_calll, // get value in local scope
|
||||||
|
op_upval, // get upvalue in closure, high 16 as the index of upval, low 16 as the index of local
|
||||||
|
op_callv, // call vec[index]
|
||||||
|
op_callvi, // call vec[immediate] (used in multi-assign/multi-define)
|
||||||
|
op_callh, // call hash.label
|
||||||
|
op_callfv, // call function(vector as parameters)
|
||||||
|
op_callfh, // call function(hash as parameters)
|
||||||
|
op_callb, // call builtin-function
|
||||||
|
op_slcbeg, // begin of slice like: vec[1,2,3:6,0,-1]
|
||||||
|
op_slcend, // end of slice
|
||||||
|
op_slc, // slice like vec[1]
|
||||||
|
op_slc2, // slice like vec[nil:10]
|
||||||
|
op_mcallg, // get memory space of value in global scope
|
||||||
|
op_mcalll, // get memory space of value in local scope
|
||||||
|
op_mupval, // get memory space of value in closure
|
||||||
|
op_mcallv, // get memory space of vec[index]
|
||||||
|
op_mcallh, // get memory space of hash.label
|
||||||
|
op_ret // return
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* opname[]={
|
||||||
|
"exit ","intg ","intl ","loadg ",
|
||||||
|
"loadl ","loadu ","pnum ","pnil ",
|
||||||
|
"pstr ","newv ","newh ","newf ",
|
||||||
|
"happ ","para ","def ","dyn ",
|
||||||
|
"lnot ","usub ","bnot ","btor ",
|
||||||
|
"btxor ","btand ","add ","sub ",
|
||||||
|
"mult ","div ","lnk ","addc ",
|
||||||
|
"subc ","multc ","divc ","lnkc ",
|
||||||
|
"addeq ","subeq ","muleq ","diveq ",
|
||||||
|
"lnkeq ","bandeq","boreq ","bxoreq",
|
||||||
|
"addeqc","subeqc","muleqc","diveqc",
|
||||||
|
"lnkeqc","addecp","subecp","mulecp",
|
||||||
|
"divecp","lnkecp","meq ","eq ",
|
||||||
|
"neq ","less ","leq ","grt ",
|
||||||
|
"geq ","lessc ","leqc ","grtc ",
|
||||||
|
"geqc ","pop ","jmp ","jt ",
|
||||||
|
"jf ","cnt ","findx ","feach ",
|
||||||
|
"callg ","calll ","upval ","callv ",
|
||||||
|
"callvi","callh ","callfv","callfh",
|
||||||
|
"callb ","slcbeg","slcend","slc ",
|
||||||
|
"slc2 ","mcallg","mcalll","mupval",
|
||||||
|
"mcallv","mcallh","ret "
|
||||||
|
};
|
||||||
|
|
||||||
|
struct opcode {
|
||||||
|
u8 op; // opcode
|
||||||
|
u16 fidx; // source code file index
|
||||||
|
u32 num; // immediate num
|
||||||
|
u32 line; // location line of source code
|
||||||
|
opcode() = default;
|
||||||
|
opcode(const opcode&) = default;
|
||||||
|
opcode& operator=(const opcode&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class codestream {
|
||||||
|
private:
|
||||||
|
opcode code;
|
||||||
|
const u32 index;
|
||||||
|
static const f64* nums;
|
||||||
|
static const string* strs;
|
||||||
|
static const string* files;
|
||||||
|
public:
|
||||||
|
codestream(const opcode& c,const u32 i):code(c),index(i) {}
|
||||||
|
static void set(const f64*,const string*,const string*);
|
||||||
|
void dump(std::ostream&) const;
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& out,const codestream& ins) {
|
||||||
|
ins.dump(out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const f64* codestream::nums=nullptr;
|
||||||
|
const string* codestream::strs=nullptr;
|
||||||
|
const string* codestream::files=nullptr;
|
||||||
|
|
||||||
|
void codestream::set(const f64* numbuff,const string* strbuff,const string* filelist=nullptr) {
|
||||||
|
nums=numbuff;
|
||||||
|
strs=strbuff;
|
||||||
|
files=filelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void codestream::dump(std::ostream& out) const {
|
||||||
|
auto op=code.op;
|
||||||
|
auto num=code.num;
|
||||||
|
out<<std::hex<<"0x"
|
||||||
|
<<std::setw(6)<<std::setfill('0')<<index<<" "
|
||||||
|
<<std::setw(2)<<std::setfill('0')<<(u32)op<<" "
|
||||||
|
<<std::setw(2)<<std::setfill('0')<<((num>>16)&0xff)<<" "
|
||||||
|
<<std::setw(2)<<std::setfill('0')<<((num>>8)&0xff)<<" "
|
||||||
|
<<std::setw(2)<<std::setfill('0')<<(num&0xff)<<" "
|
||||||
|
<<opname[op]<<" "<<std::dec;
|
||||||
|
switch(op) {
|
||||||
|
case op_addeq: case op_subeq: case op_muleq: case op_diveq:
|
||||||
|
case op_lnkeq: case op_meq: case op_btandeq: case op_btoreq:
|
||||||
|
case op_btxoreq:
|
||||||
|
out<<std::hex<<"0x"<<num<<std::dec
|
||||||
|
<<" sp-"<<num;break;
|
||||||
|
case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc:
|
||||||
|
out<<std::hex<<"0x"<<num<<std::dec
|
||||||
|
<<" ("<<nums[num]<<")";break;
|
||||||
|
case op_lnkeqc:
|
||||||
|
out<<std::hex<<"0x"<<num<<std::dec<<" (\""
|
||||||
|
<<rawstr(strs[num],16)<<"\")";break;
|
||||||
|
case op_addecp:case op_subecp:case op_mulecp:case op_divecp:
|
||||||
|
out<<std::hex<<"0x"<<num<<std::dec
|
||||||
|
<<" ("<<nums[num]<<") sp-1";break;
|
||||||
|
case op_lnkecp:
|
||||||
|
out<<std::hex<<"0x"<<num<<std::dec<<" (\""
|
||||||
|
<<rawstr(strs[num],16)<<"\") sp-1";break;
|
||||||
|
case op_addc: case op_subc: case op_mulc: case op_divc:
|
||||||
|
case op_lessc: case op_leqc: case op_grtc: case op_geqc:
|
||||||
|
case op_pnum:
|
||||||
|
out<<std::hex<<"0x"<<num<<std::dec<<" ("
|
||||||
|
<<nums[num]<<")";break;
|
||||||
|
case op_callvi:case op_newv: case op_callfv:
|
||||||
|
case op_intg: case op_intl:
|
||||||
|
case op_findex:case op_feach:
|
||||||
|
case op_newf: case op_jmp: case op_jt: case op_jf:
|
||||||
|
case op_callg: case op_mcallg: case op_loadg:
|
||||||
|
case op_calll: case op_mcalll: case op_loadl:
|
||||||
|
out<<std::hex<<"0x"<<num<<std::dec;break;
|
||||||
|
case op_callb:
|
||||||
|
out<<std::hex<<"0x"<<num<<" <"<<builtin[num].name
|
||||||
|
<<"@0x"<<(u64)builtin[num].func<<std::dec<<">";break;
|
||||||
|
case op_upval: case op_mupval: case op_loadu:
|
||||||
|
out<<std::hex<<"0x"<<((num>>16)&0xffff)
|
||||||
|
<<"[0x"<<(num&0xffff)<<"]"<<std::dec;break;
|
||||||
|
case op_happ: case op_pstr:
|
||||||
|
case op_lnkc:
|
||||||
|
case op_callh: case op_mcallh:
|
||||||
|
case op_para: case op_deft: case op_dyn:
|
||||||
|
out<<std::hex<<"0x"<<num<<std::dec
|
||||||
|
<<" (\""<<rawstr(strs[num],16)<<"\")";break;
|
||||||
|
default:
|
||||||
|
if (files) {
|
||||||
|
out<<std::hex<<"0x"<<num<<std::dec;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (files) {
|
||||||
|
out<<" ("<<files[code.fidx]<<":"<<code.line<<")";
|
||||||
|
}
|
||||||
|
}
|
|
@ -235,6 +235,7 @@ void vm::traceback() {
|
||||||
}
|
}
|
||||||
ret.push(pc); // store the position program crashed
|
ret.push(pc); // store the position program crashed
|
||||||
std::clog<<"trace back ("<<(ngc.stack==stack?"main":"coroutine")<<")\n";
|
std::clog<<"trace back ("<<(ngc.stack==stack?"main":"coroutine")<<")\n";
|
||||||
|
codestream::set(cnum,cstr,files);
|
||||||
for(u32 p=0,same=0,prev=0xffffffff;!ret.empty();prev=p,ret.pop()) {
|
for(u32 p=0,same=0,prev=0xffffffff;!ret.empty();prev=p,ret.pop()) {
|
||||||
if ((p=ret.top())==prev) {
|
if ((p=ret.top())==prev) {
|
||||||
++same;
|
++same;
|
||||||
|
@ -246,7 +247,7 @@ void vm::traceback() {
|
||||||
<<prev<<std::dec<<" "<<same<<" same call(s)\n";
|
<<prev<<std::dec<<" "<<same<<" same call(s)\n";
|
||||||
}
|
}
|
||||||
same=0;
|
same=0;
|
||||||
std::clog<<" "<<codestream(bytecode[p],p,cnum,cstr,files)<<"\n";
|
std::clog<<" "<<codestream(bytecode[p],p)<<"\n";
|
||||||
}
|
}
|
||||||
// the first called place has no same calls
|
// the first called place has no same calls
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue