bytecode.c revision 5dfecf96
15dfecf96Smrg/* 25dfecf96Smrg * Copyright (c) 2002 by The XFree86 Project, Inc. 35dfecf96Smrg * 45dfecf96Smrg * Permission is hereby granted, free of charge, to any person obtaining a 55dfecf96Smrg * copy of this software and associated documentation files (the "Software"), 65dfecf96Smrg * to deal in the Software without restriction, including without limitation 75dfecf96Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 85dfecf96Smrg * and/or sell copies of the Software, and to permit persons to whom the 95dfecf96Smrg * Software is furnished to do so, subject to the following conditions: 105dfecf96Smrg * 115dfecf96Smrg * The above copyright notice and this permission notice shall be included in 125dfecf96Smrg * all copies or substantial portions of the Software. 135dfecf96Smrg * 145dfecf96Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 155dfecf96Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 165dfecf96Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 175dfecf96Smrg * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 185dfecf96Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 195dfecf96Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 205dfecf96Smrg * SOFTWARE. 215dfecf96Smrg * 225dfecf96Smrg * Except as contained in this notice, the name of the XFree86 Project shall 235dfecf96Smrg * not be used in advertising or otherwise to promote the sale, use or other 245dfecf96Smrg * dealings in this Software without prior written authorization from the 255dfecf96Smrg * XFree86 Project. 265dfecf96Smrg * 275dfecf96Smrg * Author: Paulo César Pereira de Andrade 285dfecf96Smrg */ 295dfecf96Smrg 305dfecf96Smrg/* $XFree86: xc/programs/xedit/lisp/bytecode.c,v 1.17 2003/05/27 22:27:01 tsi Exp $ */ 315dfecf96Smrg 325dfecf96Smrg 335dfecf96Smrg/* 345dfecf96Smrgsomethings TODO: 355dfecf96Smrg 365dfecf96Smrg o Write code for allowing storing the bytecode on disk. Basically 375dfecf96Smrg write a section of the bytecode with the package name of the symbol 385dfecf96Smrg pointers, and after that, the symbols used. At load time just put 395dfecf96Smrg the pointers in the bytecode. Constants can be stored as the string 405dfecf96Smrg representation. Probably just storing the gc protected code as a 415dfecf96Smrg string is enough to rebuild it. 425dfecf96Smrg 435dfecf96Smrg o Write code to store tags of BLOCK/CATCH and setjump buffer stacks, 445dfecf96Smrg and, only keep track of this if non byte-compiled code is called, 455dfecf96Smrg as after byte-compilation RETURN and THROW are just jumps. 465dfecf96Smrg 475dfecf96Smrg o Remove not reliable "optmization code" code from Com_XXX functions 485dfecf96Smrg and do it later, removing dead code, tests with a constant argument, 495dfecf96Smrg etc, in the "link time". Frequently joining sequential opcodes to a 505dfecf96Smrg compound version. 515dfecf96Smrg 525dfecf96Smrg o Write an optimizer to do code transformation. 535dfecf96Smrg 545dfecf96Smrg o Write code to know when variables can be changed in place, this 555dfecf96Smrg can save a huge time in loop counters. 565dfecf96Smrg 575dfecf96Smrg o Write code for fast garbage collection of objects that can be 585dfecf96Smrg safely collected. 595dfecf96Smrg 605dfecf96Smrg o Cleanup of interpreted code. Having bytecode mean that the interpreter 615dfecf96Smrg now is better having a clean and small code. If speed is important, 625dfecf96Smrg it should be byte compiled. 635dfecf96Smrg 645dfecf96Smrg o Limit the stacks length. So that instead of using an index, use the 655dfecf96Smrg pointer where an object value should be read/stored as the stack address 665dfecf96Smrg would not change during the program execution. 675dfecf96Smrg 685dfecf96Smrg o Optimize jump to jump. Common in code like: 695dfecf96Smrg (IF test 705dfecf96Smrg (GO somewhere) 715dfecf96Smrg (GO elsewhere) 725dfecf96Smrg ) 735dfecf96Smrg (GO there) 745dfecf96Smrg that generates a bytecode like: 755dfecf96Smrg <code to evaluate test> 765dfecf96Smrg JUMPNIL :NIL-RESULT 775dfecf96Smrg :T-RESULT 785dfecf96Smrg JUMP :SOMEWHERE 795dfecf96Smrg JUMP :END-OF-IF ;; <- this is not required, or even 805dfecf96Smrg :NIL-RESULT ;; better, notice the jump after 815dfecf96Smrg JUMP :ELSEWHERE ;; the if and transform it into 825dfecf96Smrg :END-OF-IF ;; a JUMP :THERE (assuming there 835dfecf96Smrg JUMP :THERE ;; (was no jump in the T code). 845dfecf96Smrg 855dfecf96Smrg o Optimize variables that are known to not change it's value, i.e. pseudo 865dfecf96Smrg constants. Loading the value of a constant should be faster than loading 875dfecf96Smrg the current value of a variable; the constant table could fit in the 885dfecf96Smrg processor cache line and needs less calculation to find the object address. 895dfecf96Smrg 905dfecf96Smrg o Fix some known problems, like when calling return or return-from while 915dfecf96Smrg building the argument list to a builtin function, or inline of recursive 925dfecf96Smrg functions. 935dfecf96Smrg */ 945dfecf96Smrg 955dfecf96Smrg 965dfecf96Smrg#include "lisp/bytecode.h" 975dfecf96Smrg#include "lisp/write.h" 985dfecf96Smrg 995dfecf96Smrg#define SYMBOL_KEYWORD -1 /* A keyword, load as constant */ 1005dfecf96Smrg#define SYMBOL_CONSTANT -2 /* Defined as constant at compile time */ 1015dfecf96Smrg#define SYMBOL_UNBOUND -3 /* Not a local variable */ 1025dfecf96Smrg 1035dfecf96Smrg#define NEW_TREE(type) CompileNewTree(com, type) 1045dfecf96Smrg 1055dfecf96Smrg/* If in tagbody, ignore anything that is not code */ 1065dfecf96Smrg#define IN_TAGBODY() (com->block->type == LispBlockBody && \ 1075dfecf96Smrg com->level == com->tagbody) 1085dfecf96Smrg#define FORM_ENTER() ++com->level 1095dfecf96Smrg#define FORM_LEAVE() --com->level 1105dfecf96Smrg 1115dfecf96Smrg#define COMPILE_FAILURE(message) \ 1125dfecf96Smrg LispMessage("COMPILE: %s", message); \ 1135dfecf96Smrg longjmp(com->jmp, 1) 1145dfecf96Smrg 1155dfecf96Smrg/* 1165dfecf96Smrg * Types 1175dfecf96Smrg */ 1185dfecf96Smrgtypedef struct _CodeTree CodeTree; 1195dfecf96Smrgtypedef struct _CodeBlock CodeBlock; 1205dfecf96Smrg 1215dfecf96Smrgtypedef enum { 1225dfecf96Smrg CodeTreeBytecode, 1235dfecf96Smrg CodeTreeLabel, 1245dfecf96Smrg CodeTreeGo, 1255dfecf96Smrg CodeTreeJump, 1265dfecf96Smrg CodeTreeJumpIf, 1275dfecf96Smrg CodeTreeCond, 1285dfecf96Smrg CodeTreeBlock, 1295dfecf96Smrg CodeTreeReturn 1305dfecf96Smrg} CodeTreeType; 1315dfecf96Smrg 1325dfecf96Smrgstruct _CodeTree { 1335dfecf96Smrg CodeTreeType type; 1345dfecf96Smrg 1355dfecf96Smrg /* Resolved when linking, may be adjusted while optimizing */ 1365dfecf96Smrg long offset; 1375dfecf96Smrg 1385dfecf96Smrg LispByteOpcode code; 1395dfecf96Smrg 1405dfecf96Smrg union { 1415dfecf96Smrg signed char signed_char; 1425dfecf96Smrg signed short signed_short; 1435dfecf96Smrg signed int signed_int; 1445dfecf96Smrg LispAtom *atom; 1455dfecf96Smrg LispObj *object; 1465dfecf96Smrg CodeTree *tree; 1475dfecf96Smrg CodeBlock *block; 1485dfecf96Smrg struct { 1495dfecf96Smrg unsigned char num_arguments; 1505dfecf96Smrg LispBuiltin *builtin; 1515dfecf96Smrg signed short offset; /* Used if opcode is XBC_CALL_SET */ 1525dfecf96Smrg } builtin; 1535dfecf96Smrg struct { 1545dfecf96Smrg unsigned char num_arguments; 1555dfecf96Smrg LispObj *name; 1565dfecf96Smrg LispObj *lambda; 1575dfecf96Smrg } call; 1585dfecf96Smrg struct { 1595dfecf96Smrg unsigned char num_arguments; 1605dfecf96Smrg LispObj *code; 1615dfecf96Smrg } bytecall; 1625dfecf96Smrg struct { 1635dfecf96Smrg short offset; 1645dfecf96Smrg LispAtom *name; 1655dfecf96Smrg } let; 1665dfecf96Smrg struct { 1675dfecf96Smrg LispAtom *symbol; 1685dfecf96Smrg LispAtom *name; 1695dfecf96Smrg } let_sym; 1705dfecf96Smrg struct { 1715dfecf96Smrg LispObj *object; 1725dfecf96Smrg LispAtom *name; 1735dfecf96Smrg } let_con; 1745dfecf96Smrg struct { 1755dfecf96Smrg signed short load; 1765dfecf96Smrg signed short set; 1775dfecf96Smrg } load_set; 1785dfecf96Smrg struct { 1795dfecf96Smrg LispObj *object; 1805dfecf96Smrg signed short offset; 1815dfecf96Smrg } load_con_set; 1825dfecf96Smrg struct { 1835dfecf96Smrg LispObj *car; 1845dfecf96Smrg LispObj *cdr; 1855dfecf96Smrg } cons; 1865dfecf96Smrg struct { 1875dfecf96Smrg short offset; 1885dfecf96Smrg LispObj *definition; 1895dfecf96Smrg } struc; 1905dfecf96Smrg } data; 1915dfecf96Smrg 1925dfecf96Smrg CodeTree *next; 1935dfecf96Smrg CodeTree *group; 1945dfecf96Smrg CodeBlock *block; 1955dfecf96Smrg}; 1965dfecf96Smrg 1975dfecf96Smrgstruct _CodeBlock { 1985dfecf96Smrg LispBlockType type; 1995dfecf96Smrg LispObj *tag; 2005dfecf96Smrg 2015dfecf96Smrg struct { 2025dfecf96Smrg LispObj **labels; 2035dfecf96Smrg CodeTree **codes; /* Filled at link time */ 2045dfecf96Smrg int length; 2055dfecf96Smrg int space; 2065dfecf96Smrg } tagbody; 2075dfecf96Smrg 2085dfecf96Smrg struct { 2095dfecf96Smrg LispAtom **symbols; /* Identifiers of variables in a block */ 2105dfecf96Smrg int *flags; /* Information about usage of the variable */ 2115dfecf96Smrg int length; 2125dfecf96Smrg } variables; 2135dfecf96Smrg 2145dfecf96Smrg int bind; /* Used in case of RETURN from LET */ 2155dfecf96Smrg int level; /* Nesting level block was created */ 2165dfecf96Smrg 2175dfecf96Smrg CodeTree *tree, *tail; 2185dfecf96Smrg CodeBlock *prev; /* Linked list as a stack */ 2195dfecf96Smrg CodeTree *parent; /* Back reference */ 2205dfecf96Smrg}; 2215dfecf96Smrg 2225dfecf96Smrgstruct _LispCom { 2235dfecf96Smrg unsigned char *bytecode; /* Bytecode generated so far */ 2245dfecf96Smrg long length; 2255dfecf96Smrg 2265dfecf96Smrg CodeBlock *block, *toplevel; 2275dfecf96Smrg 2285dfecf96Smrg int tagbody; /* Inside a tagbody block? */ 2295dfecf96Smrg int level; /* Nesting level */ 2305dfecf96Smrg int macro; /* Expanding a macro? */ 2315dfecf96Smrg 2325dfecf96Smrg int lex; 2335dfecf96Smrg 2345dfecf96Smrg int warnings; 2355dfecf96Smrg 2365dfecf96Smrg LispObj *form, *plist; 2375dfecf96Smrg 2385dfecf96Smrg jmp_buf jmp; /* Used if compilation cannot be finished */ 2395dfecf96Smrg 2405dfecf96Smrg struct { 2415dfecf96Smrg int cstack; /* Current number of objects in forms evaluation */ 2425dfecf96Smrg int cbstack; 2435dfecf96Smrg int cpstack; 2445dfecf96Smrg int stack; /* max number of objects will be loaded in stack */ 2455dfecf96Smrg int bstack; 2465dfecf96Smrg int pstack; 2475dfecf96Smrg } stack; 2485dfecf96Smrg 2495dfecf96Smrg struct { 2505dfecf96Smrg /* Constant table */ 2515dfecf96Smrg LispObj **constants; 2525dfecf96Smrg int num_constants; 2535dfecf96Smrg /* Symbol table */ 2545dfecf96Smrg LispAtom **symbols; 2555dfecf96Smrg int num_symbols; 2565dfecf96Smrg /* Builtin table */ 2575dfecf96Smrg LispBuiltin **builtins; 2585dfecf96Smrg int num_builtins; 2595dfecf96Smrg /* Bytecode table */ 2605dfecf96Smrg LispObj **bytecodes; 2615dfecf96Smrg int num_bytecodes; 2625dfecf96Smrg } table; 2635dfecf96Smrg}; 2645dfecf96Smrg 2655dfecf96Smrg/* 2665dfecf96Smrg * Prototypes 2675dfecf96Smrg */ 2685dfecf96Smrgstatic LispObj *MakeBytecodeObject(LispCom*, LispObj*, LispObj*); 2695dfecf96Smrg 2705dfecf96Smrgstatic CodeTree *CompileNewTree(LispCom*, CodeTreeType); 2715dfecf96Smrgstatic void CompileFreeState(LispCom*); 2725dfecf96Smrgstatic void CompileFreeBlock(CodeBlock*); 2735dfecf96Smrgstatic void CompileFreeTree(CodeTree*); 2745dfecf96Smrg 2755dfecf96Smrgstatic void CompileIniBlock(LispCom*, LispBlockType, LispObj*); 2765dfecf96Smrgstatic void CompileFiniBlock(LispCom*); 2775dfecf96Smrg 2785dfecf96Smrgstatic void com_BytecodeChar(LispCom*, LispByteOpcode, char); 2795dfecf96Smrgstatic void com_BytecodeShort(LispCom*, LispByteOpcode, short); 2805dfecf96Smrgstatic void com_BytecodeObject(LispCom*, LispByteOpcode, LispObj*); 2815dfecf96Smrgstatic void com_BytecodeCons(LispCom*, LispByteOpcode, LispObj*, LispObj*); 2825dfecf96Smrg 2835dfecf96Smrgstatic void com_BytecodeAtom(LispCom*, LispByteOpcode, LispAtom*); 2845dfecf96Smrg 2855dfecf96Smrgstatic void com_Bytecode(LispCom*, LispByteOpcode); 2865dfecf96Smrg 2875dfecf96Smrgstatic void com_Load(LispCom*, short); 2885dfecf96Smrgstatic void com_LoadLet(LispCom*, short, LispAtom*); 2895dfecf96Smrgstatic void com_LoadPush(LispCom*, short); 2905dfecf96Smrg 2915dfecf96Smrgstatic void com_Let(LispCom*, LispAtom*); 2925dfecf96Smrg 2935dfecf96Smrgstatic void com_Bind(LispCom*, short); 2945dfecf96Smrgstatic void com_Unbind(LispCom*, short); 2955dfecf96Smrg 2965dfecf96Smrgstatic void com_LoadSym(LispCom*, LispAtom*); 2975dfecf96Smrgstatic void com_LoadSymLet(LispCom*, LispAtom*, LispAtom*); 2985dfecf96Smrgstatic void com_LoadSymPush(LispCom*, LispAtom*); 2995dfecf96Smrg 3005dfecf96Smrgstatic void com_LoadCon(LispCom*, LispObj*); 3015dfecf96Smrgstatic void com_LoadConLet(LispCom*, LispObj*, LispAtom*); 3025dfecf96Smrgstatic void com_LoadConPush(LispCom*, LispObj*); 3035dfecf96Smrg 3045dfecf96Smrgstatic void com_Set(LispCom*, short); 3055dfecf96Smrgstatic void com_SetSym(LispCom*, LispAtom*); 3065dfecf96Smrg 3075dfecf96Smrgstatic void com_Struct(LispCom*, short, LispObj*); 3085dfecf96Smrgstatic void com_Structp(LispCom*, LispObj*); 3095dfecf96Smrg 3105dfecf96Smrgstatic void com_Call(LispCom*, unsigned char, LispBuiltin*); 3115dfecf96Smrgstatic void com_Bytecall(LispCom*, unsigned char, LispObj*); 3125dfecf96Smrgstatic void com_Funcall(LispCom*, LispObj*, LispObj*); 3135dfecf96Smrg 3145dfecf96Smrgstatic void CompileStackEnter(LispCom*, int, int); 3155dfecf96Smrgstatic void CompileStackLeave(LispCom*, int, int); 3165dfecf96Smrg 3175dfecf96Smrgstatic void LinkBytecode(LispCom*); 3185dfecf96Smrg 3195dfecf96Smrgstatic LispObj *ExecuteBytecode(unsigned char*); 3205dfecf96Smrg 3215dfecf96Smrg 3225dfecf96Smrg/* Defined in lisp.c */ 3235dfecf96Smrgvoid LispMoreStack(void); 3245dfecf96Smrgvoid LispMoreEnvironment(void); 3255dfecf96Smrgvoid LispMoreGlobals(LispPackage*); 3265dfecf96SmrgLispObj *LispEvalBackquote(LispObj*, int); 3275dfecf96Smrgvoid LispSetAtomObjectProperty(LispAtom*, LispObj*); 3285dfecf96Smrg 3295dfecf96Smrg/* 3305dfecf96Smrg * Initialization 3315dfecf96Smrg */ 3325dfecf96Smrgextern int pagesize; 3335dfecf96Smrg 3345dfecf96SmrgLispObj x_cons[8]; 3355dfecf96Smrgstatic LispObj *cons, *cons1, *cons2, *cons3, *cons4, *cons5, *cons6, *cons7; 3365dfecf96Smrg 3375dfecf96Smrg/* 3385dfecf96Smrg * Implementation 3395dfecf96Smrg */ 3405dfecf96Smrg#include "lisp/compile.c" 3415dfecf96Smrg 3425dfecf96Smrgvoid 3435dfecf96SmrgLispBytecodeInit(void) 3445dfecf96Smrg{ 3455dfecf96Smrg cons = &x_cons[7]; 3465dfecf96Smrg cons->type = LispCons_t; 3475dfecf96Smrg CDR(cons) = NIL; 3485dfecf96Smrg cons1 = &x_cons[6]; 3495dfecf96Smrg cons1->type = LispCons_t; 3505dfecf96Smrg CDR(cons1) = cons; 3515dfecf96Smrg cons2 = &x_cons[5]; 3525dfecf96Smrg cons2->type = LispCons_t; 3535dfecf96Smrg CDR(cons2) = cons1; 3545dfecf96Smrg cons3 = &x_cons[4]; 3555dfecf96Smrg cons3->type = LispCons_t; 3565dfecf96Smrg CDR(cons3) = cons2; 3575dfecf96Smrg cons4 = &x_cons[3]; 3585dfecf96Smrg cons4->type = LispCons_t; 3595dfecf96Smrg CDR(cons4) = cons3; 3605dfecf96Smrg cons5 = &x_cons[2]; 3615dfecf96Smrg cons5->type = LispCons_t; 3625dfecf96Smrg CDR(cons5) = cons4; 3635dfecf96Smrg cons6 = &x_cons[1]; 3645dfecf96Smrg cons6->type = LispCons_t; 3655dfecf96Smrg CDR(cons6) = cons5; 3665dfecf96Smrg cons7 = &x_cons[0]; 3675dfecf96Smrg cons7->type = LispCons_t; 3685dfecf96Smrg CDR(cons7) = cons6; 3695dfecf96Smrg} 3705dfecf96Smrg 3715dfecf96SmrgLispObj * 3725dfecf96SmrgLisp_Compile(LispBuiltin *builtin) 3735dfecf96Smrg/* 3745dfecf96Smrg compile name &optional definition 3755dfecf96Smrg */ 3765dfecf96Smrg{ 3775dfecf96Smrg GC_ENTER(); 3785dfecf96Smrg LispObj *result, *warnings_p, *failure_p; 3795dfecf96Smrg 3805dfecf96Smrg LispObj *name, *definition; 3815dfecf96Smrg 3825dfecf96Smrg definition = ARGUMENT(1); 3835dfecf96Smrg name = ARGUMENT(0); 3845dfecf96Smrg 3855dfecf96Smrg result = name; 3865dfecf96Smrg warnings_p = NIL; 3875dfecf96Smrg failure_p = T; 3885dfecf96Smrg 3895dfecf96Smrg if (name != NIL) { 3905dfecf96Smrg LispAtom *atom; 3915dfecf96Smrg 3925dfecf96Smrg CHECK_SYMBOL(name); 3935dfecf96Smrg atom = name->data.atom; 3945dfecf96Smrg if (atom->a_builtin || atom->a_compiled) 3955dfecf96Smrg goto finished_compilation; 3965dfecf96Smrg else if (atom->a_function) { 3975dfecf96Smrg LispCom com; 3985dfecf96Smrg int failed; 3995dfecf96Smrg int lex = 0, base; 4005dfecf96Smrg LispArgList *alist; 4015dfecf96Smrg LispObj *lambda, *form, *arguments; 4025dfecf96Smrg 4035dfecf96Smrg lambda = atom->property->fun.function; 4045dfecf96Smrg if (definition != UNSPEC || lambda->funtype != LispFunction) 4055dfecf96Smrg /* XXX TODO replace definition etc. */ 4065dfecf96Smrg goto finished_compilation; 4075dfecf96Smrg alist = atom->property->alist; 4085dfecf96Smrg 4095dfecf96Smrg memset(&com, 0, sizeof(LispCom)); 4105dfecf96Smrg com.toplevel = com.block = LispCalloc(1, sizeof(CodeBlock)); 4115dfecf96Smrg com.block->type = LispBlockClosure; 4125dfecf96Smrg com.block->tag = name; 4135dfecf96Smrg 4145dfecf96Smrg /* Create a fake argument list to avoid yet another flag 4155dfecf96Smrg * for ComCall. The value does not matter, just the fact 4165dfecf96Smrg * that the symbol will be bound or not in the implicit 4175dfecf96Smrg * PROGN of the function body. */ 4185dfecf96Smrg base = alist->num_arguments - alist->auxs.num_symbols; 4195dfecf96Smrg if (base) { 4205dfecf96Smrg LispObj *argument; 4215dfecf96Smrg int i, sforms; 4225dfecf96Smrg 4235dfecf96Smrg for (i = sforms = 0; i < alist->optionals.num_symbols; i++) 4245dfecf96Smrg if (alist->optionals.sforms[i]) 4255dfecf96Smrg ++sforms; 4265dfecf96Smrg 4275dfecf96Smrg arguments = form = NIL; 4285dfecf96Smrg i = sforms + 4295dfecf96Smrg alist->normals.num_symbols + alist->optionals.num_symbols; 4305dfecf96Smrg 4315dfecf96Smrg if (i) { 4325dfecf96Smrg arguments = form = CONS(NIL, NIL); 4335dfecf96Smrg GC_PROTECT(arguments); 4345dfecf96Smrg for (--i; i > 0; i--) { 4355dfecf96Smrg RPLACD(form, CONS(NIL, NIL)); 4365dfecf96Smrg form = CDR(form); 4375dfecf96Smrg } 4385dfecf96Smrg } 4395dfecf96Smrg 4405dfecf96Smrg for (i = 0; i < alist->keys.num_symbols; i++) { 4415dfecf96Smrg /* key symbol */ 4425dfecf96Smrg if (alist->keys.keys[i]) 4435dfecf96Smrg argument = QUOTE(alist->keys.keys[i]); 4445dfecf96Smrg else 4455dfecf96Smrg argument = alist->keys.symbols[i]; 4465dfecf96Smrg 4475dfecf96Smrg /* add key */ 4485dfecf96Smrg if (arguments == NIL) { 4495dfecf96Smrg arguments = form = CONS(argument, NIL); 4505dfecf96Smrg GC_PROTECT(arguments); 4515dfecf96Smrg } 4525dfecf96Smrg else { 4535dfecf96Smrg RPLACD(form, CONS(argument, NIL)); 4545dfecf96Smrg form = CDR(form); 4555dfecf96Smrg } 4565dfecf96Smrg 4575dfecf96Smrg /* add value */ 4585dfecf96Smrg RPLACD(form, CONS(NIL, NIL)); 4595dfecf96Smrg form = CDR(form); 4605dfecf96Smrg 4615dfecf96Smrg if (alist->keys.sforms[i]) { 4625dfecf96Smrg RPLACD(form, CONS(NIL, NIL)); 4635dfecf96Smrg form = CDR(form); 4645dfecf96Smrg } 4655dfecf96Smrg } 4665dfecf96Smrg 4675dfecf96Smrg if (alist->rest) { 4685dfecf96Smrg if (arguments == NIL) { 4695dfecf96Smrg arguments = form = CONS(NIL, NIL); 4705dfecf96Smrg GC_PROTECT(arguments); 4715dfecf96Smrg } 4725dfecf96Smrg else { 4735dfecf96Smrg RPLACD(form, CONS(NIL, NIL)); 4745dfecf96Smrg form = CDR(form); 4755dfecf96Smrg } 4765dfecf96Smrg } 4775dfecf96Smrg } 4785dfecf96Smrg else 4795dfecf96Smrg arguments = NIL; 4805dfecf96Smrg 4815dfecf96Smrg form = CONS(lambda->data.lambda.code, NIL); 4825dfecf96Smrg GC_PROTECT(form); 4835dfecf96Smrg com.form = form; 4845dfecf96Smrg com.plist = CONS(NIL, NIL); 4855dfecf96Smrg GC_PROTECT(com.plist); 4865dfecf96Smrg 4875dfecf96Smrg failed = 1; 4885dfecf96Smrg if (setjmp(com.jmp) == 0) { 4895dfecf96Smrg /* Save interpreter state */ 4905dfecf96Smrg lex = com.lex = lisp__data.env.lex; 4915dfecf96Smrg base = ComCall(&com, alist, name, arguments, 1, 0, 1); 4925dfecf96Smrg 4935dfecf96Smrg /* Generate code tree */ 4945dfecf96Smrg lisp__data.env.lex = base; 4955dfecf96Smrg ComProgn(&com, CAR(form)); 4965dfecf96Smrg failed = 0; 4975dfecf96Smrg } 4985dfecf96Smrg 4995dfecf96Smrg /* Restore interpreter state */ 5005dfecf96Smrg lisp__data.env.lex = lex; 5015dfecf96Smrg lisp__data.env.head = lisp__data.env.length = base; 5025dfecf96Smrg 5035dfecf96Smrg if (!failed) { 5045dfecf96Smrg failure_p = NIL; 5055dfecf96Smrg result = MakeBytecodeObject(&com, name, 5065dfecf96Smrg lambda->data.lambda.data); 5075dfecf96Smrg LispSetAtomCompiledProperty(atom, result); 5085dfecf96Smrg result = name; 5095dfecf96Smrg } 5105dfecf96Smrg if (com.warnings) 5115dfecf96Smrg warnings_p = FIXNUM(com.warnings); 5125dfecf96Smrg goto finished_compilation; 5135dfecf96Smrg } 5145dfecf96Smrg else 5155dfecf96Smrg goto undefined_function; 5165dfecf96Smrg } 5175dfecf96Smrg 5185dfecf96Smrgundefined_function: 5195dfecf96Smrg LispDestroy("%s: the function %s is undefined", 5205dfecf96Smrg STRFUN(builtin), STROBJ(name)); 5215dfecf96Smrg 5225dfecf96Smrgfinished_compilation: 5235dfecf96Smrg RETURN(0) = warnings_p; 5245dfecf96Smrg RETURN(1) = failure_p; 5255dfecf96Smrg RETURN_COUNT = 2; 5265dfecf96Smrg GC_LEAVE(); 5275dfecf96Smrg 5285dfecf96Smrg return (result); 5295dfecf96Smrg} 5305dfecf96Smrg 5315dfecf96SmrgLispObj * 5325dfecf96SmrgLisp_Disassemble(LispBuiltin *builtin) 5335dfecf96Smrg/* 5345dfecf96Smrg disassemble function 5355dfecf96Smrg */ 5365dfecf96Smrg{ 5375dfecf96Smrg int macro; 5385dfecf96Smrg char buffer[128]; 5395dfecf96Smrg LispAtom *atom; 5405dfecf96Smrg LispArgList *alist; 5415dfecf96Smrg LispBuiltin *xbuiltin; 5425dfecf96Smrg LispObj *name, *lambda, *bytecode; 5435dfecf96Smrg 5445dfecf96Smrg LispObj *function; 5455dfecf96Smrg 5465dfecf96Smrg function = ARGUMENT(0); 5475dfecf96Smrg 5485dfecf96Smrg macro = 0; 5495dfecf96Smrg alist = NULL; 5505dfecf96Smrg xbuiltin = NULL; 5515dfecf96Smrg name = bytecode = NULL; 5525dfecf96Smrg 5535dfecf96Smrg switch (OBJECT_TYPE(function)) { 5545dfecf96Smrg case LispAtom_t: 5555dfecf96Smrg name = function; 5565dfecf96Smrg atom = function->data.atom; 5575dfecf96Smrg alist = atom->property->alist; 5585dfecf96Smrg if (atom->a_builtin) { 5595dfecf96Smrg xbuiltin = atom->property->fun.builtin; 5605dfecf96Smrg macro = xbuiltin->type == LispMacro; 5615dfecf96Smrg } 5625dfecf96Smrg else if (atom->a_compiled) 5635dfecf96Smrg bytecode = atom->property->fun.function; 5645dfecf96Smrg else if (atom->a_function) { 5655dfecf96Smrg lambda = atom->property->fun.function; 5665dfecf96Smrg macro = lambda->funtype == LispMacro; 5675dfecf96Smrg } 5685dfecf96Smrg else if (atom->a_defstruct && 5695dfecf96Smrg atom->property->structure.function != STRUCT_NAME) { 5705dfecf96Smrg if (atom->property->structure.function == STRUCT_CONSTRUCTOR) 5715dfecf96Smrg atom = Omake_struct->data.atom; 5725dfecf96Smrg else if (atom->property->structure.function == STRUCT_CHECK) 5735dfecf96Smrg atom = Ostruct_type->data.atom; 5745dfecf96Smrg else 5755dfecf96Smrg atom = Ostruct_access->data.atom; 5765dfecf96Smrg xbuiltin = atom->property->fun.builtin; 5775dfecf96Smrg } 5785dfecf96Smrg else 5795dfecf96Smrg LispDestroy("%s: the function %s is not defined", 5805dfecf96Smrg STRFUN(builtin), STROBJ(function)); 5815dfecf96Smrg break; 5825dfecf96Smrg case LispBytecode_t: 5835dfecf96Smrg name = Olambda; 5845dfecf96Smrg bytecode = function; 5855dfecf96Smrg break; 5865dfecf96Smrg case LispLambda_t: 5875dfecf96Smrg name = Olambda; 5885dfecf96Smrg alist = (LispArgList*)function->data.lambda.name->data.opaque.data; 5895dfecf96Smrg break; 5905dfecf96Smrg case LispCons_t: 5915dfecf96Smrg if (CAR(function) == Olambda) { 5925dfecf96Smrg function = EVAL(function); 5935dfecf96Smrg if (OBJECT_TYPE(function) == LispLambda_t) { 5945dfecf96Smrg name = Olambda; 5955dfecf96Smrg alist = (LispArgList*) 5965dfecf96Smrg function->data.lambda.name->data.opaque.data; 5975dfecf96Smrg break; 5985dfecf96Smrg } 5995dfecf96Smrg } 6005dfecf96Smrg default: 6015dfecf96Smrg LispDestroy("%s: %s is not a function", 6025dfecf96Smrg STRFUN(builtin), STROBJ(function)); 6035dfecf96Smrg break; 6045dfecf96Smrg } 6055dfecf96Smrg 6065dfecf96Smrg if (xbuiltin) { 6075dfecf96Smrg LispWriteStr(NIL, "Builtin ", 8); 6085dfecf96Smrg if (macro) 6095dfecf96Smrg LispWriteStr(NIL, "macro ", 6); 6105dfecf96Smrg else 6115dfecf96Smrg LispWriteStr(NIL, "function ", 9); 6125dfecf96Smrg } 6135dfecf96Smrg else if (macro) 6145dfecf96Smrg LispWriteStr(NIL, "Macro ", 6); 6155dfecf96Smrg else 6165dfecf96Smrg LispWriteStr(NIL, "Function ", 9); 6175dfecf96Smrg LispWriteObject(NIL, name); 6185dfecf96Smrg LispWriteStr(NIL, ":\n", 2); 6195dfecf96Smrg 6205dfecf96Smrg if (alist) { 6215dfecf96Smrg int i; 6225dfecf96Smrg 6235dfecf96Smrg sprintf(buffer, "%d required argument%s", 6245dfecf96Smrg alist->normals.num_symbols, 6255dfecf96Smrg alist->normals.num_symbols != 1 ? "s" : ""); 6265dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 6275dfecf96Smrg for (i = 0; i < alist->normals.num_symbols; i++) { 6285dfecf96Smrg LispWriteChar(NIL, i ? ',' : ':'); 6295dfecf96Smrg LispWriteChar(NIL, ' '); 6305dfecf96Smrg LispWriteStr(NIL, ATOMID(alist->normals.symbols[i]), 6315dfecf96Smrg strlen(ATOMID(alist->normals.symbols[i]))); 6325dfecf96Smrg } 6335dfecf96Smrg LispWriteChar(NIL, '\n'); 6345dfecf96Smrg 6355dfecf96Smrg sprintf(buffer, "%d optional argument%s", 6365dfecf96Smrg alist->optionals.num_symbols, 6375dfecf96Smrg alist->optionals.num_symbols != 1 ? "s" : ""); 6385dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 6395dfecf96Smrg for (i = 0; i < alist->optionals.num_symbols; i++) { 6405dfecf96Smrg LispWriteChar(NIL, i ? ',' : ':'); 6415dfecf96Smrg LispWriteChar(NIL, ' '); 6425dfecf96Smrg LispWriteStr(NIL, ATOMID(alist->optionals.symbols[i]), 6435dfecf96Smrg strlen(ATOMID(alist->optionals.symbols[i]))); 6445dfecf96Smrg } 6455dfecf96Smrg LispWriteChar(NIL, '\n'); 6465dfecf96Smrg 6475dfecf96Smrg sprintf(buffer, "%d keyword parameter%s", 6485dfecf96Smrg alist->keys.num_symbols, 6495dfecf96Smrg alist->keys.num_symbols != 1 ? "s" : ""); 6505dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 6515dfecf96Smrg for (i = 0; i < alist->keys.num_symbols; i++) { 6525dfecf96Smrg LispWriteChar(NIL, i ? ',' : ':'); 6535dfecf96Smrg LispWriteChar(NIL, ' '); 6545dfecf96Smrg LispWriteObject(NIL, alist->keys.symbols[i]); 6555dfecf96Smrg } 6565dfecf96Smrg LispWriteChar(NIL, '\n'); 6575dfecf96Smrg 6585dfecf96Smrg if (alist->rest) { 6595dfecf96Smrg LispWriteStr(NIL, "Rest argument: ", 15); 6605dfecf96Smrg LispWriteStr(NIL, ATOMID(alist->rest), 6615dfecf96Smrg strlen(ATOMID(alist->rest))); 6625dfecf96Smrg LispWriteChar(NIL, '\n'); 6635dfecf96Smrg } 6645dfecf96Smrg else 6655dfecf96Smrg LispWriteStr(NIL, "No rest argument\n", 17); 6665dfecf96Smrg } 6675dfecf96Smrg 6685dfecf96Smrg if (bytecode) { 6695dfecf96Smrg char *ptr; 6705dfecf96Smrg int *offsets[4]; 6715dfecf96Smrg int i, done, j, sym0, sym1, con0, con1, bui0, byt0, strd, strf; 6725dfecf96Smrg LispObj **constants; 6735dfecf96Smrg LispAtom **symbols; 6745dfecf96Smrg LispBuiltin **builtins; 6755dfecf96Smrg LispObj **names; 6765dfecf96Smrg short stack, num_constants, num_symbols, num_builtins, num_bytecodes; 6775dfecf96Smrg unsigned char *base, *stream = bytecode->data.bytecode.bytecode->code; 6785dfecf96Smrg 6795dfecf96Smrg LispWriteStr(NIL, "\nBytecode header:\n", 18); 6805dfecf96Smrg 6815dfecf96Smrg /* Header information */ 6825dfecf96Smrg stack = *(short*)stream; 6835dfecf96Smrg stream += sizeof(short); 6845dfecf96Smrg sprintf(buffer, "%d element%s used in the stack\n", 6855dfecf96Smrg stack, stack != 1 ? "s" : ""); 6865dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 6875dfecf96Smrg stack = *(short*)stream; 6885dfecf96Smrg stream += sizeof(short); 6895dfecf96Smrg sprintf(buffer, "%d element%s used in the builtin stack\n", 6905dfecf96Smrg stack, stack != 1 ? "s" : ""); 6915dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 6925dfecf96Smrg stack = *(short*)stream; 6935dfecf96Smrg stream += sizeof(short); 6945dfecf96Smrg sprintf(buffer, "%d element%s used in the protected stack\n", 6955dfecf96Smrg stack, stack != 1 ? "s" : ""); 6965dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 6975dfecf96Smrg 6985dfecf96Smrg num_constants = *(short*)stream; 6995dfecf96Smrg stream += sizeof(short); 7005dfecf96Smrg num_symbols = *(short*)stream; 7015dfecf96Smrg stream += sizeof(short); 7025dfecf96Smrg num_builtins = *(short*)stream; 7035dfecf96Smrg stream += sizeof(short); 7045dfecf96Smrg num_bytecodes = *(short*)stream; 7055dfecf96Smrg stream += sizeof(short); 7065dfecf96Smrg 7075dfecf96Smrg constants = (LispObj**)stream; 7085dfecf96Smrg stream += num_constants * sizeof(LispObj*); 7095dfecf96Smrg symbols = (LispAtom**)stream; 7105dfecf96Smrg stream += num_symbols * sizeof(LispAtom*); 7115dfecf96Smrg builtins = (LispBuiltin**)stream; 7125dfecf96Smrg stream += num_builtins * sizeof(LispBuiltin*); 7135dfecf96Smrg stream += num_bytecodes * sizeof(unsigned char*); 7145dfecf96Smrg names = (LispObj**)stream; 7155dfecf96Smrg stream += num_bytecodes * sizeof(LispObj*); 7165dfecf96Smrg 7175dfecf96Smrg for (i = 0; i < num_constants; i++) { 7185dfecf96Smrg sprintf(buffer, "Constant %d = %s\n", i, STROBJ(constants[i])); 7195dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 7205dfecf96Smrg } 7215dfecf96Smrg 7225dfecf96Smrg/* Macro XSTRING avoids some noisy in the output, if it were defined as 7235dfecf96Smrg * #define XSTRING(object) object ? STROBJ(object) : #<UNBOUND> 7245dfecf96Smrg * and called as XSTRING(atom->object) 7255dfecf96Smrg * it would also print the package name were the symbol was first defined, 7265dfecf96Smrg * but for local variables, only the symbol string is important. */ 7275dfecf96Smrg#define XSTRING(string) string ? string : "#<UNBOUND>" 7285dfecf96Smrg 7295dfecf96Smrg for (i = 0; i < num_symbols; i++) { 7305dfecf96Smrg sprintf(buffer, "Symbol %d = %s\n", 7315dfecf96Smrg i, XSTRING(symbols[i]->string)); 7325dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 7335dfecf96Smrg } 7345dfecf96Smrg for (i = 0; i < num_builtins; i++) { 7355dfecf96Smrg sprintf(buffer, "Builtin %d = %s\n", 7365dfecf96Smrg i, STROBJ(builtins[i]->symbol)); 7375dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 7385dfecf96Smrg } 7395dfecf96Smrg for (i = 0; i < num_bytecodes; i++) { 7405dfecf96Smrg sprintf(buffer, "Bytecode %d = %s\n", 7415dfecf96Smrg i, STROBJ(names[i])); 7425dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 7435dfecf96Smrg } 7445dfecf96Smrg 7455dfecf96Smrg /* Make readability slightly easier printing the names of local 7465dfecf96Smrg * variables where it's offset is known, i.e. function arguments. */ 7475dfecf96Smrg if (alist) { 7485dfecf96Smrg if (alist->num_arguments == 0) 7495dfecf96Smrg LispWriteStr(NIL, "\nNo initial stack\n", 18); 7505dfecf96Smrg else { 7515dfecf96Smrg int len1, len2; 7525dfecf96Smrg 7535dfecf96Smrg j = 0; 7545dfecf96Smrg LispWriteStr(NIL, "\nInitial stack:\n", 16); 7555dfecf96Smrg 7565dfecf96Smrg for (i = 0; i < alist->normals.num_symbols; i++, j++) { 7575dfecf96Smrg sprintf(buffer, "%d = ", j); 7585dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 7595dfecf96Smrg ptr = alist->normals.symbols[i]->data.atom->string; 7605dfecf96Smrg LispWriteStr(NIL, ptr, strlen(ptr)); 7615dfecf96Smrg LispWriteChar(NIL, '\n'); 7625dfecf96Smrg } 7635dfecf96Smrg 7645dfecf96Smrg for (i = 0; i < alist->optionals.num_symbols; i++, j++) { 7655dfecf96Smrg sprintf(buffer, "%d = ", j); 7665dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 7675dfecf96Smrg ptr = alist->optionals.symbols[i]->data.atom->string; 7685dfecf96Smrg LispWriteStr(NIL, ptr, strlen(ptr)); 7695dfecf96Smrg LispWriteChar(NIL, '\n'); 7705dfecf96Smrg if (alist->optionals.sforms[i]) { 7715dfecf96Smrg sprintf(buffer, "%d = ", j); 7725dfecf96Smrg len1 = strlen(buffer); 7735dfecf96Smrg LispWriteStr(NIL, buffer, len1); 7745dfecf96Smrg ptr = alist->optionals.sforms[i]->data.atom->string; 7755dfecf96Smrg len2 = strlen(ptr); 7765dfecf96Smrg LispWriteStr(NIL, ptr, len2); 7775dfecf96Smrg LispWriteChars(NIL, ' ', 28 - (len1 + len2)); 7785dfecf96Smrg LispWriteStr(NIL, "; sform\n", 9); 7795dfecf96Smrg j++; 7805dfecf96Smrg } 7815dfecf96Smrg } 7825dfecf96Smrg 7835dfecf96Smrg for (i = 0; i < alist->keys.num_symbols; i++, j++) { 7845dfecf96Smrg sprintf(buffer, "%d = ", j); 7855dfecf96Smrg len1 = strlen(buffer); 7865dfecf96Smrg LispWriteStr(NIL, buffer, len1); 7875dfecf96Smrg if (alist->keys.keys[i]) { 7885dfecf96Smrg ptr = alist->keys.keys[i]->data.atom->string; 7895dfecf96Smrg len2 = strlen(ptr); 7905dfecf96Smrg LispWriteStr(NIL, ptr, strlen(ptr)); 7915dfecf96Smrg LispWriteChars(NIL, ' ', 28 - (len1 + len2)); 7925dfecf96Smrg LispWriteStr(NIL, "; special key", 14); 7935dfecf96Smrg } 7945dfecf96Smrg else { 7955dfecf96Smrg ptr = alist->keys.symbols[i]->data.atom->string; 7965dfecf96Smrg LispWriteStr(NIL, ptr, strlen(ptr)); 7975dfecf96Smrg } 7985dfecf96Smrg LispWriteChar(NIL, '\n'); 7995dfecf96Smrg if (alist->keys.sforms[i]) { 8005dfecf96Smrg sprintf(buffer, "%d = ", j); 8015dfecf96Smrg len1 = strlen(buffer); 8025dfecf96Smrg LispWriteStr(NIL, buffer, len1); 8035dfecf96Smrg ptr = alist->keys.sforms[i]->data.atom->string; 8045dfecf96Smrg len2 = strlen(ptr); 8055dfecf96Smrg LispWriteStr(NIL, ptr, len2); 8065dfecf96Smrg LispWriteChars(NIL, ' ', 28 - (len1 + len2)); 8075dfecf96Smrg LispWriteStr(NIL, "; sform\n", 9); 8085dfecf96Smrg j++; 8095dfecf96Smrg } 8105dfecf96Smrg } 8115dfecf96Smrg 8125dfecf96Smrg if (alist->rest) { 8135dfecf96Smrg sprintf(buffer, "%d = ", j); 8145dfecf96Smrg len1 = strlen(buffer); 8155dfecf96Smrg LispWriteStr(NIL, buffer, len1); 8165dfecf96Smrg ptr = alist->rest->data.atom->string; 8175dfecf96Smrg len2 = strlen(ptr); 8185dfecf96Smrg LispWriteStr(NIL, ptr, len2); 8195dfecf96Smrg LispWriteChar(NIL, '\n'); 8205dfecf96Smrg j++; 8215dfecf96Smrg } 8225dfecf96Smrg 8235dfecf96Smrg for (i = 0; i < alist->auxs.num_symbols; i++, j++) { 8245dfecf96Smrg sprintf(buffer, "%d = ", j); 8255dfecf96Smrg len1 = strlen(buffer); 8265dfecf96Smrg LispWriteStr(NIL, buffer, len1); 8275dfecf96Smrg ptr = alist->auxs.symbols[i]->data.atom->string; 8285dfecf96Smrg len2 = strlen(ptr); 8295dfecf96Smrg LispWriteStr(NIL, ptr, len2); 8305dfecf96Smrg LispWriteChars(NIL, ' ', 28 - (len1 + len2)); 8315dfecf96Smrg LispWriteStr(NIL, "; aux\n", 7); 8325dfecf96Smrg } 8335dfecf96Smrg } 8345dfecf96Smrg } 8355dfecf96Smrg 8365dfecf96Smrg LispWriteStr(NIL, "\nBytecode stream:\n", 18); 8375dfecf96Smrg 8385dfecf96Smrg base = stream; 8395dfecf96Smrg for (done = j = 0; !done; j = 0) { 8405dfecf96Smrg sym0 = sym1 = con0 = con1 = bui0 = byt0 = strd = strf = -1; 8415dfecf96Smrg sprintf(buffer, "%4ld ", (long)(stream - base)); 8425dfecf96Smrg ptr = buffer + strlen(buffer); 8435dfecf96Smrg switch (*stream++) { 8445dfecf96Smrg case XBC_NOOP: strcpy(ptr, "NOOP"); break; 8455dfecf96Smrg case XBC_PRED: 8465dfecf96Smrg strcpy(ptr, "PRED:"); 8475dfecf96Smrg ptr += strlen(ptr); 8485dfecf96Smrg goto predicate; 8495dfecf96Smrg case XBC_INV: strcpy(ptr, "INV"); break; 8505dfecf96Smrg case XBC_NIL: strcpy(ptr, "NIL"); break; 8515dfecf96Smrg case XBC_T: strcpy(ptr, "T"); break; 8525dfecf96Smrg case XBC_CAR: strcpy(ptr, "CAR"); break; 8535dfecf96Smrg case XBC_CDR: strcpy(ptr, "CDR"); break; 8545dfecf96Smrg case XBC_RPLACA:strcpy(ptr, "RPLACA"); break; 8555dfecf96Smrg case XBC_RPLACD:strcpy(ptr, "RPLACD"); break; 8565dfecf96Smrg case XBC_EQ: strcpy(ptr, "EQ"); break; 8575dfecf96Smrg case XBC_EQL: strcpy(ptr, "EQL"); break; 8585dfecf96Smrg case XBC_EQUAL: strcpy(ptr, "EQUAL"); break; 8595dfecf96Smrg case XBC_EQUALP:strcpy(ptr, "EQUALP"); break; 8605dfecf96Smrg case XBC_LENGTH:strcpy(ptr, "LENGTH"); break; 8615dfecf96Smrg case XBC_LAST: strcpy(ptr, "LAST"); break; 8625dfecf96Smrg case XBC_NTHCDR:strcpy(ptr, "NTHCDR"); break; 8635dfecf96Smrg case XBC_PUSH: strcpy(ptr, "PUSH"); break; 8645dfecf96Smrg case XBC_CAR_PUSH: 8655dfecf96Smrg strcpy(ptr, "CAR&PUSH"); 8665dfecf96Smrg break; 8675dfecf96Smrg case XBC_CDR_PUSH: 8685dfecf96Smrg strcpy(ptr, "CDR&PUSH"); 8695dfecf96Smrg break; 8705dfecf96Smrg case XBC_PUSH_NIL: 8715dfecf96Smrg strcpy(ptr, "PUSH NIL"); 8725dfecf96Smrg break; 8735dfecf96Smrg case XBC_PUSH_UNSPEC: 8745dfecf96Smrg strcpy(ptr, "PUSH #<UNSPEC>"); 8755dfecf96Smrg break; 8765dfecf96Smrg case XBC_PUSH_T: 8775dfecf96Smrg strcpy(ptr, "PUSH T"); 8785dfecf96Smrg break; 8795dfecf96Smrg case XBC_PUSH_NIL_N: 8805dfecf96Smrg strcpy(ptr, "PUSH NIL "); 8815dfecf96Smrg ptr += strlen(ptr); 8825dfecf96Smrg sprintf(ptr, "%d", (int)(*stream++)); 8835dfecf96Smrg break; 8845dfecf96Smrg case XBC_PUSH_UNSPEC_N: 8855dfecf96Smrg strcpy(ptr, "PUSH #<UNSPEC> "); 8865dfecf96Smrg ptr += strlen(ptr); 8875dfecf96Smrg sprintf(ptr, "%d", (int)(*stream++)); 8885dfecf96Smrg break; 8895dfecf96Smrg case XBC_LET: 8905dfecf96Smrg strcpy(ptr, "LET"); 8915dfecf96Smrg/* update sym0 */ 8925dfecf96Smrgsymbol: 8935dfecf96Smrg offsets[j++] = &sym0; 8945dfecf96Smrg/* update <offsets> - print [byte] */ 8955dfecf96Smrgoffset: 8965dfecf96Smrg ptr += strlen(ptr); 8975dfecf96Smrg i = *stream++; 8985dfecf96Smrg *(offsets[j - 1]) = i; 8995dfecf96Smrg sprintf(ptr, " [%d]", i); 9005dfecf96Smrg break; 9015dfecf96Smrg case XBC_LETX: 9025dfecf96Smrg strcpy(ptr, "LET*"); 9035dfecf96Smrg goto symbol; 9045dfecf96Smrg case XBC_LET_NIL: 9055dfecf96Smrg strcpy(ptr, "LET NIL"); 9065dfecf96Smrg goto symbol; 9075dfecf96Smrg case XBC_LETX_NIL: 9085dfecf96Smrg strcpy(ptr, "LET* NIL"); 9095dfecf96Smrg goto symbol; 9105dfecf96Smrg case XBC_LETBIND: 9115dfecf96Smrg strcpy(ptr, "LETBIND"); 9125dfecf96Smrg/* print byte */ 9135dfecf96Smrgvalue: 9145dfecf96Smrg ptr += strlen(ptr); 9155dfecf96Smrg sprintf(ptr, " %d", (int)(*stream++)); 9165dfecf96Smrg break; 9175dfecf96Smrg case XBC_UNLET:strcpy(ptr, "UNLET"); goto value; 9185dfecf96Smrg case XBC_LOAD: 9195dfecf96Smrg strcpy(ptr, "LOAD"); 9205dfecf96Smrg/* print (byte) */ 9215dfecf96Smrgreference: 9225dfecf96Smrg ptr += strlen(ptr); 9235dfecf96Smrg i = *stream++; 9245dfecf96Smrg sprintf(ptr, " (%d)", i); 9255dfecf96Smrg break; 9265dfecf96Smrg case XBC_LOAD_CAR: 9275dfecf96Smrg strcpy(ptr, "LOAD&CAR"); 9285dfecf96Smrg goto reference; 9295dfecf96Smrg case XBC_LOAD_CDR: 9305dfecf96Smrg strcpy(ptr, "LOAD&CDR"); 9315dfecf96Smrg goto reference; 9325dfecf96Smrg case XBC_LOAD_CAR_STORE: 9335dfecf96Smrg strcpy(ptr, "LOAD&CAR&STORE"); 9345dfecf96Smrg goto reference; 9355dfecf96Smrg case XBC_LOAD_CDR_STORE: 9365dfecf96Smrg strcpy(ptr, "LOAD&CDR&STORE"); 9375dfecf96Smrg goto reference; 9385dfecf96Smrg case XBC_LOAD_LET: 9395dfecf96Smrg strcpy(ptr, "LOAD&LET"); 9405dfecf96Smrgload_let: 9415dfecf96Smrg offsets[j++] = &sym0; 9425dfecf96Smrg i = *stream++; 9435dfecf96Smrg ptr += strlen(ptr); 9445dfecf96Smrg sprintf(ptr, " (%d)", i); 9455dfecf96Smrg goto offset; 9465dfecf96Smrg case XBC_LOAD_LETX: 9475dfecf96Smrg strcpy(ptr, "LOAD&LET*"); 9485dfecf96Smrg goto load_let; 9495dfecf96Smrg case XBC_STRUCT: 9505dfecf96Smrg strcpy(ptr, "STRUCT"); 9515dfecf96Smrg offsets[j++] = &strf; 9525dfecf96Smrg offsets[j++] = &strd; 9535dfecf96Smrg/* update <offsets> - print [byte] - update <offsets> - print [byte] */ 9545dfecf96Smrgoffset_offset: 9555dfecf96Smrg ptr += strlen(ptr); 9565dfecf96Smrg i = *stream++; 9575dfecf96Smrg *(offsets[j - 2]) = i; 9585dfecf96Smrg sprintf(ptr, " [%d]", i); 9595dfecf96Smrg goto offset; 9605dfecf96Smrg case XBC_LOAD_PUSH: 9615dfecf96Smrg strcpy(ptr, "LOAD&PUSH"); 9625dfecf96Smrg goto reference; 9635dfecf96Smrg case XBC_LOADCON: 9645dfecf96Smrg strcpy(ptr, "LOADCON"); 9655dfecf96Smrgconstant: 9665dfecf96Smrg offsets[j++] = &con0; 9675dfecf96Smrg goto offset; 9685dfecf96Smrg case XBC_LOADCON_SET: 9695dfecf96Smrg strcpy(ptr, "LOADCON&SET"); 9705dfecf96Smrg offsets[j++] = &con0; 9715dfecf96Smrg/* update <offsets> - print [byte] - print (byte) */ 9725dfecf96Smrgoffset_reference: 9735dfecf96Smrg i = *stream++; 9745dfecf96Smrg *(offsets[j - 1]) = i; 9755dfecf96Smrg ptr += strlen(ptr); 9765dfecf96Smrg sprintf(ptr, " [%d]", i); 9775dfecf96Smrg goto reference; 9785dfecf96Smrg case XBC_STRUCTP: 9795dfecf96Smrg strcpy(ptr, "STRUCTP"); 9805dfecf96Smrg offsets[j++] = &strd; 9815dfecf96Smrg goto offset; 9825dfecf96Smrg case XBC_LOADCON_LET: 9835dfecf96Smrg strcpy(ptr, "LOADCON&LET"); 9845dfecf96Smrgloadcon_let: 9855dfecf96Smrg offsets[j++] = &con0; 9865dfecf96Smrg offsets[j++] = &sym0; 9875dfecf96Smrg goto offset_offset; 9885dfecf96Smrg case XBC_LOADCON_LETX: 9895dfecf96Smrg strcpy(ptr, "LOADCON&LET*"); 9905dfecf96Smrg goto loadcon_let; 9915dfecf96Smrg case XBC_LOADCON_PUSH: 9925dfecf96Smrg strcpy(ptr, "LOADCON&PUSH"); 9935dfecf96Smrg goto constant; 9945dfecf96Smrg case XBC_LOADSYM: 9955dfecf96Smrg strcpy(ptr, "LOADSYM"); 9965dfecf96Smrg goto symbol; 9975dfecf96Smrg case XBC_LOADSYM_LET: 9985dfecf96Smrg strcpy(ptr, "LOADSYM&LET"); 9995dfecf96Smrgloadsym_let: 10005dfecf96Smrg offsets[j++] = &sym0; 10015dfecf96Smrg offsets[j++] = &sym1; 10025dfecf96Smrg goto offset_offset; 10035dfecf96Smrg case XBC_LOADSYM_LETX: 10045dfecf96Smrg strcpy(ptr, "LOADSYM&LET*"); 10055dfecf96Smrg goto loadsym_let; 10065dfecf96Smrg case XBC_LOADSYM_PUSH: 10075dfecf96Smrg strcpy(ptr, "LOADSYM&PUSH"); 10085dfecf96Smrg goto symbol; 10095dfecf96Smrg case XBC_LOAD_SET: 10105dfecf96Smrg strcpy(ptr, "LOAD&SET"); 10115dfecf96Smrg/* print (byte) - print (byte) */ 10125dfecf96Smrgreference_reference: 10135dfecf96Smrg ptr += strlen(ptr); 10145dfecf96Smrg i = *stream++; 10155dfecf96Smrg sprintf(ptr, " (%d)", i); 10165dfecf96Smrg goto reference; 10175dfecf96Smrg case XBC_LOAD_CAR_SET: 10185dfecf96Smrg strcpy(ptr, "LOAD&CAR&SET"); 10195dfecf96Smrg goto reference_reference; 10205dfecf96Smrg case XBC_LOAD_CDR_SET: 10215dfecf96Smrg strcpy(ptr, "LOAD&CDR&SET"); 10225dfecf96Smrg goto reference_reference; 10235dfecf96Smrg case XBC_CAR_SET: 10245dfecf96Smrg strcpy(ptr, "CAR&SET"); 10255dfecf96Smrg goto reference; 10265dfecf96Smrg case XBC_CDR_SET: 10275dfecf96Smrg strcpy(ptr, "CDR&SET"); 10285dfecf96Smrg goto reference; 10295dfecf96Smrg case XBC_SET: 10305dfecf96Smrg strcpy(ptr, "SET"); 10315dfecf96Smrg goto reference; 10325dfecf96Smrg case XBC_SETSYM: 10335dfecf96Smrg strcpy(ptr, "SETSYM"); 10345dfecf96Smrg goto symbol; 10355dfecf96Smrg case XBC_SET_NIL: 10365dfecf96Smrg strcpy(ptr, "SET NIL"); 10375dfecf96Smrg goto reference; 10385dfecf96Smrg case XBC_CALL: 10395dfecf96Smrg strcpy(ptr, "CALL"); 10405dfecf96Smrg ptr += strlen(ptr); 10415dfecf96Smrg sprintf(ptr, " %d", (int)(*stream++)); 10425dfecf96Smrg offsets[j++] = &bui0; 10435dfecf96Smrg goto offset; 10445dfecf96Smrg case XBC_CALL_SET: 10455dfecf96Smrg strcpy(ptr, "CALL&SET"); 10465dfecf96Smrg ptr += strlen(ptr); 10475dfecf96Smrg sprintf(ptr, " %d", (int)(*stream++)); 10485dfecf96Smrg offsets[j++] = &bui0; 10495dfecf96Smrg goto offset_reference; 10505dfecf96Smrg case XBC_BYTECALL: 10515dfecf96Smrg strcpy(ptr, "BYTECALL"); 10525dfecf96Smrg ptr += strlen(ptr); 10535dfecf96Smrg sprintf(ptr, " %d", (int)(*stream++)); 10545dfecf96Smrg offsets[j++] = &byt0; 10555dfecf96Smrg goto offset; 10565dfecf96Smrg case XBC_FUNCALL: 10575dfecf96Smrg strcpy(ptr, "FUNCALL"); 10585dfecf96Smrgconstant_constant: 10595dfecf96Smrg offsets[j++] = &con0; 10605dfecf96Smrg offsets[j++] = &con1; 10615dfecf96Smrg goto offset_offset; 10625dfecf96Smrg case XBC_CCONS: 10635dfecf96Smrg strcpy(ptr, "CCONS"); 10645dfecf96Smrg goto constant_constant; 10655dfecf96Smrg case XBC_CSTAR: strcpy(ptr, "CSTAR"); break; 10665dfecf96Smrg case XBC_CFINI: strcpy(ptr, "CFINI"); break; 10675dfecf96Smrg case XBC_LSTAR: strcpy(ptr, "LSTAR"); break; 10685dfecf96Smrg case XBC_LCONS: strcpy(ptr, "LCONS"); break; 10695dfecf96Smrg case XBC_LFINI: strcpy(ptr, "LFINI"); break; 10705dfecf96Smrg case XBC_BCONS: strcpy(ptr, "BCONS"); break; 10715dfecf96Smrg case XBC_BCONS1: case XBC_BCONS2: case XBC_BCONS3: 10725dfecf96Smrg case XBC_BCONS4: case XBC_BCONS5: case XBC_BCONS6: 10735dfecf96Smrg case XBC_BCONS7: 10745dfecf96Smrg strcpy(ptr, "BCONS"); 10755dfecf96Smrg ptr += strlen(ptr); 10765dfecf96Smrg sprintf(ptr, "%d", (int)(stream[-1] - XBC_BCONS)); 10775dfecf96Smrg break; 10785dfecf96Smrg case XBC_JUMP: 10795dfecf96Smrg strcpy(ptr, "JUMP"); 10805dfecf96Smrginteger: 10815dfecf96Smrg ptr += strlen(ptr); 10825dfecf96Smrg sprintf(ptr, " %d", *(signed short*)stream); 10835dfecf96Smrg stream += sizeof(short); 10845dfecf96Smrg break; 10855dfecf96Smrg case XBC_JUMPT: 10865dfecf96Smrg strcpy(ptr, "JUMPT"); 10875dfecf96Smrg goto integer; 10885dfecf96Smrg case XBC_JUMPNIL: 10895dfecf96Smrg strcpy(ptr, "JUMPNIL"); 10905dfecf96Smrg goto integer; 10915dfecf96Smrg case XBC_LETREC: 10925dfecf96Smrg strcpy(ptr, "LETREC"); 10935dfecf96Smrg ptr += strlen(ptr); 10945dfecf96Smrg sprintf(ptr, " %d", (int)*stream++); 10955dfecf96Smrg break; 10965dfecf96Smrg case XBC_RETURN: 10975dfecf96Smrg strcpy(ptr, "RETURN"); 10985dfecf96Smrg done = 1; 10995dfecf96Smrg break; 11005dfecf96Smrg } 11015dfecf96Smrg i = ptr - buffer + strlen(ptr); 11025dfecf96Smrg LispWriteStr(NIL, buffer, i); 11035dfecf96Smrg if (j) { 11045dfecf96Smrg 11055dfecf96Smrg /* Pad */ 11065dfecf96Smrg LispWriteChars(NIL, ' ', 28 - i); 11075dfecf96Smrg LispWriteChar(NIL, ';'); 11085dfecf96Smrg 11095dfecf96Smrg ptr = buffer; 11105dfecf96Smrg 11115dfecf96Smrg /* Structure */ 11125dfecf96Smrg if (strf >= 0) { 11135dfecf96Smrg /* strd is valid if strf set */ 11145dfecf96Smrg LispObj *fields = constants[strd]; 11155dfecf96Smrg 11165dfecf96Smrg for (; strf >= 0; strf--) 11175dfecf96Smrg fields = CDR(fields); 11185dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11195dfecf96Smrg strcpy(ptr, CAR(fields)->data.atom->string); 11205dfecf96Smrg ptr += strlen(ptr); 11215dfecf96Smrg } 11225dfecf96Smrg if (strd >= 0) { 11235dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11245dfecf96Smrg strcpy(ptr, STROBJ(CAR(constants[strd]))); 11255dfecf96Smrg ptr += strlen(ptr); 11265dfecf96Smrg } 11275dfecf96Smrg 11285dfecf96Smrg /* Constants */ 11295dfecf96Smrg if (con0 >= 0) { 11305dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11315dfecf96Smrg strcpy(ptr, STROBJ(constants[con0])); 11325dfecf96Smrg ptr += strlen(ptr); 11335dfecf96Smrg if (con1 >= 0) { 11345dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11355dfecf96Smrg strcpy(ptr, STROBJ(constants[con1])); 11365dfecf96Smrg ptr += strlen(ptr); 11375dfecf96Smrg } 11385dfecf96Smrg } 11395dfecf96Smrg 11405dfecf96Smrg /* Builtin */ 11415dfecf96Smrg if (bui0 >= 0) { 11425dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11435dfecf96Smrg strcpy(ptr, STROBJ(builtins[bui0]->symbol)); 11445dfecf96Smrg ptr += strlen(ptr); 11455dfecf96Smrg } 11465dfecf96Smrg 11475dfecf96Smrg /* Bytecode */ 11485dfecf96Smrg if (byt0 >= 0) { 11495dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11505dfecf96Smrg strcpy(ptr, STROBJ(names[byt0])); 11515dfecf96Smrg ptr += strlen(ptr); 11525dfecf96Smrg } 11535dfecf96Smrg 11545dfecf96Smrg /* Symbols */ 11555dfecf96Smrg if (sym0 >= 0) { 11565dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11575dfecf96Smrg strcpy(ptr, XSTRING(symbols[sym0]->string)); 11585dfecf96Smrg ptr += strlen(ptr); 11595dfecf96Smrg if (sym1 >= 0) { 11605dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11615dfecf96Smrg strcpy(ptr, XSTRING(symbols[sym1]->string)); 11625dfecf96Smrg ptr += strlen(ptr); 11635dfecf96Smrg } 11645dfecf96Smrg } 11655dfecf96Smrg 11665dfecf96Smrg i = ptr - buffer; 11675dfecf96Smrg LispWriteStr(NIL, buffer, i); 11685dfecf96Smrg } 11695dfecf96Smrg LispWriteChar(NIL, '\n'); 11705dfecf96Smrg continue; 11715dfecf96Smrgpredicate: 11725dfecf96Smrg switch (*stream++) { 11735dfecf96Smrg case XBP_CONSP: strcpy(ptr, "CONSP"); break; 11745dfecf96Smrg case XBP_LISTP: strcpy(ptr, "LISTP"); break; 11755dfecf96Smrg case XBP_NUMBERP: strcpy(ptr, "NUMBERP"); break; 11765dfecf96Smrg } 11775dfecf96Smrg LispWriteStr(NIL, buffer, ptr - buffer + strlen(ptr)); 11785dfecf96Smrg LispWriteChar(NIL, '\n'); 11795dfecf96Smrg } 11805dfecf96Smrg#undef XSTRING 11815dfecf96Smrg } 11825dfecf96Smrg 11835dfecf96Smrg return (function); 11845dfecf96Smrg} 11855dfecf96Smrg 11865dfecf96Smrg 11875dfecf96Smrg 11885dfecf96SmrgLispObj * 11895dfecf96SmrgLispCompileForm(LispObj *form) 11905dfecf96Smrg{ 11915dfecf96Smrg GC_ENTER(); 11925dfecf96Smrg int failed; 11935dfecf96Smrg LispCom com; 11945dfecf96Smrg 11955dfecf96Smrg if (!CONSP(form)) 11965dfecf96Smrg /* Incorrect call or NIL */ 11975dfecf96Smrg return (form); 11985dfecf96Smrg 11995dfecf96Smrg memset(&com, 0, sizeof(LispCom)); 12005dfecf96Smrg 12015dfecf96Smrg com.toplevel = com.block = LispCalloc(1, sizeof(CodeBlock)); 12025dfecf96Smrg com.block->type = LispBlockNone; 12035dfecf96Smrg com.lex = lisp__data.env.lex; 12045dfecf96Smrg 12055dfecf96Smrg com.plist = CONS(NIL, NIL); 12065dfecf96Smrg GC_PROTECT(com.plist); 12075dfecf96Smrg 12085dfecf96Smrg failed = 1; 12095dfecf96Smrg if (setjmp(com.jmp) == 0) { 12105dfecf96Smrg for (; CONSP(form); form = CDR(form)) { 12115dfecf96Smrg com.form = form; 12125dfecf96Smrg ComEval(&com, CAR(form)); 12135dfecf96Smrg } 12145dfecf96Smrg failed = 0; 12155dfecf96Smrg } 12165dfecf96Smrg GC_LEAVE(); 12175dfecf96Smrg 12185dfecf96Smrg return (failed ? NIL : MakeBytecodeObject(&com, NIL, NIL)); 12195dfecf96Smrg} 12205dfecf96Smrg 12215dfecf96SmrgLispObj * 12225dfecf96SmrgLispExecuteBytecode(LispObj *object) 12235dfecf96Smrg{ 12245dfecf96Smrg if (!BYTECODEP(object)) 12255dfecf96Smrg return (EVAL(object)); 12265dfecf96Smrg 12275dfecf96Smrg return (ExecuteBytecode(object->data.bytecode.bytecode->code)); 12285dfecf96Smrg} 12295dfecf96Smrg 12305dfecf96Smrgstatic LispObj * 12315dfecf96SmrgMakeBytecodeObject(LispCom *com, LispObj *name, LispObj *plist) 12325dfecf96Smrg{ 12335dfecf96Smrg LispObj *object; 12345dfecf96Smrg LispBytecode *bytecode; 12355dfecf96Smrg 12365dfecf96Smrg GC_ENTER(); 12375dfecf96Smrg unsigned char *stream; 12385dfecf96Smrg short i, num_constants; 12395dfecf96Smrg LispObj **constants, *code, *cons, *prev; 12405dfecf96Smrg 12415dfecf96Smrg /* Resolve dependencies, optimize and create byte stream */ 12425dfecf96Smrg LinkBytecode(com); 12435dfecf96Smrg 12445dfecf96Smrg object = LispNew(NIL, NIL); 12455dfecf96Smrg GC_PROTECT(object); 12465dfecf96Smrg bytecode = LispMalloc(sizeof(LispBytecode)); 12475dfecf96Smrg bytecode->code = com->bytecode; 12485dfecf96Smrg bytecode->length = com->length; 12495dfecf96Smrg 12505dfecf96Smrg 12515dfecf96Smrg stream = bytecode->code; 12525dfecf96Smrg 12535dfecf96Smrg /* Skip stack information */ 12545dfecf96Smrg stream += sizeof(short) * 3; 12555dfecf96Smrg 12565dfecf96Smrg /* Get information */ 12575dfecf96Smrg num_constants = *(short*)stream; 12585dfecf96Smrg stream += sizeof(short) * 4; 12595dfecf96Smrg constants = (LispObj**)stream; 12605dfecf96Smrg 12615dfecf96Smrg GC_PROTECT(plist); 12625dfecf96Smrg code = cons = prev = NIL; 12635dfecf96Smrg for (i = 0; i < num_constants; i++) { 12645dfecf96Smrg if (POINTERP(constants[i]) && !XSYMBOLP(constants[i])) { 12655dfecf96Smrg if (code == NIL) { 12665dfecf96Smrg code = cons = prev = CONS(constants[i], NIL); 12675dfecf96Smrg GC_PROTECT(code); 12685dfecf96Smrg } 12695dfecf96Smrg else { 12705dfecf96Smrg RPLACD(cons, CONS(constants[i], NIL)); 12715dfecf96Smrg prev = cons; 12725dfecf96Smrg cons = CDR(cons); 12735dfecf96Smrg } 12745dfecf96Smrg } 12755dfecf96Smrg } 12765dfecf96Smrg 12775dfecf96Smrg /* Protect this in case the function is redefined */ 12785dfecf96Smrg for (i = 0; i < com->table.num_bytecodes; i++) { 12795dfecf96Smrg if (code == NIL) { 12805dfecf96Smrg code = cons = prev = CONS(com->table.bytecodes[i], NIL); 12815dfecf96Smrg GC_PROTECT(code); 12825dfecf96Smrg } 12835dfecf96Smrg else { 12845dfecf96Smrg RPLACD(cons, CONS(com->table.bytecodes[i], NIL)); 12855dfecf96Smrg prev = cons; 12865dfecf96Smrg cons = CDR(cons); 12875dfecf96Smrg } 12885dfecf96Smrg } 12895dfecf96Smrg 12905dfecf96Smrg /* Free everything, but the LispCom structure and the generated bytecode */ 12915dfecf96Smrg CompileFreeState(com); 12925dfecf96Smrg 12935dfecf96Smrg /* Allocate the minimum required number of cons cells to protect objects */ 12945dfecf96Smrg if (!CONSP(code)) 12955dfecf96Smrg code = plist; 12965dfecf96Smrg else if (CONSP(plist)) { 12975dfecf96Smrg if (code == cons) 12985dfecf96Smrg RPLACD(code, plist); 12995dfecf96Smrg else 13005dfecf96Smrg RPLACD(cons, plist); 13015dfecf96Smrg } 13025dfecf96Smrg else { 13035dfecf96Smrg if (code == cons) 13045dfecf96Smrg code = CAR(code); 13055dfecf96Smrg else 13065dfecf96Smrg CDR(prev) = CAR(cons); 13075dfecf96Smrg } 13085dfecf96Smrg 13095dfecf96Smrg object->data.bytecode.bytecode = bytecode; 13105dfecf96Smrg /* Byte code references this object, so it cannot be garbage collected */ 13115dfecf96Smrg object->data.bytecode.code = code; 13125dfecf96Smrg object->data.bytecode.name = name; 13135dfecf96Smrg object->type = LispBytecode_t; 13145dfecf96Smrg 13155dfecf96Smrg LispMused(bytecode); 13165dfecf96Smrg LispMused(bytecode->code); 13175dfecf96Smrg GC_LEAVE(); 13185dfecf96Smrg 13195dfecf96Smrg return (object); 13205dfecf96Smrg} 13215dfecf96Smrg 13225dfecf96Smrgstatic void 13235dfecf96SmrgCompileFreeTree(CodeTree *tree) 13245dfecf96Smrg{ 13255dfecf96Smrg if (tree->type == CodeTreeBlock) 13265dfecf96Smrg CompileFreeBlock(tree->data.block); 13275dfecf96Smrg LispFree(tree); 13285dfecf96Smrg} 13295dfecf96Smrg 13305dfecf96Smrgstatic void 13315dfecf96SmrgCompileFreeBlock(CodeBlock *block) 13325dfecf96Smrg{ 13335dfecf96Smrg CodeTree *tree = block->tree, *next; 13345dfecf96Smrg 13355dfecf96Smrg while (tree) { 13365dfecf96Smrg next = tree->next; 13375dfecf96Smrg CompileFreeTree(tree); 13385dfecf96Smrg tree = next; 13395dfecf96Smrg } 13405dfecf96Smrg if (block->type == LispBlockBody) { 13415dfecf96Smrg LispFree(block->tagbody.labels); 13425dfecf96Smrg LispFree(block->tagbody.codes); 13435dfecf96Smrg } 13445dfecf96Smrg LispFree(block->variables.symbols); 13455dfecf96Smrg LispFree(block->variables.flags); 13465dfecf96Smrg LispFree(block); 13475dfecf96Smrg} 13485dfecf96Smrg 13495dfecf96Smrgstatic void 13505dfecf96SmrgCompileFreeState(LispCom *com) 13515dfecf96Smrg{ 13525dfecf96Smrg CompileFreeBlock(com->block); 13535dfecf96Smrg LispFree(com->table.constants); 13545dfecf96Smrg LispFree(com->table.symbols); 13555dfecf96Smrg LispFree(com->table.builtins); 13565dfecf96Smrg LispFree(com->table.bytecodes); 13575dfecf96Smrg} 13585dfecf96Smrg 13595dfecf96Smrg/* XXX Put a breakpoint here when changing the macro expansion code. 13605dfecf96Smrg * No opcodes should be generated during macro expansion. */ 13615dfecf96Smrgstatic CodeTree * 13625dfecf96SmrgCompileNewTree(LispCom *com, CodeTreeType type) 13635dfecf96Smrg{ 13645dfecf96Smrg CodeTree *tree = LispMalloc(sizeof(CodeTree)); 13655dfecf96Smrg 13665dfecf96Smrg tree->type = type; 13675dfecf96Smrg tree->next = NULL; 13685dfecf96Smrg tree->block = com->block; 13695dfecf96Smrg if (com->block->tree == NULL) 13705dfecf96Smrg com->block->tree = tree; 13715dfecf96Smrg else 13725dfecf96Smrg com->block->tail->next = tree; 13735dfecf96Smrg com->block->tail = tree; 13745dfecf96Smrg 13755dfecf96Smrg return (tree); 13765dfecf96Smrg} 13775dfecf96Smrg 13785dfecf96Smrgstatic void 13795dfecf96SmrgCompileIniBlock(LispCom *com, LispBlockType type, LispObj *tag) 13805dfecf96Smrg{ 13815dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBlock); 13825dfecf96Smrg CodeBlock *block = LispCalloc(1, sizeof(CodeBlock)); 13835dfecf96Smrg 13845dfecf96Smrg tree->data.block = block; 13855dfecf96Smrg 13865dfecf96Smrg block->type = type; 13875dfecf96Smrg block->tag = tag; 13885dfecf96Smrg block->prev = com->block; 13895dfecf96Smrg block->parent = tree; 13905dfecf96Smrg block->level = com->level; 13915dfecf96Smrg com->block = block; 13925dfecf96Smrg 13935dfecf96Smrg if (type == LispBlockBody) 13945dfecf96Smrg com->tagbody = com->level; 13955dfecf96Smrg} 13965dfecf96Smrg 13975dfecf96Smrgstatic void 13985dfecf96SmrgCompileFiniBlock(LispCom *com) 13995dfecf96Smrg{ 14005dfecf96Smrg com->block = com->block->prev; 14015dfecf96Smrg if (com->block && com->block->type == LispBlockBody) 14025dfecf96Smrg com->tagbody = com->block->level; 14035dfecf96Smrg} 14045dfecf96Smrg 14055dfecf96Smrgstatic void 14065dfecf96Smrgcom_BytecodeChar(LispCom *com, LispByteOpcode code, char value) 14075dfecf96Smrg{ 14085dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14095dfecf96Smrg 14105dfecf96Smrg tree->code = code; 14115dfecf96Smrg tree->data.signed_char = value; 14125dfecf96Smrg} 14135dfecf96Smrg 14145dfecf96Smrgstatic void 14155dfecf96Smrgcom_BytecodeShort(LispCom *com, LispByteOpcode code, short value) 14165dfecf96Smrg{ 14175dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14185dfecf96Smrg 14195dfecf96Smrg tree->code = code; 14205dfecf96Smrg tree->data.signed_short = value; 14215dfecf96Smrg} 14225dfecf96Smrg 14235dfecf96Smrgstatic void 14245dfecf96Smrgcom_BytecodeAtom(LispCom *com, LispByteOpcode code, LispAtom *atom) 14255dfecf96Smrg{ 14265dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14275dfecf96Smrg 14285dfecf96Smrg tree->code = code; 14295dfecf96Smrg tree->data.atom = atom; 14305dfecf96Smrg} 14315dfecf96Smrg 14325dfecf96Smrgstatic void 14335dfecf96Smrgcom_BytecodeObject(LispCom *com, LispByteOpcode code, LispObj *object) 14345dfecf96Smrg{ 14355dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14365dfecf96Smrg 14375dfecf96Smrg tree->code = code; 14385dfecf96Smrg tree->data.object = object; 14395dfecf96Smrg} 14405dfecf96Smrg 14415dfecf96Smrgstatic void 14425dfecf96Smrgcom_BytecodeCons(LispCom *com, LispByteOpcode code, LispObj *car, LispObj *cdr) 14435dfecf96Smrg{ 14445dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14455dfecf96Smrg 14465dfecf96Smrg tree->code = code; 14475dfecf96Smrg tree->data.cons.car = car; 14485dfecf96Smrg tree->data.cons.cdr = cdr; 14495dfecf96Smrg} 14505dfecf96Smrg 14515dfecf96Smrgstatic void 14525dfecf96Smrgcom_Bytecode(LispCom *com, LispByteOpcode code) 14535dfecf96Smrg{ 14545dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14555dfecf96Smrg 14565dfecf96Smrg tree->code = code; 14575dfecf96Smrg} 14585dfecf96Smrg 14595dfecf96Smrgstatic void 14605dfecf96Smrgcom_Load(LispCom *com, short offset) 14615dfecf96Smrg{ 14625dfecf96Smrg com_BytecodeShort(com, XBC_LOAD, offset); 14635dfecf96Smrg} 14645dfecf96Smrg 14655dfecf96Smrgstatic void 14665dfecf96Smrgcom_LoadLet(LispCom *com, short offset, LispAtom *name) 14675dfecf96Smrg{ 14685dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14695dfecf96Smrg 14705dfecf96Smrg tree->code = XBC_LOAD_LET; 14715dfecf96Smrg tree->data.let.offset = offset; 14725dfecf96Smrg tree->data.let.name = name; 14735dfecf96Smrg} 14745dfecf96Smrg 14755dfecf96Smrgstatic void 14765dfecf96Smrgcom_LoadPush(LispCom *com, short offset) 14775dfecf96Smrg{ 14785dfecf96Smrg com_BytecodeShort(com, XBC_LOAD_PUSH, offset); 14795dfecf96Smrg} 14805dfecf96Smrg 14815dfecf96Smrgstatic void 14825dfecf96Smrgcom_Let(LispCom *com, LispAtom *name) 14835dfecf96Smrg{ 14845dfecf96Smrg com_BytecodeAtom(com, XBC_LET, name); 14855dfecf96Smrg} 14865dfecf96Smrg 14875dfecf96Smrgstatic void 14885dfecf96Smrgcom_Bind(LispCom *com, short count) 14895dfecf96Smrg{ 14905dfecf96Smrg if (count) 14915dfecf96Smrg com_BytecodeShort(com, XBC_LETBIND, count); 14925dfecf96Smrg} 14935dfecf96Smrg 14945dfecf96Smrgstatic void 14955dfecf96Smrgcom_Unbind(LispCom *com, short count) 14965dfecf96Smrg{ 14975dfecf96Smrg if (count) 14985dfecf96Smrg com_BytecodeShort(com, XBC_UNLET, count); 14995dfecf96Smrg} 15005dfecf96Smrg 15015dfecf96Smrgstatic void 15025dfecf96Smrgcom_LoadSym(LispCom *com, LispAtom *atom) 15035dfecf96Smrg{ 15045dfecf96Smrg com_BytecodeAtom(com, XBC_LOADSYM, atom); 15055dfecf96Smrg} 15065dfecf96Smrg 15075dfecf96Smrgstatic void 15085dfecf96Smrgcom_LoadSymLet(LispCom *com, LispAtom *symbol, LispAtom *name) 15095dfecf96Smrg{ 15105dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 15115dfecf96Smrg 15125dfecf96Smrg tree->code = XBC_LOADSYM_LET; 15135dfecf96Smrg tree->data.let_sym.symbol = symbol; 15145dfecf96Smrg tree->data.let_sym.name = name; 15155dfecf96Smrg} 15165dfecf96Smrg 15175dfecf96Smrgstatic void 15185dfecf96Smrgcom_LoadSymPush(LispCom *com, LispAtom *name) 15195dfecf96Smrg{ 15205dfecf96Smrg com_BytecodeAtom(com, XBC_LOADSYM_PUSH, name); 15215dfecf96Smrg} 15225dfecf96Smrg 15235dfecf96Smrgstatic void 15245dfecf96Smrgcom_LoadCon(LispCom *com, LispObj *constant) 15255dfecf96Smrg{ 15265dfecf96Smrg if (constant == NIL) 15275dfecf96Smrg com_Bytecode(com, XBC_NIL); 15285dfecf96Smrg else if (constant == T) 15295dfecf96Smrg com_Bytecode(com, XBC_T); 15305dfecf96Smrg else if (constant == UNSPEC) { 15315dfecf96Smrg COMPILE_FAILURE("internal error: loading #<UNSPEC>"); 15325dfecf96Smrg } 15335dfecf96Smrg else 15345dfecf96Smrg com_BytecodeObject(com, XBC_LOADCON, constant); 15355dfecf96Smrg} 15365dfecf96Smrg 15375dfecf96Smrgstatic void 15385dfecf96Smrgcom_LoadConLet(LispCom *com, LispObj *constant, LispAtom *name) 15395dfecf96Smrg{ 15405dfecf96Smrg if (constant == NIL) 15415dfecf96Smrg com_BytecodeAtom(com, XBC_LET_NIL, name); 15425dfecf96Smrg else { 15435dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 15445dfecf96Smrg 15455dfecf96Smrg tree->code = XBC_LOADCON_LET; 15465dfecf96Smrg tree->data.let_con.object = constant; 15475dfecf96Smrg tree->data.let_con.name = name; 15485dfecf96Smrg } 15495dfecf96Smrg} 15505dfecf96Smrg 15515dfecf96Smrgstatic void 15525dfecf96Smrgcom_LoadConPush(LispCom *com, LispObj *constant) 15535dfecf96Smrg{ 15545dfecf96Smrg if (constant == NIL) 15555dfecf96Smrg com_Bytecode(com, XBC_PUSH_NIL); 15565dfecf96Smrg else if (constant == T) 15575dfecf96Smrg com_Bytecode(com, XBC_PUSH_T); 15585dfecf96Smrg else if (constant == UNSPEC) 15595dfecf96Smrg com_Bytecode(com, XBC_PUSH_UNSPEC); 15605dfecf96Smrg else 15615dfecf96Smrg com_BytecodeObject(com, XBC_LOADCON_PUSH, constant); 15625dfecf96Smrg} 15635dfecf96Smrg 15645dfecf96Smrgstatic void 15655dfecf96Smrgcom_Set(LispCom *com, short offset) 15665dfecf96Smrg{ 15675dfecf96Smrg com_BytecodeShort(com, XBC_SET, offset); 15685dfecf96Smrg} 15695dfecf96Smrg 15705dfecf96Smrgstatic void 15715dfecf96Smrgcom_SetSym(LispCom *com, LispAtom *symbol) 15725dfecf96Smrg{ 15735dfecf96Smrg com_BytecodeAtom(com, XBC_SETSYM, symbol); 15745dfecf96Smrg} 15755dfecf96Smrg 15765dfecf96Smrgstatic void 15775dfecf96Smrgcom_Struct(LispCom *com, short offset, LispObj *definition) 15785dfecf96Smrg{ 15795dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 15805dfecf96Smrg 15815dfecf96Smrg tree->code = XBC_STRUCT; 15825dfecf96Smrg tree->data.struc.offset = offset; 15835dfecf96Smrg tree->data.struc.definition = definition; 15845dfecf96Smrg} 15855dfecf96Smrg 15865dfecf96Smrgstatic void 15875dfecf96Smrgcom_Structp(LispCom *com, LispObj *definition) 15885dfecf96Smrg{ 15895dfecf96Smrg com_BytecodeObject(com, XBC_STRUCTP, definition); 15905dfecf96Smrg} 15915dfecf96Smrg 15925dfecf96Smrgstatic void 15935dfecf96Smrgcom_Call(LispCom *com, unsigned char num_arguments, LispBuiltin *builtin) 15945dfecf96Smrg{ 15955dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 15965dfecf96Smrg 15975dfecf96Smrg tree->code = XBC_CALL; 15985dfecf96Smrg tree->data.builtin.num_arguments = num_arguments; 15995dfecf96Smrg tree->data.builtin.builtin = builtin; 16005dfecf96Smrg} 16015dfecf96Smrg 16025dfecf96Smrgstatic void 16035dfecf96Smrgcom_Bytecall(LispCom *com, unsigned char num_arguments, LispObj *code) 16045dfecf96Smrg{ 16055dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 16065dfecf96Smrg 16075dfecf96Smrg tree->code = XBC_BYTECALL; 16085dfecf96Smrg tree->data.bytecall.num_arguments = num_arguments; 16095dfecf96Smrg tree->data.bytecall.code = code; 16105dfecf96Smrg} 16115dfecf96Smrg 16125dfecf96Smrgstatic void 16135dfecf96Smrgcom_Funcall(LispCom *com, LispObj *function, LispObj *arguments) 16145dfecf96Smrg{ 16155dfecf96Smrg com_BytecodeCons(com, XBC_FUNCALL, function, arguments); 16165dfecf96Smrg} 16175dfecf96Smrg 16185dfecf96Smrgstatic void 16195dfecf96SmrgCompileStackEnter(LispCom *com, int count, int builtin) 16205dfecf96Smrg{ 16215dfecf96Smrg if (!com->macro) { 16225dfecf96Smrg if (builtin) { 16235dfecf96Smrg com->stack.cbstack += count; 16245dfecf96Smrg if (com->stack.bstack < com->stack.cbstack) 16255dfecf96Smrg com->stack.bstack = com->stack.cbstack; 16265dfecf96Smrg } 16275dfecf96Smrg else { 16285dfecf96Smrg com->stack.cstack += count; 16295dfecf96Smrg if (com->stack.stack < com->stack.cstack) 16305dfecf96Smrg com->stack.stack = com->stack.cstack; 16315dfecf96Smrg } 16325dfecf96Smrg } 16335dfecf96Smrg} 16345dfecf96Smrg 16355dfecf96Smrgstatic void 16365dfecf96SmrgCompileStackLeave(LispCom *com, int count, int builtin) 16375dfecf96Smrg{ 16385dfecf96Smrg if (!com->macro) { 16395dfecf96Smrg if (builtin) 16405dfecf96Smrg com->stack.cbstack -= count; 16415dfecf96Smrg else 16425dfecf96Smrg com->stack.cstack -= count; 16435dfecf96Smrg } 16445dfecf96Smrg} 16455dfecf96Smrg 16465dfecf96Smrgstatic void 16475dfecf96SmrgLinkWarnUnused(LispCom *com, CodeBlock *block) 16485dfecf96Smrg{ 16495dfecf96Smrg int i; 16505dfecf96Smrg CodeTree *tree; 16515dfecf96Smrg 16525dfecf96Smrg for (tree = block->tree; tree; tree = tree->next) { 16535dfecf96Smrg if (tree->type == CodeTreeBlock) 16545dfecf96Smrg LinkWarnUnused(com, tree->data.block); 16555dfecf96Smrg } 16565dfecf96Smrg 16575dfecf96Smrg for (i = 0; i < block->variables.length; i++) 16585dfecf96Smrg if (!(block->variables.flags[i] & (VARIABLE_USED | VARIABLE_ARGUMENT))) { 16595dfecf96Smrg ++com->warnings; 16605dfecf96Smrg LispWarning("the variable %s is unused", 16615dfecf96Smrg block->variables.symbols[i]->string); 16625dfecf96Smrg } 16635dfecf96Smrg} 16645dfecf96Smrg 16655dfecf96Smrg#define INTERNAL_ERROR_STRING "COMPILE: internal error #%d" 16665dfecf96Smrg#define INTERNAL_ERROR(value) LispDestroy(INTERNAL_ERROR_STRING, value) 16675dfecf96Smrgstatic long 16685dfecf96SmrgLinkBuildOffsets(LispCom *com, CodeTree *tree, long offset) 16695dfecf96Smrg{ 16705dfecf96Smrg for (; tree; tree = tree->next) { 16715dfecf96Smrg tree->offset = offset; 16725dfecf96Smrg switch (tree->type) { 16735dfecf96Smrg case CodeTreeBytecode: 16745dfecf96Smrg switch (tree->code) { 16755dfecf96Smrg case XBC_NOOP: 16765dfecf96Smrg INTERNAL_ERROR(__LINE__); 16775dfecf96Smrg break; 16785dfecf96Smrg 16795dfecf96Smrg /* byte */ 16805dfecf96Smrg case XBC_BCONS: 16815dfecf96Smrg case XBC_BCONS1: 16825dfecf96Smrg case XBC_BCONS2: 16835dfecf96Smrg case XBC_BCONS3: 16845dfecf96Smrg case XBC_BCONS4: 16855dfecf96Smrg case XBC_BCONS5: 16865dfecf96Smrg case XBC_BCONS6: 16875dfecf96Smrg case XBC_BCONS7: 16885dfecf96Smrg case XBC_INV: 16895dfecf96Smrg case XBC_NIL: 16905dfecf96Smrg case XBC_T: 16915dfecf96Smrg case XBC_PUSH: 16925dfecf96Smrg case XBC_CAR_PUSH: 16935dfecf96Smrg case XBC_CDR_PUSH: 16945dfecf96Smrg case XBC_PUSH_NIL: 16955dfecf96Smrg case XBC_PUSH_UNSPEC: 16965dfecf96Smrg case XBC_PUSH_T: 16975dfecf96Smrg case XBC_LSTAR: 16985dfecf96Smrg case XBC_LCONS: 16995dfecf96Smrg case XBC_LFINI: 17005dfecf96Smrg case XBC_RETURN: 17015dfecf96Smrg case XBC_CSTAR: 17025dfecf96Smrg case XBC_CFINI: 17035dfecf96Smrg case XBC_CAR: 17045dfecf96Smrg case XBC_CDR: 17055dfecf96Smrg case XBC_RPLACA: 17065dfecf96Smrg case XBC_RPLACD: 17075dfecf96Smrg case XBC_EQ: 17085dfecf96Smrg case XBC_EQL: 17095dfecf96Smrg case XBC_EQUAL: 17105dfecf96Smrg case XBC_EQUALP: 17115dfecf96Smrg case XBC_LENGTH: 17125dfecf96Smrg case XBC_LAST: 17135dfecf96Smrg case XBC_NTHCDR: 17145dfecf96Smrg ++offset; 17155dfecf96Smrg break; 17165dfecf96Smrg 17175dfecf96Smrg /* byte + byte */ 17185dfecf96Smrg case XBC_PUSH_NIL_N: 17195dfecf96Smrg case XBC_PUSH_UNSPEC_N: 17205dfecf96Smrg case XBC_PRED: 17215dfecf96Smrg case XBC_LETREC: 17225dfecf96Smrg case XBC_LOAD_PUSH: 17235dfecf96Smrg case XBC_CAR_SET: 17245dfecf96Smrg case XBC_CDR_SET: 17255dfecf96Smrg case XBC_SET: 17265dfecf96Smrg case XBC_SET_NIL: 17275dfecf96Smrg case XBC_LETBIND: 17285dfecf96Smrg case XBC_UNLET: 17295dfecf96Smrg case XBC_LOAD: 17305dfecf96Smrg case XBC_LOAD_CAR: 17315dfecf96Smrg case XBC_LOAD_CDR: 17325dfecf96Smrg case XBC_LOAD_CAR_STORE: 17335dfecf96Smrg case XBC_LOAD_CDR_STORE: 17345dfecf96Smrg case XBC_LET: 17355dfecf96Smrg case XBC_LETX: 17365dfecf96Smrg case XBC_LET_NIL: 17375dfecf96Smrg case XBC_LETX_NIL: 17385dfecf96Smrg case XBC_STRUCTP: 17395dfecf96Smrg case XBC_SETSYM: 17405dfecf96Smrg case XBC_LOADCON_PUSH: 17415dfecf96Smrg case XBC_LOADSYM_PUSH: 17425dfecf96Smrg case XBC_LOADCON: 17435dfecf96Smrg case XBC_LOADSYM: 17445dfecf96Smrg offset += 2; 17455dfecf96Smrg break; 17465dfecf96Smrg 17475dfecf96Smrg /* byte + byte + byte */ 17485dfecf96Smrg case XBC_CALL: 17495dfecf96Smrg case XBC_BYTECALL: 17505dfecf96Smrg case XBC_LOAD_SET: 17515dfecf96Smrg case XBC_LOAD_CAR_SET: 17525dfecf96Smrg case XBC_LOAD_CDR_SET: 17535dfecf96Smrg case XBC_LOADCON_SET: 17545dfecf96Smrg case XBC_LOAD_LET: 17555dfecf96Smrg case XBC_LOAD_LETX: 17565dfecf96Smrg case XBC_STRUCT: 17575dfecf96Smrg case XBC_LOADCON_LET: 17585dfecf96Smrg case XBC_LOADCON_LETX: 17595dfecf96Smrg case XBC_LOADSYM_LET: 17605dfecf96Smrg case XBC_LOADSYM_LETX: 17615dfecf96Smrg case XBC_CCONS: 17625dfecf96Smrg case XBC_FUNCALL: 17635dfecf96Smrg offset += 3; 17645dfecf96Smrg break; 17655dfecf96Smrg 17665dfecf96Smrg /* byte + short */ 17675dfecf96Smrg case XBC_JUMP: 17685dfecf96Smrg case XBC_JUMPT: 17695dfecf96Smrg case XBC_JUMPNIL: 17705dfecf96Smrg /* XXX this is likely a jump to random address here */ 17715dfecf96Smrg INTERNAL_ERROR(__LINE__); 17725dfecf96Smrg offset += sizeof(short) + 1; 17735dfecf96Smrg break; 17745dfecf96Smrg 17755dfecf96Smrg /* byte + byte + byte + byte */ 17765dfecf96Smrg case XBC_CALL_SET: 17775dfecf96Smrg offset += 4; 17785dfecf96Smrg break; 17795dfecf96Smrg } 17805dfecf96Smrg break; 17815dfecf96Smrg case CodeTreeLabel: 17825dfecf96Smrg /* Labels are not loaded */ 17835dfecf96Smrg break; 17845dfecf96Smrg case CodeTreeJump: 17855dfecf96Smrg case CodeTreeJumpIf: 17865dfecf96Smrg case CodeTreeCond: 17875dfecf96Smrg /* If not the point where the conditional block finishes */ 17885dfecf96Smrg if (tree->code != XBC_NOOP) 17895dfecf96Smrg /* Reserve space for the jump opcode */ 17905dfecf96Smrg offset += sizeof(short) + 1; 17915dfecf96Smrg break; 17925dfecf96Smrg case CodeTreeGo: 17935dfecf96Smrg case CodeTreeReturn: 17945dfecf96Smrg /* Reserve space for the jump opcode */ 17955dfecf96Smrg offset += sizeof(short) + 1; 17965dfecf96Smrg break; 17975dfecf96Smrg case CodeTreeBlock: 17985dfecf96Smrg offset = LinkBuildOffsets(com, tree->data.block->tree, offset); 17995dfecf96Smrg break; 18005dfecf96Smrg } 18015dfecf96Smrg } 18025dfecf96Smrg 18035dfecf96Smrg return (offset); 18045dfecf96Smrg} 18055dfecf96Smrg 18065dfecf96Smrgstatic void 18075dfecf96SmrgLinkDoOptimize_0(LispCom *com, CodeBlock *block) 18085dfecf96Smrg{ 18095dfecf96Smrg CodeTree *tree, *prev, *next; 18105dfecf96Smrg 18115dfecf96Smrg /* Remove redundant or join opcodes that can be joined. Do it here 18125dfecf96Smrg * because some of these are hard to detect earlier, and/or would 18135dfecf96Smrg * require a lot of duplicated code or more time. */ 18145dfecf96Smrg tree = prev = block->tree; 18155dfecf96Smrg while (tree) { 18165dfecf96Smrg next = tree->next; 18175dfecf96Smrg 18185dfecf96Smrg /* LET -> LET* */ 18195dfecf96Smrg if (next && 18205dfecf96Smrg next->type == CodeTreeBytecode && 18215dfecf96Smrg next->code == XBC_LETBIND && 18225dfecf96Smrg next->data.signed_short == 1) { 18235dfecf96Smrg switch (tree->code) { 18245dfecf96Smrg case XBC_LET: 18255dfecf96Smrg tree->code = XBC_LETX; 18265dfecf96Smrg goto remove_next_label; 18275dfecf96Smrg case XBC_LET_NIL: 18285dfecf96Smrg tree->code = XBC_LETX_NIL; 18295dfecf96Smrg goto remove_next_label; 18305dfecf96Smrg case XBC_LOAD_LET: 18315dfecf96Smrg tree->code = XBC_LOAD_LETX; 18325dfecf96Smrg goto remove_next_label; 18335dfecf96Smrg case XBC_LOADCON_LET: 18345dfecf96Smrg tree->code = XBC_LOADCON_LETX; 18355dfecf96Smrg goto remove_next_label; 18365dfecf96Smrg case XBC_LOADSYM_LET: 18375dfecf96Smrg tree->code = XBC_LOADSYM_LETX; 18385dfecf96Smrg goto remove_next_label; 18395dfecf96Smrg default: 18405dfecf96Smrg break; 18415dfecf96Smrg } 18425dfecf96Smrg } 18435dfecf96Smrg 18445dfecf96Smrg switch (tree->type) { 18455dfecf96Smrg case CodeTreeBytecode: 18465dfecf96Smrg switch (tree->code) { 18475dfecf96Smrg case XBC_LOADCON: 18485dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 18495dfecf96Smrg switch (next->code) { 18505dfecf96Smrg case XBC_LET: 18515dfecf96Smrg next->code = XBC_LOADCON_LET; 18525dfecf96Smrg next->data.let_con.name = 18535dfecf96Smrg next->data.atom; 18545dfecf96Smrg next->data.let_con.object = 18555dfecf96Smrg tree->data.object; 18565dfecf96Smrg goto remove_label; 18575dfecf96Smrg case XBC_PUSH: 18585dfecf96Smrg next->code = XBC_LOADCON_PUSH; 18595dfecf96Smrg next->data.object = tree->data.object; 18605dfecf96Smrg goto remove_label; 18615dfecf96Smrg case XBC_CAR: 18625dfecf96Smrg if (tree->data.object != NIL) { 18635dfecf96Smrg if (!CONSP(tree->data.object)) 18645dfecf96Smrg LispDestroy("CAR: %s is not a list", 18655dfecf96Smrg STROBJ( 18665dfecf96Smrg tree->data.object)); 18675dfecf96Smrg next->code = XBC_LOADCON; 18685dfecf96Smrg next->data.object = 18695dfecf96Smrg CAR(tree->data.object); 18705dfecf96Smrg } 18715dfecf96Smrg goto remove_label; 18725dfecf96Smrg case XBC_CDR: 18735dfecf96Smrg if (tree->data.object != NIL) { 18745dfecf96Smrg if (!CONSP(tree->data.object)) 18755dfecf96Smrg LispDestroy("CAR: %s is not a list", 18765dfecf96Smrg STROBJ( 18775dfecf96Smrg tree->data.object)); 18785dfecf96Smrg next->code = XBC_LOADCON; 18795dfecf96Smrg next->data.object = 18805dfecf96Smrg CDR(tree->data.object); 18815dfecf96Smrg } 18825dfecf96Smrg goto remove_label; 18835dfecf96Smrg case XBC_SET: 18845dfecf96Smrg next->code = XBC_LOADCON_SET; 18855dfecf96Smrg next->data.load_con_set.offset = 18865dfecf96Smrg next->data.signed_short; 18875dfecf96Smrg next->data.load_con_set.object = 18885dfecf96Smrg tree->data.object; 18895dfecf96Smrg goto remove_label; 18905dfecf96Smrg default: 18915dfecf96Smrg break; 18925dfecf96Smrg } 18935dfecf96Smrg } 18945dfecf96Smrg break; 18955dfecf96Smrg case XBC_LOADSYM: 18965dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 18975dfecf96Smrg switch (next->code) { 18985dfecf96Smrg case XBC_LET: 18995dfecf96Smrg next->code = XBC_LOADSYM_LET; 19005dfecf96Smrg next->data.let_sym.name = 19015dfecf96Smrg next->data.atom; 19025dfecf96Smrg next->data.let_sym.symbol = 19035dfecf96Smrg tree->data.atom; 19045dfecf96Smrg goto remove_label; 19055dfecf96Smrg case XBC_PUSH: 19065dfecf96Smrg next->code = XBC_LOADSYM_PUSH; 19075dfecf96Smrg next->data.atom = tree->data.atom; 19085dfecf96Smrg goto remove_label; 19095dfecf96Smrg default: 19105dfecf96Smrg break; 19115dfecf96Smrg } 19125dfecf96Smrg } 19135dfecf96Smrg break; 19145dfecf96Smrg case XBC_LOAD: 19155dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 19165dfecf96Smrg switch (next->code) { 19175dfecf96Smrg case XBC_SET: 19185dfecf96Smrg next->code = XBC_LOAD_SET; 19195dfecf96Smrg next->data.load_set.set = 19205dfecf96Smrg next->data.signed_short; 19215dfecf96Smrg next->data.load_set.load = 19225dfecf96Smrg tree->data.signed_short; 19235dfecf96Smrg goto remove_label; 19245dfecf96Smrg /* TODO add XBC_LOAD_SETSYM */ 19255dfecf96Smrg case XBC_CAR: 19265dfecf96Smrg next->code = XBC_LOAD_CAR; 19275dfecf96Smrg next->data.signed_short = 19285dfecf96Smrg tree->data.signed_short; 19295dfecf96Smrg goto remove_label; 19305dfecf96Smrg case XBC_CDR: 19315dfecf96Smrg next->code = XBC_LOAD_CDR; 19325dfecf96Smrg next->data.signed_short = 19335dfecf96Smrg tree->data.signed_short; 19345dfecf96Smrg goto remove_label; 19355dfecf96Smrg case XBC_PUSH: 19365dfecf96Smrg tree->code = XBC_LOAD_PUSH; 19375dfecf96Smrg goto remove_next_label; 19385dfecf96Smrg case XBC_LET: 19395dfecf96Smrg next->code = XBC_LOAD_LET; 19405dfecf96Smrg next->data.let.name = next->data.atom; 19415dfecf96Smrg next->data.let.offset = 19425dfecf96Smrg tree->data.signed_short; 19435dfecf96Smrg goto remove_label; 19445dfecf96Smrg default: 19455dfecf96Smrg break; 19465dfecf96Smrg } 19475dfecf96Smrg } 19485dfecf96Smrg break; 19495dfecf96Smrg case XBC_LOAD_CAR: 19505dfecf96Smrg if (next && next->type == CodeTreeBytecode && 19515dfecf96Smrg next->code == XBC_SET) { 19525dfecf96Smrg if (next->data.signed_short == 19535dfecf96Smrg tree->data.signed_short) 19545dfecf96Smrg next->code = XBC_LOAD_CAR_STORE; 19555dfecf96Smrg else { 19565dfecf96Smrg next->code = XBC_LOAD_CAR_SET; 19575dfecf96Smrg next->data.load_set.set = 19585dfecf96Smrg next->data.signed_short; 19595dfecf96Smrg next->data.load_set.load = 19605dfecf96Smrg tree->data.signed_short; 19615dfecf96Smrg } 19625dfecf96Smrg goto remove_label; 19635dfecf96Smrg } 19645dfecf96Smrg break; 19655dfecf96Smrg case XBC_LOAD_CDR: 19665dfecf96Smrg if (next && next->type == CodeTreeBytecode && 19675dfecf96Smrg next->code == XBC_SET) { 19685dfecf96Smrg if (next->data.signed_short == 19695dfecf96Smrg tree->data.signed_short) 19705dfecf96Smrg next->code = XBC_LOAD_CDR_STORE; 19715dfecf96Smrg else { 19725dfecf96Smrg next->code = XBC_LOAD_CDR_SET; 19735dfecf96Smrg next->data.load_set.set = 19745dfecf96Smrg next->data.signed_short; 19755dfecf96Smrg next->data.load_set.load = 19765dfecf96Smrg tree->data.signed_short; 19775dfecf96Smrg } 19785dfecf96Smrg goto remove_label; 19795dfecf96Smrg } 19805dfecf96Smrg break; 19815dfecf96Smrg case XBC_CALL: 19825dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 19835dfecf96Smrg switch (next->code) { 19845dfecf96Smrg case XBC_SET: 19855dfecf96Smrg next->code = XBC_CALL_SET; 19865dfecf96Smrg next->data.builtin.offset = 19875dfecf96Smrg next->data.signed_short; 19885dfecf96Smrg next->data.builtin.num_arguments = 19895dfecf96Smrg tree->data.builtin.num_arguments; 19905dfecf96Smrg next->data.builtin.builtin = 19915dfecf96Smrg tree->data.builtin.builtin; 19925dfecf96Smrg goto remove_label; 19935dfecf96Smrg /* TODO add XBC_CALL_SETSYM */ 19945dfecf96Smrg default: 19955dfecf96Smrg break; 19965dfecf96Smrg } 19975dfecf96Smrg } 19985dfecf96Smrg break; 19995dfecf96Smrg case XBC_CAR: 20005dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 20015dfecf96Smrg switch (next->code) { 20025dfecf96Smrg case XBC_SET: 20035dfecf96Smrg next->code = XBC_CAR_SET; 20045dfecf96Smrg goto remove_label; 20055dfecf96Smrg /* TODO add XBC_CAR_SETSYM */ 20065dfecf96Smrg case XBC_PUSH: 20075dfecf96Smrg next->code = XBC_CAR_PUSH; 20085dfecf96Smrg goto remove_label; 20095dfecf96Smrg default: 20105dfecf96Smrg break; 20115dfecf96Smrg } 20125dfecf96Smrg } 20135dfecf96Smrg break; 20145dfecf96Smrg case XBC_CDR: 20155dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 20165dfecf96Smrg switch (next->code) { 20175dfecf96Smrg case XBC_SET: 20185dfecf96Smrg next->code = XBC_CDR_SET; 20195dfecf96Smrg goto remove_label; 20205dfecf96Smrg /* TODO add XBC_CDR_SETSYM */ 20215dfecf96Smrg case XBC_PUSH: 20225dfecf96Smrg next->code = XBC_CDR_PUSH; 20235dfecf96Smrg goto remove_label; 20245dfecf96Smrg default: 20255dfecf96Smrg break; 20265dfecf96Smrg } 20275dfecf96Smrg } 20285dfecf96Smrg break; 20295dfecf96Smrg case XBC_NIL: 20305dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 20315dfecf96Smrg switch (next->code) { 20325dfecf96Smrg case XBC_SET: 20335dfecf96Smrg next->code = XBC_SET_NIL; 20345dfecf96Smrg goto remove_label; 20355dfecf96Smrg /* TODO add XBC_SETSYM_NIL */ 20365dfecf96Smrg default: 20375dfecf96Smrg break; 20385dfecf96Smrg } 20395dfecf96Smrg } 20405dfecf96Smrg break; 20415dfecf96Smrg case XBC_PUSH_NIL: 20425dfecf96Smrg if (next && next->type == CodeTreeBytecode && 20435dfecf96Smrg next->code == XBC_PUSH_NIL) { 20445dfecf96Smrg next->code = XBC_PUSH_NIL_N; 20455dfecf96Smrg next->data.signed_char = 2; 20465dfecf96Smrg goto remove_label; 20475dfecf96Smrg } 20485dfecf96Smrg break; 20495dfecf96Smrg case XBC_PUSH_NIL_N: 20505dfecf96Smrg if (next && next->type == CodeTreeBytecode && 20515dfecf96Smrg next->code == XBC_PUSH_NIL) { 20525dfecf96Smrg next->code = XBC_PUSH_NIL_N; 20535dfecf96Smrg next->data.signed_char = tree->data.signed_char + 1; 20545dfecf96Smrg goto remove_label; 20555dfecf96Smrg } 20565dfecf96Smrg break; 20575dfecf96Smrg case XBC_PUSH_UNSPEC: 20585dfecf96Smrg if (next && next->type == CodeTreeBytecode && 20595dfecf96Smrg next->code == XBC_PUSH_UNSPEC) { 20605dfecf96Smrg next->code = XBC_PUSH_UNSPEC_N; 20615dfecf96Smrg next->data.signed_char = 2; 20625dfecf96Smrg goto remove_label; 20635dfecf96Smrg } 20645dfecf96Smrg break; 20655dfecf96Smrg case XBC_PUSH_UNSPEC_N: 20665dfecf96Smrg if (next && next->type == CodeTreeBytecode && 20675dfecf96Smrg next->code == XBC_PUSH_UNSPEC) { 20685dfecf96Smrg next->code = XBC_PUSH_UNSPEC_N; 20695dfecf96Smrg next->data.signed_char = tree->data.signed_char + 1; 20705dfecf96Smrg goto remove_label; 20715dfecf96Smrg } 20725dfecf96Smrg break; 20735dfecf96Smrg default: 20745dfecf96Smrg break; 20755dfecf96Smrg } 20765dfecf96Smrg break; 20775dfecf96Smrg case CodeTreeBlock: 20785dfecf96Smrg LinkDoOptimize_0(com, tree->data.block); 20795dfecf96Smrg break; 20805dfecf96Smrg default: 20815dfecf96Smrg break; 20825dfecf96Smrg } 20835dfecf96Smrg goto update_label; 20845dfecf96Smrgremove_label: 20855dfecf96Smrg if (tree == block->tree) { 20865dfecf96Smrg block->tree = prev = next; 20875dfecf96Smrg if (tree == block->tail) 20885dfecf96Smrg block->tail = tree; 20895dfecf96Smrg } 20905dfecf96Smrg else 20915dfecf96Smrg prev->next = next; 20925dfecf96Smrg CompileFreeTree(tree); 20935dfecf96Smrg tree = next; 20945dfecf96Smrg continue; 20955dfecf96Smrgremove_next_label: 20965dfecf96Smrg tree->next = next->next; 20975dfecf96Smrg CompileFreeTree(next); 20985dfecf96Smrg continue; 20995dfecf96Smrgupdate_label: 21005dfecf96Smrg prev = tree; 21015dfecf96Smrg tree = tree->next; 21025dfecf96Smrg } 21035dfecf96Smrg} 21045dfecf96Smrg 21055dfecf96Smrgstatic void 21065dfecf96SmrgLinkOptimize_0(LispCom *com) 21075dfecf96Smrg{ 21085dfecf96Smrg /* Recursive */ 21095dfecf96Smrg LinkDoOptimize_0(com, com->block); 21105dfecf96Smrg} 21115dfecf96Smrg 21125dfecf96Smrgstatic void 21135dfecf96SmrgLinkResolveLabels(LispCom *com, CodeBlock *block) 21145dfecf96Smrg{ 21155dfecf96Smrg int i; 21165dfecf96Smrg CodeTree *tree = block->tree; 21175dfecf96Smrg 21185dfecf96Smrg for (; tree; tree = tree->next) { 21195dfecf96Smrg if (tree->type == CodeTreeBlock) 21205dfecf96Smrg LinkResolveLabels(com, tree->data.block); 21215dfecf96Smrg else if (tree->type == CodeTreeLabel) { 21225dfecf96Smrg for (i = 0; i < block->tagbody.length; i++) 21235dfecf96Smrg if (tree->data.object == block->tagbody.labels[i]) { 21245dfecf96Smrg block->tagbody.codes[i] = tree; 21255dfecf96Smrg break; 21265dfecf96Smrg } 21275dfecf96Smrg } 21285dfecf96Smrg } 21295dfecf96Smrg} 21305dfecf96Smrg 21315dfecf96Smrgstatic void 21325dfecf96SmrgLinkResolveJumps(LispCom *com, CodeBlock *block) 21335dfecf96Smrg{ 21345dfecf96Smrg int i; 21355dfecf96Smrg CodeBlock *body = block; 21365dfecf96Smrg CodeTree *ptr, *tree = block->tree; 21375dfecf96Smrg 21385dfecf96Smrg /* Check if there is a tagbody. Error checking already done */ 21395dfecf96Smrg while (body && body->type != LispBlockBody) 21405dfecf96Smrg body = body->prev; 21415dfecf96Smrg 21425dfecf96Smrg for (; tree; tree = tree->next) { 21435dfecf96Smrg switch (tree->type) { 21445dfecf96Smrg case CodeTreeBytecode: 21455dfecf96Smrg case CodeTreeLabel: 21465dfecf96Smrg break; 21475dfecf96Smrg 21485dfecf96Smrg case CodeTreeBlock: 21495dfecf96Smrg LinkResolveJumps(com, tree->data.block); 21505dfecf96Smrg break; 21515dfecf96Smrg 21525dfecf96Smrg case CodeTreeGo: 21535dfecf96Smrg for (i = 0; i < body->tagbody.length; i++) 21545dfecf96Smrg if (tree->data.object == body->tagbody.labels[i]) 21555dfecf96Smrg break; 21565dfecf96Smrg if (i == body->tagbody.length) 21575dfecf96Smrg LispDestroy("COMPILE: no visible tag %s to GO", 21585dfecf96Smrg STROBJ(tree->data.object)); 21595dfecf96Smrg /* Now the jump code is known */ 21605dfecf96Smrg tree->data.tree = body->tagbody.codes[i]; 21615dfecf96Smrg break; 21625dfecf96Smrg 21635dfecf96Smrg case CodeTreeCond: 21645dfecf96Smrg if (tree->code == XBC_JUMPNIL) 21655dfecf96Smrg /* If test is NIL, go to next test */ 21665dfecf96Smrg tree->data.tree = tree->group->next; 21675dfecf96Smrg else if (tree->code == XBC_JUMPT) { 21685dfecf96Smrg /* After executing code, test was T */ 21695dfecf96Smrg for (ptr = tree->group; 21705dfecf96Smrg ptr->code != XBC_NOOP; 21715dfecf96Smrg ptr = ptr->group) 21725dfecf96Smrg ; 21735dfecf96Smrg tree->data.tree = ptr; 21745dfecf96Smrg } 21755dfecf96Smrg break; 21765dfecf96Smrg 21775dfecf96Smrg case CodeTreeJumpIf: 21785dfecf96Smrg if (tree->code != XBC_NOOP) { 21795dfecf96Smrg for (ptr = tree->group; 21805dfecf96Smrg ptr->code != XBC_NOOP; 21815dfecf96Smrg ptr = ptr->group) { 21825dfecf96Smrg if (ptr->type == CodeTreeJump) { 21835dfecf96Smrg /* ELSE code of IF */ 21845dfecf96Smrg ptr = ptr->next; 21855dfecf96Smrg /* Skip inconditional jump node */ 21865dfecf96Smrg break; 21875dfecf96Smrg } 21885dfecf96Smrg } 21895dfecf96Smrg tree->data.tree = ptr; 21905dfecf96Smrg } 21915dfecf96Smrg break; 21925dfecf96Smrg 21935dfecf96Smrg case CodeTreeJump: 21945dfecf96Smrg if (tree->code != XBC_NOOP) 21955dfecf96Smrg tree->data.tree = tree->group; 21965dfecf96Smrg break; 21975dfecf96Smrg 21985dfecf96Smrg case CodeTreeReturn: 21995dfecf96Smrg /* One bytecode is guaranteed to exist in the code tree */ 22005dfecf96Smrg if (tree->data.block->parent == NULL) 22015dfecf96Smrg /* Returning from the function or toplevel form */ 22025dfecf96Smrg tree->data.tree = tree->data.block->tail; 22035dfecf96Smrg else { 22045dfecf96Smrg for (;;) { 22055dfecf96Smrg ptr = tree->data.block->parent->next; 22065dfecf96Smrg if (ptr) { 22075dfecf96Smrg tree->data.tree = ptr; 22085dfecf96Smrg break; 22095dfecf96Smrg } 22105dfecf96Smrg else 22115dfecf96Smrg /* Move one BLOCK up */ 22125dfecf96Smrg tree->data.block = tree->data.block->prev; 22135dfecf96Smrg } 22145dfecf96Smrg } 22155dfecf96Smrg break; 22165dfecf96Smrg } 22175dfecf96Smrg } 22185dfecf96Smrg} 22195dfecf96Smrg 22205dfecf96Smrgstatic long 22215dfecf96SmrgLinkPad(long offset, long adjust, int preffix, int datalen) 22225dfecf96Smrg{ 22235dfecf96Smrg /* If byte or aligned data */ 22245dfecf96Smrg if (datalen <= preffix || ((offset + adjust + preffix) % datalen) == 0) 22255dfecf96Smrg return (adjust); 22265dfecf96Smrg 22275dfecf96Smrg return (adjust + (datalen - ((offset + adjust + preffix) % datalen))); 22285dfecf96Smrg} 22295dfecf96Smrg 22305dfecf96Smrgstatic long 22315dfecf96SmrgLinkFixupOffsets(LispCom *com, CodeTree *tree, long adjust) 22325dfecf96Smrg{ 22335dfecf96Smrg for (; tree; tree = tree->next) { 22345dfecf96Smrg switch (tree->type) { 22355dfecf96Smrg case CodeTreeBytecode: 22365dfecf96Smrg switch (tree->code) { 22375dfecf96Smrg /* byte + short */ 22385dfecf96Smrg case XBC_JUMP: 22395dfecf96Smrg case XBC_JUMPT: 22405dfecf96Smrg case XBC_JUMPNIL: 22415dfecf96Smrg adjust = LinkPad(tree->offset, adjust, 1, 22425dfecf96Smrg sizeof(short)); 22435dfecf96Smrg /*FALLTROUGH*/ 22445dfecf96Smrg default: 22455dfecf96Smrg tree->offset += adjust; 22465dfecf96Smrg break; 22475dfecf96Smrg } 22485dfecf96Smrg break; 22495dfecf96Smrg case CodeTreeLabel: 22505dfecf96Smrg /* Labels are not loaded, just adjust offset */ 22515dfecf96Smrg tree->offset += adjust; 22525dfecf96Smrg break; 22535dfecf96Smrg case CodeTreeJump: 22545dfecf96Smrg case CodeTreeCond: 22555dfecf96Smrg case CodeTreeJumpIf: 22565dfecf96Smrg /* If an opcode will be generated. */ 22575dfecf96Smrg if (tree->code != XBC_NOOP) 22585dfecf96Smrg adjust = LinkPad(tree->offset, adjust, 1, sizeof(short)); 22595dfecf96Smrg tree->offset += adjust; 22605dfecf96Smrg break; 22615dfecf96Smrg case CodeTreeGo: 22625dfecf96Smrg case CodeTreeReturn: 22635dfecf96Smrg adjust = LinkPad(tree->offset, adjust, 1, sizeof(short)); 22645dfecf96Smrg tree->offset += adjust; 22655dfecf96Smrg break; 22665dfecf96Smrg case CodeTreeBlock: 22675dfecf96Smrg adjust = LinkFixupOffsets(com, tree->data.block->tree, adjust); 22685dfecf96Smrg break; 22695dfecf96Smrg } 22705dfecf96Smrg } 22715dfecf96Smrg 22725dfecf96Smrg return (adjust); 22735dfecf96Smrg} 22745dfecf96Smrg 22755dfecf96Smrgstatic void 22765dfecf96SmrgLinkSkipPadding(LispCom *com, CodeTree *tree) 22775dfecf96Smrg{ 22785dfecf96Smrg int found; 22795dfecf96Smrg CodeTree *ptr; 22805dfecf96Smrg 22815dfecf96Smrg /* Recurse to adjust forward jumps or jumps to the start of the block */ 22825dfecf96Smrg for (ptr = tree; ptr; ptr = ptr->next) { 22835dfecf96Smrg if (ptr->type == CodeTreeBlock) { 22845dfecf96Smrg LinkSkipPadding(com, ptr->data.block->tree); 22855dfecf96Smrg ptr->offset = ptr->data.block->tree->offset; 22865dfecf96Smrg } 22875dfecf96Smrg } 22885dfecf96Smrg 22895dfecf96Smrg /* Adjust the nodes offsets */ 22905dfecf96Smrg for (; tree; tree = tree->next) { 22915dfecf96Smrg switch (tree->type) { 22925dfecf96Smrg case CodeTreeBytecode: 22935dfecf96Smrg case CodeTreeBlock: 22945dfecf96Smrg case CodeTreeGo: 22955dfecf96Smrg case CodeTreeReturn: 22965dfecf96Smrg break; 22975dfecf96Smrg case CodeTreeJump: 22985dfecf96Smrg case CodeTreeCond: 22995dfecf96Smrg case CodeTreeJumpIf: 23005dfecf96Smrg if (tree->code != XBC_NOOP) 23015dfecf96Smrg /* If code will be generated */ 23025dfecf96Smrg break; 23035dfecf96Smrg case CodeTreeLabel: 23045dfecf96Smrg /* This should be done in reversed order, but to avoid 23055dfecf96Smrg * the requirement of a prev pointer, do the job in a 23065dfecf96Smrg * harder way here. */ 23075dfecf96Smrg for (found = 0, ptr = tree->next; ptr; ptr = ptr->next) { 23085dfecf96Smrg switch (ptr->type) { 23095dfecf96Smrg case CodeTreeBytecode: 23105dfecf96Smrg case CodeTreeBlock: 23115dfecf96Smrg case CodeTreeGo: 23125dfecf96Smrg case CodeTreeReturn: 23135dfecf96Smrg found = 1; 23145dfecf96Smrg break; 23155dfecf96Smrg case CodeTreeJump: 23165dfecf96Smrg case CodeTreeCond: 23175dfecf96Smrg case CodeTreeJumpIf: 23185dfecf96Smrg if (ptr->code != XBC_NOOP) 23195dfecf96Smrg found = 1; 23205dfecf96Smrg break; 23215dfecf96Smrg case CodeTreeLabel: 23225dfecf96Smrg break; 23235dfecf96Smrg } 23245dfecf96Smrg if (found) 23255dfecf96Smrg break; 23265dfecf96Smrg } 23275dfecf96Smrg if (found) 23285dfecf96Smrg tree->offset = ptr->offset; 23295dfecf96Smrg break; 23305dfecf96Smrg } 23315dfecf96Smrg } 23325dfecf96Smrg} 23335dfecf96Smrg 23345dfecf96Smrgstatic void 23355dfecf96SmrgLinkCalculateJump(LispCom *com, CodeTree *tree, LispByteOpcode code) 23365dfecf96Smrg{ 23375dfecf96Smrg long jumpto, offset, distance; 23385dfecf96Smrg 23395dfecf96Smrg tree->type = CodeTreeBytecode; 23405dfecf96Smrg /* After the opcode */ 23415dfecf96Smrg offset = tree->offset + 1; 23425dfecf96Smrg jumpto = tree->data.tree->offset; 23435dfecf96Smrg /* Effective distance */ 23445dfecf96Smrg distance = jumpto - offset; 23455dfecf96Smrg tree->code = code; 23465dfecf96Smrg if (distance < -32768 || distance > 32767) { 23475dfecf96Smrg COMPILE_FAILURE("jump too long"); 23485dfecf96Smrg } 23495dfecf96Smrg tree->data.signed_int = distance; 23505dfecf96Smrg} 23515dfecf96Smrg 23525dfecf96Smrgstatic void 23535dfecf96SmrgLinkFixupJumps(LispCom *com, CodeTree *tree) 23545dfecf96Smrg{ 23555dfecf96Smrg for (; tree; tree = tree->next) { 23565dfecf96Smrg switch (tree->type) { 23575dfecf96Smrg case CodeTreeBytecode: 23585dfecf96Smrg case CodeTreeLabel: 23595dfecf96Smrg break; 23605dfecf96Smrg case CodeTreeCond: 23615dfecf96Smrg if (tree->code == XBC_JUMPNIL) 23625dfecf96Smrg /* Go to next test if NIL */ 23635dfecf96Smrg LinkCalculateJump(com, tree, XBC_JUMPNIL); 23645dfecf96Smrg else if (tree->code == XBC_JUMPT) 23655dfecf96Smrg /* After executing T code */ 23665dfecf96Smrg LinkCalculateJump(com, tree, XBC_JUMP); 23675dfecf96Smrg break; 23685dfecf96Smrg case CodeTreeJumpIf: 23695dfecf96Smrg if (tree->code != XBC_NOOP) 23705dfecf96Smrg LinkCalculateJump(com, tree, tree->code); 23715dfecf96Smrg break; 23725dfecf96Smrg case CodeTreeGo: 23735dfecf96Smrg /* Inconditional jump */ 23745dfecf96Smrg LinkCalculateJump(com, tree, XBC_JUMP); 23755dfecf96Smrg break; 23765dfecf96Smrg case CodeTreeReturn: 23775dfecf96Smrg /* Inconditional jump */ 23785dfecf96Smrg if (tree->data.tree != tree) 23795dfecf96Smrg /* If need to skip something */ 23805dfecf96Smrg LinkCalculateJump(com, tree, XBC_JUMP); 23815dfecf96Smrg break; 23825dfecf96Smrg case CodeTreeBlock: 23835dfecf96Smrg LinkFixupJumps(com, tree->data.block->tree); 23845dfecf96Smrg break; 23855dfecf96Smrg case CodeTreeJump: 23865dfecf96Smrg if (tree->code != XBC_NOOP) 23875dfecf96Smrg LinkCalculateJump(com, tree, tree->code); 23885dfecf96Smrg } 23895dfecf96Smrg } 23905dfecf96Smrg} 23915dfecf96Smrg 23925dfecf96Smrgstatic void 23935dfecf96SmrgLinkBuildTableSymbol(LispCom *com, LispAtom *symbol) 23945dfecf96Smrg{ 23955dfecf96Smrg if (BuildTablePointer(symbol, (void***)&com->table.symbols, 23965dfecf96Smrg &com->table.num_symbols) > 0xff) { 23975dfecf96Smrg COMPILE_FAILURE("more than 256 symbols"); 23985dfecf96Smrg } 23995dfecf96Smrg} 24005dfecf96Smrg 24015dfecf96Smrgstatic void 24025dfecf96SmrgLinkBuildTableConstant(LispCom *com, LispObj *constant) 24035dfecf96Smrg{ 24045dfecf96Smrg if (BuildTablePointer(constant, (void***)&com->table.constants, 24055dfecf96Smrg &com->table.num_constants) > 0xff) { 24065dfecf96Smrg COMPILE_FAILURE("more than 256 constants"); 24075dfecf96Smrg } 24085dfecf96Smrg} 24095dfecf96Smrg 24105dfecf96Smrgstatic void 24115dfecf96SmrgLinkBuildTableBuiltin(LispCom *com, LispBuiltin *builtin) 24125dfecf96Smrg{ 24135dfecf96Smrg if (BuildTablePointer(builtin, (void***)&com->table.builtins, 24145dfecf96Smrg &com->table.num_builtins) > 0xff) { 24155dfecf96Smrg COMPILE_FAILURE("more than 256 functions"); 24165dfecf96Smrg } 24175dfecf96Smrg} 24185dfecf96Smrg 24195dfecf96Smrgstatic void 24205dfecf96SmrgLinkBuildTableBytecode(LispCom *com, LispObj *bytecode) 24215dfecf96Smrg{ 24225dfecf96Smrg if (BuildTablePointer(bytecode, (void***)&com->table.bytecodes, 24235dfecf96Smrg &com->table.num_bytecodes) > 0xff) { 24245dfecf96Smrg COMPILE_FAILURE("more than 256 bytecode functions"); 24255dfecf96Smrg } 24265dfecf96Smrg} 24275dfecf96Smrg 24285dfecf96Smrgstatic void 24295dfecf96SmrgLinkBuildTables(LispCom *com, CodeBlock *block) 24305dfecf96Smrg{ 24315dfecf96Smrg CodeTree *tree; 24325dfecf96Smrg 24335dfecf96Smrg for (tree = block->tree; tree; tree = tree->next) { 24345dfecf96Smrg switch (tree->type) { 24355dfecf96Smrg case CodeTreeBytecode: 24365dfecf96Smrg switch (tree->code) { 24375dfecf96Smrg case XBC_LET: 24385dfecf96Smrg case XBC_LETX: 24395dfecf96Smrg case XBC_LET_NIL: 24405dfecf96Smrg case XBC_LETX_NIL: 24415dfecf96Smrg case XBC_SETSYM: 24425dfecf96Smrg case XBC_LOADSYM: 24435dfecf96Smrg case XBC_LOADSYM_PUSH: 24445dfecf96Smrg LinkBuildTableSymbol(com, tree->data.atom); 24455dfecf96Smrg break; 24465dfecf96Smrg case XBC_STRUCTP: 24475dfecf96Smrg case XBC_LOADCON: 24485dfecf96Smrg case XBC_LOADCON_PUSH: 24495dfecf96Smrg LinkBuildTableConstant(com, tree->data.object); 24505dfecf96Smrg break; 24515dfecf96Smrg case XBC_LOADCON_SET: 24525dfecf96Smrg LinkBuildTableConstant(com, tree->data.load_con_set.object); 24535dfecf96Smrg break; 24545dfecf96Smrg case XBC_CALL: 24555dfecf96Smrg case XBC_CALL_SET: 24565dfecf96Smrg LinkBuildTableBuiltin(com, tree->data.builtin.builtin); 24575dfecf96Smrg break; 24585dfecf96Smrg case XBC_BYTECALL: 24595dfecf96Smrg LinkBuildTableBytecode(com, tree->data.bytecall.code); 24605dfecf96Smrg break; 24615dfecf96Smrg case XBC_LOAD_LET: 24625dfecf96Smrg case XBC_LOAD_LETX: 24635dfecf96Smrg LinkBuildTableSymbol(com, tree->data.let.name); 24645dfecf96Smrg break; 24655dfecf96Smrg case XBC_STRUCT: 24665dfecf96Smrg LinkBuildTableConstant(com, tree->data.struc.definition); 24675dfecf96Smrg break; 24685dfecf96Smrg case XBC_LOADSYM_LET: 24695dfecf96Smrg case XBC_LOADSYM_LETX: 24705dfecf96Smrg LinkBuildTableSymbol(com, tree->data.let_sym.symbol); 24715dfecf96Smrg LinkBuildTableSymbol(com, tree->data.let_sym.name); 24725dfecf96Smrg break; 24735dfecf96Smrg case XBC_LOADCON_LET: 24745dfecf96Smrg case XBC_LOADCON_LETX: 24755dfecf96Smrg LinkBuildTableConstant(com, tree->data.let_con.object); 24765dfecf96Smrg LinkBuildTableSymbol(com, tree->data.let_con.name); 24775dfecf96Smrg break; 24785dfecf96Smrg case XBC_CCONS: 24795dfecf96Smrg case XBC_FUNCALL: 24805dfecf96Smrg LinkBuildTableConstant(com, tree->data.cons.car); 24815dfecf96Smrg LinkBuildTableConstant(com, tree->data.cons.cdr); 24825dfecf96Smrg break; 24835dfecf96Smrg default: 24845dfecf96Smrg break; 24855dfecf96Smrg } 24865dfecf96Smrg break; 24875dfecf96Smrg case CodeTreeBlock: 24885dfecf96Smrg LinkBuildTables(com, tree->data.block); 24895dfecf96Smrg break; 24905dfecf96Smrg default: 24915dfecf96Smrg break; 24925dfecf96Smrg } 24935dfecf96Smrg } 24945dfecf96Smrg} 24955dfecf96Smrg 24965dfecf96Smrgstatic long 24975dfecf96SmrgLinkEmmitBytecode(LispCom *com, CodeTree *tree, 24985dfecf96Smrg unsigned char *bytecode, long offset) 24995dfecf96Smrg{ 25005dfecf96Smrg short i; 25015dfecf96Smrg 25025dfecf96Smrg for (; tree; tree = tree->next) { 25035dfecf96Smrg /* Fill padding */ 25045dfecf96Smrg while (offset < tree->offset) 25055dfecf96Smrg bytecode[offset++] = XBC_NOOP; 25065dfecf96Smrg 25075dfecf96Smrg switch (tree->type) { 25085dfecf96Smrg case CodeTreeBytecode: 25095dfecf96Smrg bytecode[offset++] = tree->code; 25105dfecf96Smrg switch (tree->code) { 25115dfecf96Smrg /* Noop should not enter the CodeTree */ 25125dfecf96Smrg case XBC_NOOP: 25135dfecf96Smrg INTERNAL_ERROR(__LINE__); 25145dfecf96Smrg break; 25155dfecf96Smrg 25165dfecf96Smrg /* byte */ 25175dfecf96Smrg case XBC_BCONS: 25185dfecf96Smrg case XBC_BCONS1: 25195dfecf96Smrg case XBC_BCONS2: 25205dfecf96Smrg case XBC_BCONS3: 25215dfecf96Smrg case XBC_BCONS4: 25225dfecf96Smrg case XBC_BCONS5: 25235dfecf96Smrg case XBC_BCONS6: 25245dfecf96Smrg case XBC_BCONS7: 25255dfecf96Smrg case XBC_INV: 25265dfecf96Smrg case XBC_NIL: 25275dfecf96Smrg case XBC_T: 25285dfecf96Smrg case XBC_PUSH_NIL: 25295dfecf96Smrg case XBC_PUSH_UNSPEC: 25305dfecf96Smrg case XBC_PUSH_T: 25315dfecf96Smrg case XBC_CAR_PUSH: 25325dfecf96Smrg case XBC_CDR_PUSH: 25335dfecf96Smrg case XBC_PUSH: 25345dfecf96Smrg case XBC_LSTAR: 25355dfecf96Smrg case XBC_LCONS: 25365dfecf96Smrg case XBC_LFINI: 25375dfecf96Smrg case XBC_RETURN: 25385dfecf96Smrg case XBC_CSTAR: 25395dfecf96Smrg case XBC_CFINI: 25405dfecf96Smrg case XBC_CAR: 25415dfecf96Smrg case XBC_CDR: 25425dfecf96Smrg case XBC_RPLACA: 25435dfecf96Smrg case XBC_RPLACD: 25445dfecf96Smrg case XBC_EQ: 25455dfecf96Smrg case XBC_EQL: 25465dfecf96Smrg case XBC_EQUAL: 25475dfecf96Smrg case XBC_EQUALP: 25485dfecf96Smrg case XBC_LENGTH: 25495dfecf96Smrg case XBC_LAST: 25505dfecf96Smrg case XBC_NTHCDR: 25515dfecf96Smrg break; 25525dfecf96Smrg 25535dfecf96Smrg /* byte + byte */ 25545dfecf96Smrg case XBC_LETREC: 25555dfecf96Smrg case XBC_PRED: 25565dfecf96Smrg case XBC_PUSH_NIL_N: 25575dfecf96Smrg case XBC_PUSH_UNSPEC_N: 25585dfecf96Smrg bytecode[offset++] = tree->data.signed_char; 25595dfecf96Smrg break; 25605dfecf96Smrg 25615dfecf96Smrg /* byte + byte */ 25625dfecf96Smrg case XBC_CAR_SET: 25635dfecf96Smrg case XBC_CDR_SET: 25645dfecf96Smrg case XBC_SET: 25655dfecf96Smrg case XBC_SET_NIL: 25665dfecf96Smrg case XBC_LETBIND: 25675dfecf96Smrg case XBC_UNLET: 25685dfecf96Smrg case XBC_LOAD_PUSH: 25695dfecf96Smrg case XBC_LOAD: 25705dfecf96Smrg case XBC_LOAD_CAR: 25715dfecf96Smrg case XBC_LOAD_CDR: 25725dfecf96Smrg case XBC_LOAD_CAR_STORE: 25735dfecf96Smrg case XBC_LOAD_CDR_STORE: 25745dfecf96Smrg bytecode[offset++] = tree->data.signed_short; 25755dfecf96Smrg break; 25765dfecf96Smrg 25775dfecf96Smrg /* byte + byte + byte */ 25785dfecf96Smrg case XBC_LOAD_SET: 25795dfecf96Smrg case XBC_LOAD_CAR_SET: 25805dfecf96Smrg case XBC_LOAD_CDR_SET: 25815dfecf96Smrg bytecode[offset++] = tree->data.load_set.load; 25825dfecf96Smrg bytecode[offset++] = tree->data.load_set.set; 25835dfecf96Smrg break; 25845dfecf96Smrg 25855dfecf96Smrg /* byte + short */ 25865dfecf96Smrg case XBC_JUMP: 25875dfecf96Smrg case XBC_JUMPT: 25885dfecf96Smrg case XBC_JUMPNIL: 25895dfecf96Smrg *(short*)(bytecode + offset) = tree->data.signed_int; 25905dfecf96Smrg offset += sizeof(short); 25915dfecf96Smrg break; 25925dfecf96Smrg 25935dfecf96Smrg /* byte + byte */ 25945dfecf96Smrg case XBC_LET: 25955dfecf96Smrg case XBC_LETX: 25965dfecf96Smrg case XBC_LET_NIL: 25975dfecf96Smrg case XBC_LETX_NIL: 25985dfecf96Smrg case XBC_SETSYM: 25995dfecf96Smrg case XBC_LOADSYM: 26005dfecf96Smrg case XBC_LOADSYM_PUSH: 26015dfecf96Smrg i = FindIndex(tree->data.atom, 26025dfecf96Smrg (void**)com->table.symbols, 26035dfecf96Smrg com->table.num_symbols); 26045dfecf96Smrg bytecode[offset++] = i; 26055dfecf96Smrg break; 26065dfecf96Smrg 26075dfecf96Smrg /* byte + byte */ 26085dfecf96Smrg case XBC_STRUCTP: 26095dfecf96Smrg case XBC_LOADCON: 26105dfecf96Smrg case XBC_LOADCON_PUSH: 26115dfecf96Smrg i = FindIndex(tree->data.object, 26125dfecf96Smrg (void**)com->table.constants, 26135dfecf96Smrg com->table.num_constants); 26145dfecf96Smrg bytecode[offset++] = i; 26155dfecf96Smrg break; 26165dfecf96Smrg 26175dfecf96Smrg /* byte + byte + byte */ 26185dfecf96Smrg case XBC_LOADCON_SET: 26195dfecf96Smrg i = FindIndex(tree->data.load_con_set.object, 26205dfecf96Smrg (void**)com->table.constants, 26215dfecf96Smrg com->table.num_constants); 26225dfecf96Smrg bytecode[offset++] = i; 26235dfecf96Smrg bytecode[offset++] = tree->data.load_con_set.offset; 26245dfecf96Smrg break; 26255dfecf96Smrg 26265dfecf96Smrg /* byte + byte + byte */ 26275dfecf96Smrg case XBC_CALL: 26285dfecf96Smrg bytecode[offset++] = tree->data.builtin.num_arguments; 26295dfecf96Smrg i = FindIndex(tree->data.builtin.builtin, 26305dfecf96Smrg (void**)com->table.builtins, 26315dfecf96Smrg com->table.num_builtins); 26325dfecf96Smrg bytecode[offset++] = i; 26335dfecf96Smrg break; 26345dfecf96Smrg 26355dfecf96Smrg /* byte + byte + byte */ 26365dfecf96Smrg case XBC_BYTECALL: 26375dfecf96Smrg bytecode[offset++] = tree->data.bytecall.num_arguments; 26385dfecf96Smrg i = FindIndex(tree->data.bytecall.code, 26395dfecf96Smrg (void**)com->table.bytecodes, 26405dfecf96Smrg com->table.num_bytecodes); 26415dfecf96Smrg bytecode[offset++] = i; 26425dfecf96Smrg break; 26435dfecf96Smrg 26445dfecf96Smrg /* byte + byte + byte + byte */ 26455dfecf96Smrg case XBC_CALL_SET: 26465dfecf96Smrg bytecode[offset++] = tree->data.builtin.num_arguments; 26475dfecf96Smrg i = FindIndex(tree->data.builtin.builtin, 26485dfecf96Smrg (void**)com->table.builtins, 26495dfecf96Smrg com->table.num_builtins); 26505dfecf96Smrg bytecode[offset++] = i; 26515dfecf96Smrg bytecode[offset++] = tree->data.builtin.offset; 26525dfecf96Smrg break; 26535dfecf96Smrg 26545dfecf96Smrg /* byte + byte + byte */ 26555dfecf96Smrg case XBC_LOAD_LET: 26565dfecf96Smrg case XBC_LOAD_LETX: 26575dfecf96Smrg bytecode[offset++] = tree->data.let.offset; 26585dfecf96Smrg i = FindIndex(tree->data.let.name, 26595dfecf96Smrg (void**)com->table.symbols, 26605dfecf96Smrg com->table.num_symbols); 26615dfecf96Smrg bytecode[offset++] = i; 26625dfecf96Smrg break; 26635dfecf96Smrg 26645dfecf96Smrg /* byte + byte + byte */ 26655dfecf96Smrg case XBC_STRUCT: 26665dfecf96Smrg bytecode[offset++] = tree->data.struc.offset; 26675dfecf96Smrg i = FindIndex(tree->data.struc.definition, 26685dfecf96Smrg (void**)com->table.constants, 26695dfecf96Smrg com->table.num_constants); 26705dfecf96Smrg bytecode[offset++] = i; 26715dfecf96Smrg break; 26725dfecf96Smrg 26735dfecf96Smrg /* byte + byte + byte */ 26745dfecf96Smrg case XBC_LOADSYM_LET: 26755dfecf96Smrg case XBC_LOADSYM_LETX: 26765dfecf96Smrg i = FindIndex(tree->data.let_sym.symbol, 26775dfecf96Smrg (void**)com->table.symbols, 26785dfecf96Smrg com->table.num_symbols); 26795dfecf96Smrg bytecode[offset++] = i; 26805dfecf96Smrg i = FindIndex(tree->data.let_sym.name, 26815dfecf96Smrg (void**)com->table.symbols, 26825dfecf96Smrg com->table.num_symbols); 26835dfecf96Smrg bytecode[offset++] = i; 26845dfecf96Smrg break; 26855dfecf96Smrg 26865dfecf96Smrg /* byte + byte + byte */ 26875dfecf96Smrg case XBC_LOADCON_LET: 26885dfecf96Smrg case XBC_LOADCON_LETX: 26895dfecf96Smrg i = FindIndex(tree->data.let_con.object, 26905dfecf96Smrg (void**)com->table.constants, 26915dfecf96Smrg com->table.num_constants); 26925dfecf96Smrg bytecode[offset++] = i; 26935dfecf96Smrg i = FindIndex(tree->data.let_con.name, 26945dfecf96Smrg (void**)com->table.symbols, 26955dfecf96Smrg com->table.num_symbols); 26965dfecf96Smrg bytecode[offset++] = i; 26975dfecf96Smrg break; 26985dfecf96Smrg 26995dfecf96Smrg /* byte + byte + byte */ 27005dfecf96Smrg case XBC_CCONS: 27015dfecf96Smrg case XBC_FUNCALL: 27025dfecf96Smrg i = FindIndex(tree->data.cons.car, 27035dfecf96Smrg (void**)com->table.constants, 27045dfecf96Smrg com->table.num_constants); 27055dfecf96Smrg bytecode[offset++] = i; 27065dfecf96Smrg i = FindIndex(tree->data.cons.cdr, 27075dfecf96Smrg (void**)com->table.constants, 27085dfecf96Smrg com->table.num_constants); 27095dfecf96Smrg bytecode[offset++] = i; 27105dfecf96Smrg break; 27115dfecf96Smrg } 27125dfecf96Smrg break; 27135dfecf96Smrg case CodeTreeLabel: 27145dfecf96Smrg /* Labels are not loaded */ 27155dfecf96Smrg break; 27165dfecf96Smrg case CodeTreeCond: 27175dfecf96Smrg case CodeTreeJump: 27185dfecf96Smrg case CodeTreeJumpIf: 27195dfecf96Smrg if (tree->code != XBC_NOOP) 27205dfecf96Smrg INTERNAL_ERROR(__LINE__); 27215dfecf96Smrg break; 27225dfecf96Smrg case CodeTreeGo: 27235dfecf96Smrg INTERNAL_ERROR(__LINE__); 27245dfecf96Smrg break; 27255dfecf96Smrg case CodeTreeReturn: 27265dfecf96Smrg if (tree->data.tree != tree) 27275dfecf96Smrg INTERNAL_ERROR(__LINE__); 27285dfecf96Smrg break; 27295dfecf96Smrg case CodeTreeBlock: 27305dfecf96Smrg offset = LinkEmmitBytecode(com, tree->data.block->tree, 27315dfecf96Smrg bytecode, offset); 27325dfecf96Smrg break; 27335dfecf96Smrg } 27345dfecf96Smrg } 27355dfecf96Smrg 27365dfecf96Smrg return (offset); 27375dfecf96Smrg} 27385dfecf96Smrg 27395dfecf96Smrgstatic void 27405dfecf96SmrgLinkBytecode(LispCom *com) 27415dfecf96Smrg{ 27425dfecf96Smrg long offset, count; 27435dfecf96Smrg unsigned char **codes; 27445dfecf96Smrg LispObj **names; 27455dfecf96Smrg 27465dfecf96Smrg /* Close bytecode */ 27475dfecf96Smrg com_Bytecode(com, XBC_RETURN); 27485dfecf96Smrg 27495dfecf96Smrg /* The only usage of this information for now, and still may generate 27505dfecf96Smrg * false positives because arguments to unamed functions are not being 27515dfecf96Smrg * parsed as well as arguments to yet undefined function/maros. 27525dfecf96Smrg * XXX should also add declaim/declare to let the code specify that 27535dfecf96Smrg * the argument is unused */ 27545dfecf96Smrg LinkWarnUnused(com, com->block); 27555dfecf96Smrg 27565dfecf96Smrg /* First level optimization */ 27575dfecf96Smrg LinkOptimize_0(com); 27585dfecf96Smrg 27595dfecf96Smrg /* Resolve tagbody labels */ 27605dfecf96Smrg LinkResolveLabels(com, com->block); 27615dfecf96Smrg 27625dfecf96Smrg /* Resolve any pending jumps */ 27635dfecf96Smrg LinkResolveJumps(com, com->block); 27645dfecf96Smrg 27655dfecf96Smrg /* Calculate unpadded offsets */ 27665dfecf96Smrg LinkBuildOffsets(com, com->block->tree, 0); 27675dfecf96Smrg 27685dfecf96Smrg /* Do padding for aligned memory reads */ 27695dfecf96Smrg LinkFixupOffsets(com, com->block->tree, 0); 27705dfecf96Smrg 27715dfecf96Smrg /* Jumps normally are to a node that does not generate code, 27725dfecf96Smrg * and due to padding, the jump may go to a address with a 27735dfecf96Smrg * XBC_NOOP, so adjust the jump to the next useful opcode. */ 27745dfecf96Smrg LinkSkipPadding(com, com->block->tree); 27755dfecf96Smrg 27765dfecf96Smrg /* Now addresses are known */ 27775dfecf96Smrg LinkFixupJumps(com, com->block->tree); 27785dfecf96Smrg 27795dfecf96Smrg /* Build symbol, constant and builtin tables */ 27805dfecf96Smrg LinkBuildTables(com, com->block); 27815dfecf96Smrg 27825dfecf96Smrg /* Stack info */ 27835dfecf96Smrg com->length = sizeof(short) * 3; 27845dfecf96Smrg /* Tables info */ 27855dfecf96Smrg com->length += sizeof(short) * 4; 27865dfecf96Smrg com->length += com->table.num_constants * sizeof(LispObj*); 27875dfecf96Smrg com->length += com->table.num_symbols * sizeof(LispAtom*); 27885dfecf96Smrg com->length += com->table.num_builtins * sizeof(LispBuiltin*); 27895dfecf96Smrg com->length += com->table.num_bytecodes * sizeof(unsigned char*); 27905dfecf96Smrg com->length += com->table.num_bytecodes * sizeof(LispObj*); 27915dfecf96Smrg 27925dfecf96Smrg /* Allocate space for the bytecode stream */ 27935dfecf96Smrg com->length += com->block->tail->offset + 1; 27945dfecf96Smrg com->bytecode = LispMalloc(com->length); 27955dfecf96Smrg 27965dfecf96Smrg /* Add header */ 27975dfecf96Smrg offset = 0; 27985dfecf96Smrg *(short*)(com->bytecode + offset) = com->stack.stack; 27995dfecf96Smrg offset += sizeof(short); 28005dfecf96Smrg *(short*)(com->bytecode + offset) = com->stack.bstack; 28015dfecf96Smrg offset += sizeof(short); 28025dfecf96Smrg *(short*)(com->bytecode + offset) = com->stack.pstack; 28035dfecf96Smrg offset += sizeof(short); 28045dfecf96Smrg 28055dfecf96Smrg *(short*)(com->bytecode + offset) = com->table.num_constants; 28065dfecf96Smrg offset += sizeof(short); 28075dfecf96Smrg *(short*)(com->bytecode + offset) = com->table.num_symbols; 28085dfecf96Smrg offset += sizeof(short); 28095dfecf96Smrg *(short*)(com->bytecode + offset) = com->table.num_builtins; 28105dfecf96Smrg offset += sizeof(short); 28115dfecf96Smrg *(short*)(com->bytecode + offset) = com->table.num_bytecodes; 28125dfecf96Smrg offset += sizeof(short); 28135dfecf96Smrg 28145dfecf96Smrg count = sizeof(LispObj*) * com->table.num_constants; 28155dfecf96Smrg memcpy(com->bytecode + offset, com->table.constants, count); 28165dfecf96Smrg offset += count; 28175dfecf96Smrg count = sizeof(LispAtom*) * com->table.num_symbols; 28185dfecf96Smrg memcpy(com->bytecode + offset, com->table.symbols, count); 28195dfecf96Smrg offset += count; 28205dfecf96Smrg count = sizeof(LispBuiltin*) * com->table.num_builtins; 28215dfecf96Smrg memcpy(com->bytecode + offset, com->table.builtins, count); 28225dfecf96Smrg offset += count; 28235dfecf96Smrg 28245dfecf96Smrg /* Store bytecode information */ 28255dfecf96Smrg for (count = 0, codes = (unsigned char**)(com->bytecode + offset); 28265dfecf96Smrg count < com->table.num_bytecodes; count++, codes++) 28275dfecf96Smrg *codes = com->table.bytecodes[count]->data.bytecode.bytecode->code; 28285dfecf96Smrg offset += com->table.num_bytecodes * sizeof(unsigned char*); 28295dfecf96Smrg /* Store names, only useful for disassemble but may also be used 28305dfecf96Smrg * to check if a function was redefined, and the bytecode is referencing 28315dfecf96Smrg * the older version, the current version can be checked looking at 28325dfecf96Smrg * <name>->data.atom */ 28335dfecf96Smrg for (count = 0, names = (LispObj**)(com->bytecode + offset); 28345dfecf96Smrg count < com->table.num_bytecodes; count++, names++) 28355dfecf96Smrg *names = com->table.bytecodes[count]->data.bytecode.name; 28365dfecf96Smrg offset += com->table.num_bytecodes * sizeof(LispObj*); 28375dfecf96Smrg 28385dfecf96Smrg /* Generate it */ 28395dfecf96Smrg LinkEmmitBytecode(com, com->block->tree, com->bytecode + offset, 0); 28405dfecf96Smrg} 28415dfecf96Smrg 28425dfecf96Smrgstatic LispObj * 28435dfecf96SmrgExecuteBytecode(register unsigned char *stream) 28445dfecf96Smrg{ 28455dfecf96Smrg register LispObj *reg0; 28465dfecf96Smrg register LispAtom *atom; 28475dfecf96Smrg register short offset; 28485dfecf96Smrg LispObj *reg1; 28495dfecf96Smrg LispBuiltin *builtin; 28505dfecf96Smrg LispObj *lambda; 28515dfecf96Smrg LispObj *arguments; 28525dfecf96Smrg unsigned char *bytecode; 28535dfecf96Smrg 28545dfecf96Smrg LispObj **constants; 28555dfecf96Smrg LispAtom **symbols; 28565dfecf96Smrg LispBuiltin **builtins; 28575dfecf96Smrg unsigned char **codes; 28585dfecf96Smrg short num_constants, num_symbols, num_builtins, num_codes; 28595dfecf96Smrg 28605dfecf96Smrg int lex, len; 28615dfecf96Smrg 28625dfecf96Smrg /* To control gc protected slots */ 28635dfecf96Smrg int phead, pbase; 28645dfecf96Smrg 28655dfecf96Smrg long fixnum = 0; 28665dfecf96Smrg 28675dfecf96Smrg#if defined(__GNUC__) && !defined(ANSI_SOURCE) 28685dfecf96Smrg#define ALLOW_GOTO_ADDRESS 28695dfecf96Smrg#endif 28705dfecf96Smrg 28715dfecf96Smrg#ifdef ALLOW_GOTO_ADDRESS 28725dfecf96Smrg#define JUMP_ADDRESS(label) &&label 28735dfecf96Smrg static const void *opcode_labels[] = { 28745dfecf96Smrg JUMP_ADDRESS(XBC_NOOP), 28755dfecf96Smrg JUMP_ADDRESS(XBC_INV), 28765dfecf96Smrg JUMP_ADDRESS(XBC_NIL), 28775dfecf96Smrg JUMP_ADDRESS(XBC_T), 28785dfecf96Smrg JUMP_ADDRESS(XBC_PRED), 28795dfecf96Smrg JUMP_ADDRESS(XBC_CAR), 28805dfecf96Smrg JUMP_ADDRESS(XBC_CDR), 28815dfecf96Smrg JUMP_ADDRESS(XBC_CAR_SET), 28825dfecf96Smrg JUMP_ADDRESS(XBC_CDR_SET), 28835dfecf96Smrg JUMP_ADDRESS(XBC_RPLACA), 28845dfecf96Smrg JUMP_ADDRESS(XBC_RPLACD), 28855dfecf96Smrg JUMP_ADDRESS(XBC_EQ), 28865dfecf96Smrg JUMP_ADDRESS(XBC_EQL), 28875dfecf96Smrg JUMP_ADDRESS(XBC_EQUAL), 28885dfecf96Smrg JUMP_ADDRESS(XBC_EQUALP), 28895dfecf96Smrg JUMP_ADDRESS(XBC_LENGTH), 28905dfecf96Smrg JUMP_ADDRESS(XBC_LAST), 28915dfecf96Smrg JUMP_ADDRESS(XBC_NTHCDR), 28925dfecf96Smrg JUMP_ADDRESS(XBC_CAR_PUSH), 28935dfecf96Smrg JUMP_ADDRESS(XBC_CDR_PUSH), 28945dfecf96Smrg JUMP_ADDRESS(XBC_PUSH), 28955dfecf96Smrg JUMP_ADDRESS(XBC_PUSH_NIL), 28965dfecf96Smrg JUMP_ADDRESS(XBC_PUSH_UNSPEC), 28975dfecf96Smrg JUMP_ADDRESS(XBC_PUSH_T), 28985dfecf96Smrg JUMP_ADDRESS(XBC_PUSH_NIL_N), 28995dfecf96Smrg JUMP_ADDRESS(XBC_PUSH_UNSPEC_N), 29005dfecf96Smrg JUMP_ADDRESS(XBC_LET), 29015dfecf96Smrg JUMP_ADDRESS(XBC_LETX), 29025dfecf96Smrg JUMP_ADDRESS(XBC_LET_NIL), 29035dfecf96Smrg JUMP_ADDRESS(XBC_LETX_NIL), 29045dfecf96Smrg JUMP_ADDRESS(XBC_LETBIND), 29055dfecf96Smrg JUMP_ADDRESS(XBC_UNLET), 29065dfecf96Smrg JUMP_ADDRESS(XBC_LOAD), 29075dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_LET), 29085dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_LETX), 29095dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_PUSH), 29105dfecf96Smrg JUMP_ADDRESS(XBC_LOADCON), 29115dfecf96Smrg JUMP_ADDRESS(XBC_LOADCON_LET), 29125dfecf96Smrg JUMP_ADDRESS(XBC_LOADCON_LETX), 29135dfecf96Smrg JUMP_ADDRESS(XBC_LOADCON_PUSH), 29145dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CAR), 29155dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CDR), 29165dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CAR_STORE), 29175dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CDR_STORE), 29185dfecf96Smrg JUMP_ADDRESS(XBC_LOADCON_SET), 29195dfecf96Smrg JUMP_ADDRESS(XBC_LOADSYM), 29205dfecf96Smrg JUMP_ADDRESS(XBC_LOADSYM_LET), 29215dfecf96Smrg JUMP_ADDRESS(XBC_LOADSYM_LETX), 29225dfecf96Smrg JUMP_ADDRESS(XBC_LOADSYM_PUSH), 29235dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_SET), 29245dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CAR_SET), 29255dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CDR_SET), 29265dfecf96Smrg JUMP_ADDRESS(XBC_SET), 29275dfecf96Smrg JUMP_ADDRESS(XBC_SETSYM), 29285dfecf96Smrg JUMP_ADDRESS(XBC_SET_NIL), 29295dfecf96Smrg JUMP_ADDRESS(XBC_CALL), 29305dfecf96Smrg JUMP_ADDRESS(XBC_CALL_SET), 29315dfecf96Smrg JUMP_ADDRESS(XBC_BYTECALL), 29325dfecf96Smrg JUMP_ADDRESS(XBC_FUNCALL), 29335dfecf96Smrg JUMP_ADDRESS(XBC_LETREC), 29345dfecf96Smrg JUMP_ADDRESS(XBC_BCONS), 29355dfecf96Smrg JUMP_ADDRESS(XBC_BCONS1), 29365dfecf96Smrg JUMP_ADDRESS(XBC_BCONS2), 29375dfecf96Smrg JUMP_ADDRESS(XBC_BCONS3), 29385dfecf96Smrg JUMP_ADDRESS(XBC_BCONS4), 29395dfecf96Smrg JUMP_ADDRESS(XBC_BCONS5), 29405dfecf96Smrg JUMP_ADDRESS(XBC_BCONS6), 29415dfecf96Smrg JUMP_ADDRESS(XBC_BCONS7), 29425dfecf96Smrg JUMP_ADDRESS(XBC_CCONS), 29435dfecf96Smrg JUMP_ADDRESS(XBC_CSTAR), 29445dfecf96Smrg JUMP_ADDRESS(XBC_CFINI), 29455dfecf96Smrg JUMP_ADDRESS(XBC_LSTAR), 29465dfecf96Smrg JUMP_ADDRESS(XBC_LCONS), 29475dfecf96Smrg JUMP_ADDRESS(XBC_LFINI), 29485dfecf96Smrg JUMP_ADDRESS(XBC_JUMP), 29495dfecf96Smrg JUMP_ADDRESS(XBC_JUMPT), 29505dfecf96Smrg JUMP_ADDRESS(XBC_JUMPNIL), 29515dfecf96Smrg JUMP_ADDRESS(XBC_STRUCT), 29525dfecf96Smrg JUMP_ADDRESS(XBC_STRUCTP), 29535dfecf96Smrg JUMP_ADDRESS(XBC_RETURN) 29545dfecf96Smrg }; 29555dfecf96Smrg static const void *predicate_opcode_labels[] = { 29565dfecf96Smrg JUMP_ADDRESS(XBP_CONSP), 29575dfecf96Smrg JUMP_ADDRESS(XBP_LISTP), 29585dfecf96Smrg JUMP_ADDRESS(XBP_NUMBERP) 29595dfecf96Smrg }; 29605dfecf96Smrg#endif 29615dfecf96Smrg 29625dfecf96Smrg reg0 = NIL; 29635dfecf96Smrg 29645dfecf96Smrg bytecode = stream; 29655dfecf96Smrg pbase = lisp__data.protect.length; 29665dfecf96Smrg 29675dfecf96Smrg /* stack */ 29685dfecf96Smrg offset = *(short*)stream; 29695dfecf96Smrg stream += sizeof(short); 29705dfecf96Smrg if (lisp__data.env.length + offset > lisp__data.env.space) { 29715dfecf96Smrg do 29725dfecf96Smrg LispMoreEnvironment(); 29735dfecf96Smrg while (lisp__data.env.length + offset >= lisp__data.env.space); 29745dfecf96Smrg } 29755dfecf96Smrg /* builtin stack */ 29765dfecf96Smrg offset = *(short*)stream; 29775dfecf96Smrg stream += sizeof(short); 29785dfecf96Smrg if (lisp__data.stack.length + offset >= lisp__data.stack.space) { 29795dfecf96Smrg do 29805dfecf96Smrg LispMoreStack(); 29815dfecf96Smrg while (lisp__data.stack.length + offset >= lisp__data.stack.space); 29825dfecf96Smrg } 29835dfecf96Smrg /* protect stack */ 29845dfecf96Smrg phead = *(short*)stream; 29855dfecf96Smrg stream += sizeof(short); 29865dfecf96Smrg if (lisp__data.protect.length + phead > lisp__data.protect.space) { 29875dfecf96Smrg do 29885dfecf96Smrg LispMoreProtects(); 29895dfecf96Smrg while (lisp__data.protect.length + phead >= lisp__data.protect.space); 29905dfecf96Smrg } 29915dfecf96Smrg 29925dfecf96Smrg num_constants = *(short*)stream; 29935dfecf96Smrg stream += sizeof(short); 29945dfecf96Smrg num_symbols = *(short*)stream; 29955dfecf96Smrg stream += sizeof(short); 29965dfecf96Smrg num_builtins = *(short*)stream; 29975dfecf96Smrg stream += sizeof(short); 29985dfecf96Smrg num_codes = *(short*)stream; 29995dfecf96Smrg stream += sizeof(short); 30005dfecf96Smrg 30015dfecf96Smrg constants = (LispObj**)stream; 30025dfecf96Smrg stream += num_constants * sizeof(LispObj*); 30035dfecf96Smrg symbols = (LispAtom**)stream; 30045dfecf96Smrg stream += num_symbols * sizeof(LispAtom*); 30055dfecf96Smrg builtins = (LispBuiltin**)stream; 30065dfecf96Smrg stream += num_builtins * sizeof(LispBuiltin*); 30075dfecf96Smrg codes = (unsigned char**)stream; 30085dfecf96Smrg stream += num_codes * (sizeof(unsigned char*) + sizeof(LispObj*)); 30095dfecf96Smrg 30105dfecf96Smrg for (; phead > 0; phead--) 30115dfecf96Smrg lisp__data.protect.objects[lisp__data.protect.length++] = NIL; 30125dfecf96Smrg phead = pbase; 30135dfecf96Smrg 30145dfecf96Smrg#ifdef ALLOW_GOTO_ADDRESS 30155dfecf96Smrg#define OPCODE_LABEL(label) label 30165dfecf96Smrg#define NEXT_OPCODE() goto *opcode_labels[*stream++] 30175dfecf96Smrg#define GOTO_PREDICATE() goto *predicate_opcode_labels[*stream++] 30185dfecf96Smrg#else 30195dfecf96Smrg#define OPCODE_LABEL(label) case label 30205dfecf96Smrg#define NEXT_OPCODE() goto next_opcode 30215dfecf96Smrg#define GOTO_PREDICATE() goto predicate_label 30225dfecf96Smrg for (;;) { 30235dfecf96Smrgnext_opcode: 30245dfecf96Smrg switch (*stream++) { 30255dfecf96Smrg#endif /* ALLOW_GOTO_ADDRESS */ 30265dfecf96Smrg 30275dfecf96SmrgOPCODE_LABEL(XBC_NOOP): 30285dfecf96Smrg NEXT_OPCODE(); 30295dfecf96Smrg 30305dfecf96SmrgOPCODE_LABEL(XBC_PRED): 30315dfecf96Smrg GOTO_PREDICATE(); 30325dfecf96Smrg 30335dfecf96SmrgOPCODE_LABEL(XBC_INV): 30345dfecf96Smrg reg0 = reg0 == NIL ? T : NIL; 30355dfecf96Smrg NEXT_OPCODE(); 30365dfecf96Smrg 30375dfecf96SmrgOPCODE_LABEL(XBC_NIL): 30385dfecf96Smrg reg0 = NIL; 30395dfecf96Smrg NEXT_OPCODE(); 30405dfecf96Smrg 30415dfecf96SmrgOPCODE_LABEL(XBC_T): 30425dfecf96Smrg reg0 = T; 30435dfecf96Smrg NEXT_OPCODE(); 30445dfecf96Smrg 30455dfecf96SmrgOPCODE_LABEL(XBC_CAR): 30465dfecf96Smrgcar: 30475dfecf96Smrg if (reg0 != NIL) { 30485dfecf96Smrg if (!CONSP(reg0)) 30495dfecf96Smrg LispDestroy("CAR: %s is not a list", STROBJ(reg0)); 30505dfecf96Smrg reg0 = CAR(reg0); 30515dfecf96Smrg } 30525dfecf96Smrg NEXT_OPCODE(); 30535dfecf96Smrg 30545dfecf96SmrgOPCODE_LABEL(XBC_CDR): 30555dfecf96Smrgcdr: 30565dfecf96Smrg if (reg0 != NIL) { 30575dfecf96Smrg if (!CONSP(reg0)) 30585dfecf96Smrg LispDestroy("CDR: %s is not a list", STROBJ(reg0)); 30595dfecf96Smrg reg0 = CDR(reg0); 30605dfecf96Smrg } 30615dfecf96Smrg NEXT_OPCODE(); 30625dfecf96Smrg 30635dfecf96SmrgOPCODE_LABEL(XBC_RPLACA): 30645dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 30655dfecf96Smrg if (!CONSP(reg1)) 30665dfecf96Smrg LispDestroy("RPLACA: %s is not a cons", STROBJ(reg1)); 30675dfecf96Smrg RPLACA(reg1, reg0); 30685dfecf96Smrg reg0 = reg1; 30695dfecf96Smrg NEXT_OPCODE(); 30705dfecf96Smrg 30715dfecf96SmrgOPCODE_LABEL(XBC_RPLACD): 30725dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 30735dfecf96Smrg if (!CONSP(reg1)) 30745dfecf96Smrg LispDestroy("RPLACD: %s is not a cons", STROBJ(reg1)); 30755dfecf96Smrg RPLACD(reg1, reg0); 30765dfecf96Smrg reg0 = reg1; 30775dfecf96Smrg NEXT_OPCODE(); 30785dfecf96Smrg 30795dfecf96SmrgOPCODE_LABEL(XBC_BCONS): 30805dfecf96Smrg CAR(cons) = reg0; 30815dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = cons; 30825dfecf96Smrg NEXT_OPCODE(); 30835dfecf96Smrg 30845dfecf96SmrgOPCODE_LABEL(XBC_BCONS1): 30855dfecf96Smrg offset = lisp__data.stack.length - 1; 30865dfecf96Smrg CAR(cons) = reg0; 30875dfecf96Smrg CAR(cons1) = lisp__data.stack.values[offset]; 30885dfecf96Smrg lisp__data.stack.values[offset] = cons1; 30895dfecf96Smrg NEXT_OPCODE(); 30905dfecf96Smrg 30915dfecf96SmrgOPCODE_LABEL(XBC_BCONS2): 30925dfecf96Smrg offset = lisp__data.stack.length; 30935dfecf96Smrg CAR(cons) = reg0; 30945dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 30955dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 30965dfecf96Smrg lisp__data.stack.values[offset] = cons2; 30975dfecf96Smrg lisp__data.stack.length = offset + 1; 30985dfecf96Smrg NEXT_OPCODE(); 30995dfecf96Smrg 31005dfecf96SmrgOPCODE_LABEL(XBC_BCONS3): 31015dfecf96Smrg offset = lisp__data.stack.length; 31025dfecf96Smrg CAR(cons) = reg0; 31035dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 31045dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 31055dfecf96Smrg CAR(cons3) = lisp__data.stack.values[--offset]; 31065dfecf96Smrg lisp__data.stack.values[offset] = cons3; 31075dfecf96Smrg lisp__data.stack.length = offset + 1; 31085dfecf96Smrg NEXT_OPCODE(); 31095dfecf96Smrg 31105dfecf96SmrgOPCODE_LABEL(XBC_BCONS4): 31115dfecf96Smrg offset = lisp__data.stack.length; 31125dfecf96Smrg CAR(cons) = reg0; 31135dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 31145dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 31155dfecf96Smrg CAR(cons3) = lisp__data.stack.values[--offset]; 31165dfecf96Smrg CAR(cons4) = lisp__data.stack.values[--offset]; 31175dfecf96Smrg lisp__data.stack.values[offset] = cons4; 31185dfecf96Smrg lisp__data.stack.length = offset + 1; 31195dfecf96Smrg NEXT_OPCODE(); 31205dfecf96Smrg 31215dfecf96SmrgOPCODE_LABEL(XBC_BCONS5): 31225dfecf96Smrg offset = lisp__data.stack.length; 31235dfecf96Smrg CAR(cons) = reg0; 31245dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 31255dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 31265dfecf96Smrg CAR(cons3) = lisp__data.stack.values[--offset]; 31275dfecf96Smrg CAR(cons4) = lisp__data.stack.values[--offset]; 31285dfecf96Smrg CAR(cons5) = lisp__data.stack.values[--offset]; 31295dfecf96Smrg lisp__data.stack.values[offset] = cons5; 31305dfecf96Smrg lisp__data.stack.length = offset + 1; 31315dfecf96Smrg NEXT_OPCODE(); 31325dfecf96Smrg 31335dfecf96SmrgOPCODE_LABEL(XBC_BCONS6): 31345dfecf96Smrg offset = lisp__data.stack.length; 31355dfecf96Smrg CAR(cons) = reg0; 31365dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 31375dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 31385dfecf96Smrg CAR(cons3) = lisp__data.stack.values[--offset]; 31395dfecf96Smrg CAR(cons4) = lisp__data.stack.values[--offset]; 31405dfecf96Smrg CAR(cons5) = lisp__data.stack.values[--offset]; 31415dfecf96Smrg CAR(cons6) = lisp__data.stack.values[--offset]; 31425dfecf96Smrg lisp__data.stack.values[offset] = cons6; 31435dfecf96Smrg lisp__data.stack.length = offset + 1; 31445dfecf96Smrg NEXT_OPCODE(); 31455dfecf96Smrg 31465dfecf96SmrgOPCODE_LABEL(XBC_BCONS7): 31475dfecf96Smrg offset = lisp__data.stack.length; 31485dfecf96Smrg CAR(cons) = reg0; 31495dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 31505dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 31515dfecf96Smrg CAR(cons3) = lisp__data.stack.values[--offset]; 31525dfecf96Smrg CAR(cons4) = lisp__data.stack.values[--offset]; 31535dfecf96Smrg CAR(cons5) = lisp__data.stack.values[--offset]; 31545dfecf96Smrg CAR(cons6) = lisp__data.stack.values[--offset]; 31555dfecf96Smrg CAR(cons7) = lisp__data.stack.values[--offset]; 31565dfecf96Smrg lisp__data.stack.values[offset] = cons7; 31575dfecf96Smrg lisp__data.stack.length = offset + 1; 31585dfecf96Smrg NEXT_OPCODE(); 31595dfecf96Smrg 31605dfecf96SmrgOPCODE_LABEL(XBC_EQ): 31615dfecf96Smrg reg0 = reg0 == lisp__data.stack.values[--lisp__data.stack.length] ? T : NIL; 31625dfecf96Smrg NEXT_OPCODE(); 31635dfecf96Smrg 31645dfecf96SmrgOPCODE_LABEL(XBC_EQL): 31655dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 31665dfecf96Smrg reg0 = XEQL(reg1, reg0); 31675dfecf96Smrg NEXT_OPCODE(); 31685dfecf96Smrg 31695dfecf96SmrgOPCODE_LABEL(XBC_EQUAL): 31705dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 31715dfecf96Smrg reg0 = XEQUAL(reg1, reg0); 31725dfecf96Smrg NEXT_OPCODE(); 31735dfecf96Smrg 31745dfecf96SmrgOPCODE_LABEL(XBC_EQUALP): 31755dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 31765dfecf96Smrg reg0 = XEQUALP(reg1, reg0); 31775dfecf96Smrg NEXT_OPCODE(); 31785dfecf96Smrg 31795dfecf96SmrgOPCODE_LABEL(XBC_LENGTH): 31805dfecf96Smrg reg0 = FIXNUM(LispLength(reg0)); 31815dfecf96Smrg NEXT_OPCODE(); 31825dfecf96Smrg 31835dfecf96SmrgOPCODE_LABEL(XBC_LAST): 31845dfecf96Smrg { 31855dfecf96Smrg long length; 31865dfecf96Smrg 31875dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 31885dfecf96Smrg if (CONSP(reg1)) { 31895dfecf96Smrg if (reg0 != NIL) { 31905dfecf96Smrg if (!FIXNUMP(reg0) || (fixnum = FIXNUM_VALUE(reg0)) < 0) 31915dfecf96Smrg LispDestroy("LAST: %s is not a positive fixnum", 31925dfecf96Smrg STROBJ(reg0)); 31935dfecf96Smrg } 31945dfecf96Smrg else 31955dfecf96Smrg fixnum = 1; 31965dfecf96Smrg reg0 = reg1; 31975dfecf96Smrg for (reg0 = reg1, length = 0; 31985dfecf96Smrg CONSP(reg0); 31995dfecf96Smrg reg0 = CDR(reg0), length++) 32005dfecf96Smrg ; 32015dfecf96Smrg for (length -= fixnum, reg0 = reg1; length > 0; length--) 32025dfecf96Smrg reg0 = CDR(reg0); 32035dfecf96Smrg } 32045dfecf96Smrg else 32055dfecf96Smrg reg0 = reg1; 32065dfecf96Smrg } NEXT_OPCODE(); 32075dfecf96Smrg 32085dfecf96SmrgOPCODE_LABEL(XBC_NTHCDR): 32095dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 32105dfecf96Smrg if (!FIXNUMP(reg1) || (fixnum = FIXNUM_VALUE(reg1)) < 0) 32115dfecf96Smrg LispDestroy("NTHCDR: %s is not a positive fixnum", 32125dfecf96Smrg STROBJ(reg1)); 32135dfecf96Smrg if (reg0 != NIL) { 32145dfecf96Smrg if (!CONSP(reg0)) 32155dfecf96Smrg LispDestroy("NTHCDR: %s is not a list", STROBJ(reg0)); 32165dfecf96Smrg for (; fixnum > 0; fixnum--) { 32175dfecf96Smrg if (!CONSP(reg0)) 32185dfecf96Smrg break; 32195dfecf96Smrg reg0 = CDR(reg0); 32205dfecf96Smrg } 32215dfecf96Smrg } 32225dfecf96Smrg NEXT_OPCODE(); 32235dfecf96Smrg 32245dfecf96Smrg /* Push to builtin stack */ 32255dfecf96SmrgOPCODE_LABEL(XBC_CAR_PUSH): 32265dfecf96Smrg if (reg0 != NIL) { 32275dfecf96Smrg if (!CONSP(reg0)) 32285dfecf96Smrg LispDestroy("CAR: %s is not a list", STROBJ(reg0)); 32295dfecf96Smrg reg0 = CAR(reg0); 32305dfecf96Smrg } 32315dfecf96Smrg goto push_builtin; 32325dfecf96Smrg 32335dfecf96SmrgOPCODE_LABEL(XBC_CDR_PUSH): 32345dfecf96Smrg if (reg0 != NIL) { 32355dfecf96Smrg if (!CONSP(reg0)) 32365dfecf96Smrg LispDestroy("CDR: %s is not a list", STROBJ(reg0)); 32375dfecf96Smrg reg0 = CDR(reg0); 32385dfecf96Smrg } 32395dfecf96Smrg /*FALLTROUGH*/ 32405dfecf96Smrg 32415dfecf96SmrgOPCODE_LABEL(XBC_PUSH): 32425dfecf96Smrgpush_builtin: 32435dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = reg0; 32445dfecf96Smrg NEXT_OPCODE(); 32455dfecf96Smrg 32465dfecf96SmrgOPCODE_LABEL(XBC_PUSH_NIL): 32475dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = NIL; 32485dfecf96Smrg NEXT_OPCODE(); 32495dfecf96Smrg 32505dfecf96SmrgOPCODE_LABEL(XBC_PUSH_UNSPEC): 32515dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = UNSPEC; 32525dfecf96Smrg NEXT_OPCODE(); 32535dfecf96Smrg 32545dfecf96SmrgOPCODE_LABEL(XBC_PUSH_T): 32555dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = T; 32565dfecf96Smrg NEXT_OPCODE(); 32575dfecf96Smrg 32585dfecf96SmrgOPCODE_LABEL(XBC_PUSH_NIL_N): 32595dfecf96Smrg for (offset = *stream++; offset > 0; offset--) 32605dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = NIL; 32615dfecf96Smrg NEXT_OPCODE(); 32625dfecf96Smrg 32635dfecf96SmrgOPCODE_LABEL(XBC_PUSH_UNSPEC_N): 32645dfecf96Smrg for (offset = *stream++; offset > 0; offset--) 32655dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = UNSPEC; 32665dfecf96Smrg NEXT_OPCODE(); 32675dfecf96Smrg 32685dfecf96SmrgOPCODE_LABEL(XBC_LET): 32695dfecf96Smrglet_argument: 32705dfecf96Smrg /* The global object value is not changed, so it does not 32715dfecf96Smrg * matter if it is a constant symbol. An error would be 32725dfecf96Smrg * generated if it was declared as constant at the time of 32735dfecf96Smrg * bytecode generation. Check can be done looking at the 32745dfecf96Smrg * atom->constant field. */ 32755dfecf96Smrg atom = symbols[*stream++]; 32765dfecf96Smrg atom->offset = lisp__data.env.length; 32775dfecf96Smrg lisp__data.env.names[lisp__data.env.length] = atom->string; 32785dfecf96Smrg lisp__data.env.values[lisp__data.env.length++] = reg0; 32795dfecf96Smrg NEXT_OPCODE(); 32805dfecf96Smrg 32815dfecf96SmrgOPCODE_LABEL(XBC_LETX): 32825dfecf96Smrgletx_argument: 32835dfecf96Smrg atom = symbols[*stream++]; 32845dfecf96Smrg atom->offset = lisp__data.env.length; 32855dfecf96Smrg lisp__data.env.names[lisp__data.env.length] = atom->string; 32865dfecf96Smrg lisp__data.env.values[lisp__data.env.length++] = reg0; 32875dfecf96Smrg lisp__data.env.head++; 32885dfecf96Smrg NEXT_OPCODE(); 32895dfecf96Smrg 32905dfecf96SmrgOPCODE_LABEL(XBC_LET_NIL): 32915dfecf96Smrg atom = symbols[*stream++]; 32925dfecf96Smrg atom->offset = lisp__data.env.length; 32935dfecf96Smrg lisp__data.env.names[lisp__data.env.length] = atom->string; 32945dfecf96Smrg lisp__data.env.values[lisp__data.env.length++] = NIL; 32955dfecf96Smrg NEXT_OPCODE(); 32965dfecf96Smrg 32975dfecf96SmrgOPCODE_LABEL(XBC_LETX_NIL): 32985dfecf96Smrg atom = symbols[*stream++]; 32995dfecf96Smrg atom->offset = lisp__data.env.length; 33005dfecf96Smrg lisp__data.env.names[lisp__data.env.length] = atom->string; 33015dfecf96Smrg lisp__data.env.values[lisp__data.env.length++] = NIL; 33025dfecf96Smrg lisp__data.env.head++; 33035dfecf96Smrg NEXT_OPCODE(); 33045dfecf96Smrg 33055dfecf96Smrg /* Bind locally added variables to a block */ 33065dfecf96SmrgOPCODE_LABEL(XBC_LETBIND): 33075dfecf96Smrg offset = *stream++; 33085dfecf96Smrg lisp__data.env.head += offset; 33095dfecf96Smrg NEXT_OPCODE(); 33105dfecf96Smrg 33115dfecf96Smrg /* Unbind locally added variables to a block */ 33125dfecf96SmrgOPCODE_LABEL(XBC_UNLET): 33135dfecf96Smrg offset = *stream++; 33145dfecf96Smrg lisp__data.env.head -= offset; 33155dfecf96Smrg lisp__data.env.length -= offset; 33165dfecf96Smrg NEXT_OPCODE(); 33175dfecf96Smrg 33185dfecf96Smrg /* Load value from stack */ 33195dfecf96SmrgOPCODE_LABEL(XBC_LOAD): 33205dfecf96Smrg offset = *stream++; 33215dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33225dfecf96Smrg NEXT_OPCODE(); 33235dfecf96Smrg 33245dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CAR): 33255dfecf96Smrg offset = *stream++; 33265dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33275dfecf96Smrg goto car; 33285dfecf96Smrg 33295dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CDR): 33305dfecf96Smrg offset = *stream++; 33315dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33325dfecf96Smrg goto cdr; 33335dfecf96Smrg 33345dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CAR_STORE): 33355dfecf96Smrg offset = *stream++; 33365dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33375dfecf96Smrg if (reg0 != NIL) { 33385dfecf96Smrg if (!CONSP(reg0)) 33395dfecf96Smrg LispDestroy("CAR: %s is not a list", STROBJ(reg0)); 33405dfecf96Smrg reg0 = CAR(reg0); 33415dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = reg0; 33425dfecf96Smrg } 33435dfecf96Smrg NEXT_OPCODE(); 33445dfecf96Smrg 33455dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CDR_STORE): 33465dfecf96Smrg offset = *stream++; 33475dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33485dfecf96Smrg if (reg0 != NIL) { 33495dfecf96Smrg if (!CONSP(reg0)) 33505dfecf96Smrg LispDestroy("CDR: %s is not a list", STROBJ(reg0)); 33515dfecf96Smrg reg0 = CDR(reg0); 33525dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = reg0; 33535dfecf96Smrg } 33545dfecf96Smrg NEXT_OPCODE(); 33555dfecf96Smrg 33565dfecf96SmrgOPCODE_LABEL(XBC_LOAD_LET): 33575dfecf96Smrg offset = *stream++; 33585dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33595dfecf96Smrg goto let_argument; 33605dfecf96Smrg 33615dfecf96SmrgOPCODE_LABEL(XBC_LOAD_LETX): 33625dfecf96Smrg offset = *stream++; 33635dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33645dfecf96Smrg goto letx_argument; 33655dfecf96Smrg 33665dfecf96SmrgOPCODE_LABEL(XBC_LOAD_PUSH): 33675dfecf96Smrg offset = *stream++; 33685dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33695dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = reg0; 33705dfecf96Smrg NEXT_OPCODE(); 33715dfecf96Smrg 33725dfecf96Smrg /* Load pointer to constant */ 33735dfecf96SmrgOPCODE_LABEL(XBC_LOADCON): 33745dfecf96Smrg reg0 = constants[*stream++]; 33755dfecf96Smrg NEXT_OPCODE(); 33765dfecf96Smrg 33775dfecf96SmrgOPCODE_LABEL(XBC_LOADCON_LET): 33785dfecf96Smrg reg0 = constants[*stream++]; 33795dfecf96Smrg goto let_argument; 33805dfecf96Smrg 33815dfecf96SmrgOPCODE_LABEL(XBC_LOADCON_LETX): 33825dfecf96Smrg reg0 = constants[*stream++]; 33835dfecf96Smrg goto letx_argument; 33845dfecf96Smrg 33855dfecf96SmrgOPCODE_LABEL(XBC_LOADCON_PUSH): 33865dfecf96Smrg reg0 = constants[*stream++]; 33875dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = reg0; 33885dfecf96Smrg NEXT_OPCODE(); 33895dfecf96Smrg 33905dfecf96SmrgOPCODE_LABEL(XBC_LOADCON_SET): 33915dfecf96Smrg reg0 = constants[*stream++]; 33925dfecf96Smrg offset = *stream++; 33935dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = reg0; 33945dfecf96Smrg NEXT_OPCODE(); 33955dfecf96Smrg 33965dfecf96Smrg /* Change value of local variable */ 33975dfecf96SmrgOPCODE_LABEL(XBC_CAR_SET): 33985dfecf96Smrgcar_set: 33995dfecf96Smrg if (reg0 != NIL) { 34005dfecf96Smrg if (!CONSP(reg0)) 34015dfecf96Smrg LispDestroy("CAR: %s is not a list", STROBJ(reg0)); 34025dfecf96Smrg reg0 = CAR(reg0); 34035dfecf96Smrg } 34045dfecf96Smrg goto set_local_variable; 34055dfecf96Smrg 34065dfecf96SmrgOPCODE_LABEL(XBC_CDR_SET): 34075dfecf96Smrgcdr_set: 34085dfecf96Smrg if (reg0 != NIL) { 34095dfecf96Smrg if (!CONSP(reg0)) 34105dfecf96Smrg LispDestroy("CDR: %s is not a list", STROBJ(reg0)); 34115dfecf96Smrg reg0 = CDR(reg0); 34125dfecf96Smrg } 34135dfecf96Smrg goto set_local_variable; 34145dfecf96Smrg 34155dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CAR_SET): 34165dfecf96Smrg offset = *stream++; 34175dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 34185dfecf96Smrg goto car_set; 34195dfecf96Smrg 34205dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CDR_SET): 34215dfecf96Smrg offset = *stream++; 34225dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 34235dfecf96Smrg goto cdr_set; 34245dfecf96Smrg 34255dfecf96SmrgOPCODE_LABEL(XBC_LOAD_SET): 34265dfecf96Smrg offset = *stream++; 34275dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 34285dfecf96Smrg /*FALLTROUGH*/ 34295dfecf96Smrg 34305dfecf96SmrgOPCODE_LABEL(XBC_SET): 34315dfecf96Smrgset_local_variable: 34325dfecf96Smrg offset = *stream++; 34335dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = reg0; 34345dfecf96Smrg NEXT_OPCODE(); 34355dfecf96Smrg 34365dfecf96SmrgOPCODE_LABEL(XBC_SET_NIL): 34375dfecf96Smrg offset = *stream++; 34385dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = NIL; 34395dfecf96Smrg NEXT_OPCODE(); 34405dfecf96Smrg 34415dfecf96Smrg /* Change value of a global/special variable */ 34425dfecf96SmrgOPCODE_LABEL(XBC_SETSYM): 34435dfecf96Smrg atom = symbols[*stream++]; 34445dfecf96Smrg if (atom->dyn) { 34455dfecf96Smrg /* atom->dyn and atom->constant are exclusive, no 34465dfecf96Smrg * need to check if variable declared as constant. */ 34475dfecf96Smrg if (atom->offset < lisp__data.env.head && 34485dfecf96Smrg lisp__data.env.names[atom->offset] == atom->string) 34495dfecf96Smrg lisp__data.env.values[atom->offset] = reg0; 34505dfecf96Smrg else { 34515dfecf96Smrg if (atom->watch) 34525dfecf96Smrg LispSetAtomObjectProperty(atom, reg0); 34535dfecf96Smrg else 34545dfecf96Smrg SETVALUE(atom, reg0); 34555dfecf96Smrg } 34565dfecf96Smrg } 34575dfecf96Smrg else if (atom->a_object) { 34585dfecf96Smrg if (atom->constant) 34595dfecf96Smrg LispDestroy("EVAL: %s is a constant", 34605dfecf96Smrg STROBJ(atom->object)); 34615dfecf96Smrg else if (atom->watch) 34625dfecf96Smrg LispSetAtomObjectProperty(atom, reg0); 34635dfecf96Smrg else 34645dfecf96Smrg SETVALUE(atom, reg0); 34655dfecf96Smrg } 34665dfecf96Smrg else { 34675dfecf96Smrg /* Create new global variable */ 34685dfecf96Smrg LispPackage *pack; 34695dfecf96Smrg 34705dfecf96Smrg LispWarning("the variable %s was not declared", 34715dfecf96Smrg atom->string); 34725dfecf96Smrg LispSetAtomObjectProperty(atom, reg0); 34735dfecf96Smrg pack = atom->package->data.package.package; 34745dfecf96Smrg if (pack->glb.length >= pack->glb.space) 34755dfecf96Smrg LispMoreGlobals(pack); 34765dfecf96Smrg pack->glb.pairs[pack->glb.length++] = atom->object; 34775dfecf96Smrg } 34785dfecf96Smrg NEXT_OPCODE(); 34795dfecf96Smrg 34805dfecf96Smrg/* Resolve symbol value at runtime */ 34815dfecf96Smrg#define LOAD_SYMBOL_VALUE() \ 34825dfecf96Smrg atom = symbols[*stream++]; \ 34835dfecf96Smrg if (atom->dyn) { \ 34845dfecf96Smrg if (atom->offset < lisp__data.env.head && \ 34855dfecf96Smrg lisp__data.env.names[atom->offset] == atom->string) \ 34865dfecf96Smrg reg0 = lisp__data.env.values[atom->offset]; \ 34875dfecf96Smrg else { \ 34885dfecf96Smrg reg0 = atom->property->value; \ 34895dfecf96Smrg if (reg0 == UNBOUND) \ 34905dfecf96Smrg LispDestroy("EVAL: the symbol %s is unbound", \ 34915dfecf96Smrg STROBJ(atom->object)); \ 34925dfecf96Smrg } \ 34935dfecf96Smrg } \ 34945dfecf96Smrg else { \ 34955dfecf96Smrg if (atom->a_object) \ 34965dfecf96Smrg reg0 = atom->property->value; \ 34975dfecf96Smrg else \ 34985dfecf96Smrg LispDestroy("EVAL: the symbol %s is unbound", \ 34995dfecf96Smrg STROBJ(atom->object)); \ 35005dfecf96Smrg } 35015dfecf96Smrg 35025dfecf96SmrgOPCODE_LABEL(XBC_LOADSYM): 35035dfecf96Smrg LOAD_SYMBOL_VALUE(); 35045dfecf96Smrg NEXT_OPCODE(); 35055dfecf96Smrg 35065dfecf96SmrgOPCODE_LABEL(XBC_LOADSYM_LET): 35075dfecf96Smrg LOAD_SYMBOL_VALUE(); 35085dfecf96Smrg goto let_argument; 35095dfecf96Smrg 35105dfecf96SmrgOPCODE_LABEL(XBC_LOADSYM_LETX): 35115dfecf96Smrg LOAD_SYMBOL_VALUE(); 35125dfecf96Smrg goto letx_argument; 35135dfecf96Smrg 35145dfecf96SmrgOPCODE_LABEL(XBC_LOADSYM_PUSH): 35155dfecf96Smrg LOAD_SYMBOL_VALUE(); 35165dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = reg0; 35175dfecf96Smrg NEXT_OPCODE(); 35185dfecf96Smrg 35195dfecf96Smrg /* Builtin function */ 35205dfecf96SmrgOPCODE_LABEL(XBC_CALL): 35215dfecf96Smrg offset = *stream++; 35225dfecf96Smrg lisp__data.stack.base = lisp__data.stack.length - offset; 35235dfecf96Smrg builtin = builtins[*stream++]; 35245dfecf96Smrg if (builtin->multiple_values) { 35255dfecf96Smrg RETURN_COUNT = 0; 35265dfecf96Smrg reg0 = builtin->function(builtin); 35275dfecf96Smrg } 35285dfecf96Smrg else { 35295dfecf96Smrg reg0 = builtin->function(builtin); 35305dfecf96Smrg RETURN_COUNT = 0; 35315dfecf96Smrg } 35325dfecf96Smrg lisp__data.stack.length -= offset; 35335dfecf96Smrg NEXT_OPCODE(); 35345dfecf96Smrg 35355dfecf96SmrgOPCODE_LABEL(XBC_CALL_SET): 35365dfecf96Smrg offset = *stream++; 35375dfecf96Smrg lisp__data.stack.base = lisp__data.stack.length - offset; 35385dfecf96Smrg builtin = builtins[*stream++]; 35395dfecf96Smrg if (builtin->multiple_values) { 35405dfecf96Smrg RETURN_COUNT = 0; 35415dfecf96Smrg reg0 = builtin->function(builtin); 35425dfecf96Smrg } 35435dfecf96Smrg else { 35445dfecf96Smrg reg0 = builtin->function(builtin); 35455dfecf96Smrg RETURN_COUNT = 0; 35465dfecf96Smrg } 35475dfecf96Smrg lisp__data.stack.length -= offset; 35485dfecf96Smrg offset = *stream++; 35495dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = reg0; 35505dfecf96Smrg NEXT_OPCODE(); 35515dfecf96Smrg 35525dfecf96Smrg /* Bytecode call */ 35535dfecf96SmrgOPCODE_LABEL(XBC_BYTECALL): 35545dfecf96Smrg lex = lisp__data.env.lex; 35555dfecf96Smrg offset = *stream++; 35565dfecf96Smrg lisp__data.env.head = lisp__data.env.length; 35575dfecf96Smrg len = lisp__data.env.lex = lisp__data.env.length - offset; 35585dfecf96Smrg reg0 = ExecuteBytecode(codes[*stream++]); 35595dfecf96Smrg lisp__data.env.length = lisp__data.env.head = len; 35605dfecf96Smrg lisp__data.env.lex = lex; 35615dfecf96Smrg NEXT_OPCODE(); 35625dfecf96Smrg 35635dfecf96Smrg /* Unimplemented function/macro call */ 35645dfecf96SmrgOPCODE_LABEL(XBC_FUNCALL): 35655dfecf96Smrg lambda = constants[*stream++]; 35665dfecf96Smrg arguments = constants[*stream++]; 35675dfecf96Smrg reg0 = LispFuncall(lambda, arguments, 1); 35685dfecf96Smrg NEXT_OPCODE(); 35695dfecf96Smrg 35705dfecf96SmrgOPCODE_LABEL(XBC_JUMP): 35715dfecf96Smrg stream += *(signed short*)stream; 35725dfecf96Smrg NEXT_OPCODE(); 35735dfecf96Smrg 35745dfecf96SmrgOPCODE_LABEL(XBC_JUMPT): 35755dfecf96Smrg if (reg0 != NIL) 35765dfecf96Smrg stream += *(signed short*)stream; 35775dfecf96Smrg else 35785dfecf96Smrg /* skip jump relative offset */ 35795dfecf96Smrg stream += sizeof(signed short); 35805dfecf96Smrg NEXT_OPCODE(); 35815dfecf96Smrg 35825dfecf96SmrgOPCODE_LABEL(XBC_JUMPNIL): 35835dfecf96Smrg if (reg0 == NIL) 35845dfecf96Smrg stream += *(signed short*)stream; 35855dfecf96Smrg else 35865dfecf96Smrg /* skip jump relative offset */ 35875dfecf96Smrg stream += sizeof(signed short); 35885dfecf96Smrg NEXT_OPCODE(); 35895dfecf96Smrg 35905dfecf96Smrg /* Build CONS of two constant arguments */ 35915dfecf96SmrgOPCODE_LABEL(XBC_CCONS): 35925dfecf96Smrg reg0 = constants[*stream++]; 35935dfecf96Smrg reg1 = constants[*stream++]; 35945dfecf96Smrg reg0 = CONS(reg0, reg1); 35955dfecf96Smrg NEXT_OPCODE(); 35965dfecf96Smrg 35975dfecf96Smrg /* Start CONS */ 35985dfecf96SmrgOPCODE_LABEL(XBC_CSTAR): 35995dfecf96Smrg /* This the CAR of the CONS */ 36005dfecf96Smrg lisp__data.protect.objects[phead++] = reg0; 36015dfecf96Smrg NEXT_OPCODE(); 36025dfecf96Smrg 36035dfecf96Smrg /* Finish CONS */ 36045dfecf96SmrgOPCODE_LABEL(XBC_CFINI): 36055dfecf96Smrg reg0 = CONS(lisp__data.protect.objects[--phead], reg0); 36065dfecf96Smrg NEXT_OPCODE(); 36075dfecf96Smrg 36085dfecf96Smrg /* Start building list */ 36095dfecf96SmrgOPCODE_LABEL(XBC_LSTAR): 36105dfecf96Smrg reg1 = CONS(reg0, NIL); 36115dfecf96Smrg /* Start of list stored here */ 36125dfecf96Smrg lisp__data.protect.objects[phead++] = reg1; 36135dfecf96Smrg /* Tail of list stored here */ 36145dfecf96Smrg lisp__data.protect.objects[phead++] = reg1; 36155dfecf96Smrg NEXT_OPCODE(); 36165dfecf96Smrg 36175dfecf96Smrg /* Add to list */ 36185dfecf96SmrgOPCODE_LABEL(XBC_LCONS): 36195dfecf96Smrg reg1 = lisp__data.protect.objects[phead - 2]; 36205dfecf96Smrg RPLACD(reg1, CONS(reg0, NIL)); 36215dfecf96Smrg lisp__data.protect.objects[phead - 2] = CDR(reg1); 36225dfecf96Smrg NEXT_OPCODE(); 36235dfecf96Smrg 36245dfecf96Smrg /* Finish list */ 36255dfecf96SmrgOPCODE_LABEL(XBC_LFINI): 36265dfecf96Smrg phead -= 2; 36275dfecf96Smrg reg0 = lisp__data.protect.objects[phead + 1]; 36285dfecf96Smrg NEXT_OPCODE(); 36295dfecf96Smrg 36305dfecf96SmrgOPCODE_LABEL(XBC_STRUCT): 36315dfecf96Smrg offset = *stream++; 36325dfecf96Smrg reg1 = constants[*stream++]; 36335dfecf96Smrg if (!STRUCTP(reg0) || reg0->data.struc.def != reg1) { 36345dfecf96Smrg char *name = ATOMID(CAR(reg1)); 36355dfecf96Smrg 36365dfecf96Smrg for (reg1 = CDR(reg1); offset; offset--) 36375dfecf96Smrg reg1 = CDR(reg1); 36385dfecf96Smrg LispDestroy("%s-%s: %s is not a %s", 36395dfecf96Smrg name, ATOMID(CAR(reg1)), STROBJ(reg0), name); 36405dfecf96Smrg } 36415dfecf96Smrg for (reg0 = reg0->data.struc.fields; offset; offset--) 36425dfecf96Smrg reg0 = CDR(reg0); 36435dfecf96Smrg reg0 = CAR(reg0); 36445dfecf96Smrg NEXT_OPCODE(); 36455dfecf96Smrg 36465dfecf96SmrgOPCODE_LABEL(XBC_STRUCTP): 36475dfecf96Smrg reg1 = constants[*stream++]; 36485dfecf96Smrg reg0 = STRUCTP(reg0) && reg0->data.struc.def == reg1 ? T : NIL; 36495dfecf96Smrg NEXT_OPCODE(); 36505dfecf96Smrg 36515dfecf96SmrgOPCODE_LABEL(XBC_LETREC): 36525dfecf96Smrg /* XXX could/should optimize, shouldn't need to parse 36535dfecf96Smrg * the bytecode header again */ 36545dfecf96Smrg lex = lisp__data.env.lex; 36555dfecf96Smrg offset = *stream++; 36565dfecf96Smrg lisp__data.env.head = lisp__data.env.length; 36575dfecf96Smrg len = lisp__data.env.lex = lisp__data.env.length - offset; 36585dfecf96Smrg reg0 = ExecuteBytecode(bytecode); 36595dfecf96Smrg lisp__data.env.length = lisp__data.env.head = len; 36605dfecf96Smrg lisp__data.env.lex = lex; 36615dfecf96Smrg NEXT_OPCODE(); 36625dfecf96Smrg 36635dfecf96SmrgOPCODE_LABEL(XBC_RETURN): 36645dfecf96Smrg lisp__data.protect.length = pbase; 36655dfecf96Smrg return (reg0); 36665dfecf96Smrg 36675dfecf96Smrg#ifndef ALLOW_GOTO_ADDRESS 36685dfecf96Smrg } /* end of switch */ 36695dfecf96Smrg 36705dfecf96Smrgpredicate_label: 36715dfecf96Smrg switch (*stream++) { 36725dfecf96Smrg#endif 36735dfecf96Smrg 36745dfecf96SmrgOPCODE_LABEL(XBP_CONSP): 36755dfecf96Smrg reg0 = CONSP(reg0) ? T : NIL; 36765dfecf96Smrg NEXT_OPCODE(); 36775dfecf96Smrg 36785dfecf96SmrgOPCODE_LABEL(XBP_LISTP): 36795dfecf96Smrg reg0 = LISTP(reg0) ? T : NIL; 36805dfecf96Smrg NEXT_OPCODE(); 36815dfecf96Smrg 36825dfecf96SmrgOPCODE_LABEL(XBP_NUMBERP): 36835dfecf96Smrg reg0 = NUMBERP(reg0) ? T : NIL; 36845dfecf96Smrg NEXT_OPCODE(); 36855dfecf96Smrg 36865dfecf96Smrg#ifndef ALLOW_GOTO_ADDRESS 36875dfecf96Smrg } /* end of switch */ 36885dfecf96Smrg } 36895dfecf96Smrg#endif 36905dfecf96Smrg 36915dfecf96Smrg /*NOTREACHED*/ 36925dfecf96Smrg return (reg0); 36935dfecf96Smrg} 3694