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)) { 554f14f4646Smrg case LispFunction_t: 555f14f4646Smrg function = function->data.atom->object; 5565dfecf96Smrg case LispAtom_t: 5575dfecf96Smrg name = function; 5585dfecf96Smrg atom = function->data.atom; 5595dfecf96Smrg alist = atom->property->alist; 5605dfecf96Smrg if (atom->a_builtin) { 5615dfecf96Smrg xbuiltin = atom->property->fun.builtin; 5625dfecf96Smrg macro = xbuiltin->type == LispMacro; 5635dfecf96Smrg } 5645dfecf96Smrg else if (atom->a_compiled) 5655dfecf96Smrg bytecode = atom->property->fun.function; 5665dfecf96Smrg else if (atom->a_function) { 5675dfecf96Smrg lambda = atom->property->fun.function; 5685dfecf96Smrg macro = lambda->funtype == LispMacro; 5695dfecf96Smrg } 5705dfecf96Smrg else if (atom->a_defstruct && 5715dfecf96Smrg atom->property->structure.function != STRUCT_NAME) { 5725dfecf96Smrg if (atom->property->structure.function == STRUCT_CONSTRUCTOR) 5735dfecf96Smrg atom = Omake_struct->data.atom; 5745dfecf96Smrg else if (atom->property->structure.function == STRUCT_CHECK) 5755dfecf96Smrg atom = Ostruct_type->data.atom; 5765dfecf96Smrg else 5775dfecf96Smrg atom = Ostruct_access->data.atom; 5785dfecf96Smrg xbuiltin = atom->property->fun.builtin; 5795dfecf96Smrg } 5805dfecf96Smrg else 5815dfecf96Smrg LispDestroy("%s: the function %s is not defined", 5825dfecf96Smrg STRFUN(builtin), STROBJ(function)); 5835dfecf96Smrg break; 5845dfecf96Smrg case LispBytecode_t: 5855dfecf96Smrg name = Olambda; 5865dfecf96Smrg bytecode = function; 5875dfecf96Smrg break; 5885dfecf96Smrg case LispLambda_t: 5895dfecf96Smrg name = Olambda; 5905dfecf96Smrg alist = (LispArgList*)function->data.lambda.name->data.opaque.data; 5915dfecf96Smrg break; 5925dfecf96Smrg case LispCons_t: 5935dfecf96Smrg if (CAR(function) == Olambda) { 5945dfecf96Smrg function = EVAL(function); 5955dfecf96Smrg if (OBJECT_TYPE(function) == LispLambda_t) { 5965dfecf96Smrg name = Olambda; 5975dfecf96Smrg alist = (LispArgList*) 5985dfecf96Smrg function->data.lambda.name->data.opaque.data; 5995dfecf96Smrg break; 6005dfecf96Smrg } 6015dfecf96Smrg } 6025dfecf96Smrg default: 6035dfecf96Smrg LispDestroy("%s: %s is not a function", 6045dfecf96Smrg STRFUN(builtin), STROBJ(function)); 6055dfecf96Smrg break; 6065dfecf96Smrg } 6075dfecf96Smrg 6085dfecf96Smrg if (xbuiltin) { 6095dfecf96Smrg LispWriteStr(NIL, "Builtin ", 8); 6105dfecf96Smrg if (macro) 6115dfecf96Smrg LispWriteStr(NIL, "macro ", 6); 6125dfecf96Smrg else 6135dfecf96Smrg LispWriteStr(NIL, "function ", 9); 6145dfecf96Smrg } 6155dfecf96Smrg else if (macro) 6165dfecf96Smrg LispWriteStr(NIL, "Macro ", 6); 6175dfecf96Smrg else 6185dfecf96Smrg LispWriteStr(NIL, "Function ", 9); 6195dfecf96Smrg LispWriteObject(NIL, name); 6205dfecf96Smrg LispWriteStr(NIL, ":\n", 2); 6215dfecf96Smrg 6225dfecf96Smrg if (alist) { 6235dfecf96Smrg int i; 6245dfecf96Smrg 6255dfecf96Smrg sprintf(buffer, "%d required argument%s", 6265dfecf96Smrg alist->normals.num_symbols, 6275dfecf96Smrg alist->normals.num_symbols != 1 ? "s" : ""); 6285dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 6295dfecf96Smrg for (i = 0; i < alist->normals.num_symbols; i++) { 6305dfecf96Smrg LispWriteChar(NIL, i ? ',' : ':'); 6315dfecf96Smrg LispWriteChar(NIL, ' '); 632f14f4646Smrg LispWriteStr(NIL, ATOMID(alist->normals.symbols[i])->value, 633f14f4646Smrg ATOMID(alist->normals.symbols[i])->length); 6345dfecf96Smrg } 6355dfecf96Smrg LispWriteChar(NIL, '\n'); 6365dfecf96Smrg 6375dfecf96Smrg sprintf(buffer, "%d optional argument%s", 6385dfecf96Smrg alist->optionals.num_symbols, 6395dfecf96Smrg alist->optionals.num_symbols != 1 ? "s" : ""); 6405dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 6415dfecf96Smrg for (i = 0; i < alist->optionals.num_symbols; i++) { 6425dfecf96Smrg LispWriteChar(NIL, i ? ',' : ':'); 6435dfecf96Smrg LispWriteChar(NIL, ' '); 644f14f4646Smrg LispWriteStr(NIL, ATOMID(alist->optionals.symbols[i])->value, 645f14f4646Smrg ATOMID(alist->optionals.symbols[i])->length); 6465dfecf96Smrg } 6475dfecf96Smrg LispWriteChar(NIL, '\n'); 6485dfecf96Smrg 6495dfecf96Smrg sprintf(buffer, "%d keyword parameter%s", 6505dfecf96Smrg alist->keys.num_symbols, 6515dfecf96Smrg alist->keys.num_symbols != 1 ? "s" : ""); 6525dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 6535dfecf96Smrg for (i = 0; i < alist->keys.num_symbols; i++) { 6545dfecf96Smrg LispWriteChar(NIL, i ? ',' : ':'); 6555dfecf96Smrg LispWriteChar(NIL, ' '); 6565dfecf96Smrg LispWriteObject(NIL, alist->keys.symbols[i]); 6575dfecf96Smrg } 6585dfecf96Smrg LispWriteChar(NIL, '\n'); 6595dfecf96Smrg 6605dfecf96Smrg if (alist->rest) { 6615dfecf96Smrg LispWriteStr(NIL, "Rest argument: ", 15); 662f14f4646Smrg LispWriteStr(NIL, ATOMID(alist->rest)->value, 663f14f4646Smrg ATOMID(alist->rest)->length); 6645dfecf96Smrg LispWriteChar(NIL, '\n'); 6655dfecf96Smrg } 6665dfecf96Smrg else 6675dfecf96Smrg LispWriteStr(NIL, "No rest argument\n", 17); 6685dfecf96Smrg } 6695dfecf96Smrg 6705dfecf96Smrg if (bytecode) { 671f14f4646Smrg Atom_id id; 6725dfecf96Smrg char *ptr; 6735dfecf96Smrg int *offsets[4]; 6745dfecf96Smrg int i, done, j, sym0, sym1, con0, con1, bui0, byt0, strd, strf; 6755dfecf96Smrg LispObj **constants; 6765dfecf96Smrg LispAtom **symbols; 6775dfecf96Smrg LispBuiltin **builtins; 6785dfecf96Smrg LispObj **names; 6795dfecf96Smrg short stack, num_constants, num_symbols, num_builtins, num_bytecodes; 6805dfecf96Smrg unsigned char *base, *stream = bytecode->data.bytecode.bytecode->code; 6815dfecf96Smrg 6825dfecf96Smrg LispWriteStr(NIL, "\nBytecode header:\n", 18); 6835dfecf96Smrg 6845dfecf96Smrg /* Header information */ 6855dfecf96Smrg stack = *(short*)stream; 6865dfecf96Smrg stream += sizeof(short); 6875dfecf96Smrg sprintf(buffer, "%d element%s used in the stack\n", 6885dfecf96Smrg stack, stack != 1 ? "s" : ""); 6895dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 6905dfecf96Smrg stack = *(short*)stream; 6915dfecf96Smrg stream += sizeof(short); 6925dfecf96Smrg sprintf(buffer, "%d element%s used in the builtin stack\n", 6935dfecf96Smrg stack, stack != 1 ? "s" : ""); 6945dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 6955dfecf96Smrg stack = *(short*)stream; 6965dfecf96Smrg stream += sizeof(short); 6975dfecf96Smrg sprintf(buffer, "%d element%s used in the protected stack\n", 6985dfecf96Smrg stack, stack != 1 ? "s" : ""); 6995dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 7005dfecf96Smrg 7015dfecf96Smrg num_constants = *(short*)stream; 7025dfecf96Smrg stream += sizeof(short); 7035dfecf96Smrg num_symbols = *(short*)stream; 7045dfecf96Smrg stream += sizeof(short); 7055dfecf96Smrg num_builtins = *(short*)stream; 7065dfecf96Smrg stream += sizeof(short); 7075dfecf96Smrg num_bytecodes = *(short*)stream; 7085dfecf96Smrg stream += sizeof(short); 7095dfecf96Smrg 7105dfecf96Smrg constants = (LispObj**)stream; 7115dfecf96Smrg stream += num_constants * sizeof(LispObj*); 7125dfecf96Smrg symbols = (LispAtom**)stream; 7135dfecf96Smrg stream += num_symbols * sizeof(LispAtom*); 7145dfecf96Smrg builtins = (LispBuiltin**)stream; 7155dfecf96Smrg stream += num_builtins * sizeof(LispBuiltin*); 7165dfecf96Smrg stream += num_bytecodes * sizeof(unsigned char*); 7175dfecf96Smrg names = (LispObj**)stream; 7185dfecf96Smrg stream += num_bytecodes * sizeof(LispObj*); 7195dfecf96Smrg 7205dfecf96Smrg for (i = 0; i < num_constants; i++) { 7215dfecf96Smrg sprintf(buffer, "Constant %d = %s\n", i, STROBJ(constants[i])); 7225dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 7235dfecf96Smrg } 7245dfecf96Smrg 7255dfecf96Smrg/* Macro XSTRING avoids some noisy in the output, if it were defined as 7265dfecf96Smrg * #define XSTRING(object) object ? STROBJ(object) : #<UNBOUND> 7275dfecf96Smrg * and called as XSTRING(atom->object) 7285dfecf96Smrg * it would also print the package name were the symbol was first defined, 7295dfecf96Smrg * but for local variables, only the symbol string is important. */ 730f14f4646Smrg#define XSTRING(key) key ? key->value : "#<UNBOUND>" 7315dfecf96Smrg 7325dfecf96Smrg for (i = 0; i < num_symbols; i++) { 7335dfecf96Smrg sprintf(buffer, "Symbol %d = %s\n", 734f14f4646Smrg i, XSTRING(symbols[i]->key)); 7355dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 7365dfecf96Smrg } 7375dfecf96Smrg for (i = 0; i < num_builtins; i++) { 7385dfecf96Smrg sprintf(buffer, "Builtin %d = %s\n", 7395dfecf96Smrg i, STROBJ(builtins[i]->symbol)); 7405dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 7415dfecf96Smrg } 7425dfecf96Smrg for (i = 0; i < num_bytecodes; i++) { 7435dfecf96Smrg sprintf(buffer, "Bytecode %d = %s\n", 7445dfecf96Smrg i, STROBJ(names[i])); 7455dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 7465dfecf96Smrg } 7475dfecf96Smrg 7485dfecf96Smrg /* Make readability slightly easier printing the names of local 7495dfecf96Smrg * variables where it's offset is known, i.e. function arguments. */ 7505dfecf96Smrg if (alist) { 7515dfecf96Smrg if (alist->num_arguments == 0) 7525dfecf96Smrg LispWriteStr(NIL, "\nNo initial stack\n", 18); 7535dfecf96Smrg else { 7545dfecf96Smrg int len1, len2; 7555dfecf96Smrg 7565dfecf96Smrg j = 0; 7575dfecf96Smrg LispWriteStr(NIL, "\nInitial stack:\n", 16); 7585dfecf96Smrg 7595dfecf96Smrg for (i = 0; i < alist->normals.num_symbols; i++, j++) { 7605dfecf96Smrg sprintf(buffer, "%d = ", j); 7615dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 762f14f4646Smrg id = alist->normals.symbols[i]->data.atom->key; 763f14f4646Smrg LispWriteStr(NIL, id->value, id->length); 7645dfecf96Smrg LispWriteChar(NIL, '\n'); 7655dfecf96Smrg } 7665dfecf96Smrg 7675dfecf96Smrg for (i = 0; i < alist->optionals.num_symbols; i++, j++) { 7685dfecf96Smrg sprintf(buffer, "%d = ", j); 7695dfecf96Smrg LispWriteStr(NIL, buffer, strlen(buffer)); 770f14f4646Smrg id = alist->optionals.symbols[i]->data.atom->key; 771f14f4646Smrg LispWriteStr(NIL, id->value, id->length); 7725dfecf96Smrg LispWriteChar(NIL, '\n'); 7735dfecf96Smrg if (alist->optionals.sforms[i]) { 7745dfecf96Smrg sprintf(buffer, "%d = ", j); 7755dfecf96Smrg len1 = strlen(buffer); 7765dfecf96Smrg LispWriteStr(NIL, buffer, len1); 777f14f4646Smrg id = alist->optionals.sforms[i]->data.atom->key; 778f14f4646Smrg len2 = id->length; 779f14f4646Smrg LispWriteStr(NIL, id->value, len2); 7805dfecf96Smrg LispWriteChars(NIL, ' ', 28 - (len1 + len2)); 7815dfecf96Smrg LispWriteStr(NIL, "; sform\n", 9); 7825dfecf96Smrg j++; 7835dfecf96Smrg } 7845dfecf96Smrg } 7855dfecf96Smrg 7865dfecf96Smrg for (i = 0; i < alist->keys.num_symbols; i++, j++) { 7875dfecf96Smrg sprintf(buffer, "%d = ", j); 7885dfecf96Smrg len1 = strlen(buffer); 7895dfecf96Smrg LispWriteStr(NIL, buffer, len1); 7905dfecf96Smrg if (alist->keys.keys[i]) { 791f14f4646Smrg id = alist->keys.keys[i]->data.atom->key; 792f14f4646Smrg len2 = id->length; 793f14f4646Smrg LispWriteStr(NIL, id->value, id->length); 7945dfecf96Smrg LispWriteChars(NIL, ' ', 28 - (len1 + len2)); 7955dfecf96Smrg LispWriteStr(NIL, "; special key", 14); 7965dfecf96Smrg } 7975dfecf96Smrg else { 798f14f4646Smrg id = alist->keys.symbols[i]->data.atom->key; 799f14f4646Smrg LispWriteStr(NIL, id->value, id->length); 8005dfecf96Smrg } 8015dfecf96Smrg LispWriteChar(NIL, '\n'); 8025dfecf96Smrg if (alist->keys.sforms[i]) { 8035dfecf96Smrg sprintf(buffer, "%d = ", j); 8045dfecf96Smrg len1 = strlen(buffer); 8055dfecf96Smrg LispWriteStr(NIL, buffer, len1); 806f14f4646Smrg id = alist->keys.sforms[i]->data.atom->key; 807f14f4646Smrg len2 = id->length; 808f14f4646Smrg LispWriteStr(NIL, id->value, len2); 8095dfecf96Smrg LispWriteChars(NIL, ' ', 28 - (len1 + len2)); 8105dfecf96Smrg LispWriteStr(NIL, "; sform\n", 9); 8115dfecf96Smrg j++; 8125dfecf96Smrg } 8135dfecf96Smrg } 8145dfecf96Smrg 8155dfecf96Smrg if (alist->rest) { 8165dfecf96Smrg sprintf(buffer, "%d = ", j); 8175dfecf96Smrg len1 = strlen(buffer); 8185dfecf96Smrg LispWriteStr(NIL, buffer, len1); 819f14f4646Smrg id = alist->rest->data.atom->key; 820f14f4646Smrg len2 = id->length; 821f14f4646Smrg LispWriteStr(NIL, id->value, len2); 8225dfecf96Smrg LispWriteChar(NIL, '\n'); 8235dfecf96Smrg j++; 8245dfecf96Smrg } 8255dfecf96Smrg 8265dfecf96Smrg for (i = 0; i < alist->auxs.num_symbols; i++, j++) { 8275dfecf96Smrg sprintf(buffer, "%d = ", j); 8285dfecf96Smrg len1 = strlen(buffer); 8295dfecf96Smrg LispWriteStr(NIL, buffer, len1); 830f14f4646Smrg id = alist->auxs.symbols[i]->data.atom->key; 831f14f4646Smrg len2 = id->length; 832f14f4646Smrg LispWriteStr(NIL, id->value, len2); 8335dfecf96Smrg LispWriteChars(NIL, ' ', 28 - (len1 + len2)); 8345dfecf96Smrg LispWriteStr(NIL, "; aux\n", 7); 8355dfecf96Smrg } 8365dfecf96Smrg } 8375dfecf96Smrg } 8385dfecf96Smrg 8395dfecf96Smrg LispWriteStr(NIL, "\nBytecode stream:\n", 18); 8405dfecf96Smrg 8415dfecf96Smrg base = stream; 8425dfecf96Smrg for (done = j = 0; !done; j = 0) { 8435dfecf96Smrg sym0 = sym1 = con0 = con1 = bui0 = byt0 = strd = strf = -1; 8445dfecf96Smrg sprintf(buffer, "%4ld ", (long)(stream - base)); 8455dfecf96Smrg ptr = buffer + strlen(buffer); 8465dfecf96Smrg switch (*stream++) { 8475dfecf96Smrg case XBC_NOOP: strcpy(ptr, "NOOP"); break; 8485dfecf96Smrg case XBC_PRED: 8495dfecf96Smrg strcpy(ptr, "PRED:"); 8505dfecf96Smrg ptr += strlen(ptr); 8515dfecf96Smrg goto predicate; 8525dfecf96Smrg case XBC_INV: strcpy(ptr, "INV"); break; 8535dfecf96Smrg case XBC_NIL: strcpy(ptr, "NIL"); break; 8545dfecf96Smrg case XBC_T: strcpy(ptr, "T"); break; 8555dfecf96Smrg case XBC_CAR: strcpy(ptr, "CAR"); break; 8565dfecf96Smrg case XBC_CDR: strcpy(ptr, "CDR"); break; 8575dfecf96Smrg case XBC_RPLACA:strcpy(ptr, "RPLACA"); break; 8585dfecf96Smrg case XBC_RPLACD:strcpy(ptr, "RPLACD"); break; 8595dfecf96Smrg case XBC_EQ: strcpy(ptr, "EQ"); break; 8605dfecf96Smrg case XBC_EQL: strcpy(ptr, "EQL"); break; 8615dfecf96Smrg case XBC_EQUAL: strcpy(ptr, "EQUAL"); break; 8625dfecf96Smrg case XBC_EQUALP:strcpy(ptr, "EQUALP"); break; 8635dfecf96Smrg case XBC_LENGTH:strcpy(ptr, "LENGTH"); break; 8645dfecf96Smrg case XBC_LAST: strcpy(ptr, "LAST"); break; 8655dfecf96Smrg case XBC_NTHCDR:strcpy(ptr, "NTHCDR"); break; 8665dfecf96Smrg case XBC_PUSH: strcpy(ptr, "PUSH"); break; 8675dfecf96Smrg case XBC_CAR_PUSH: 8685dfecf96Smrg strcpy(ptr, "CAR&PUSH"); 8695dfecf96Smrg break; 8705dfecf96Smrg case XBC_CDR_PUSH: 8715dfecf96Smrg strcpy(ptr, "CDR&PUSH"); 8725dfecf96Smrg break; 8735dfecf96Smrg case XBC_PUSH_NIL: 8745dfecf96Smrg strcpy(ptr, "PUSH NIL"); 8755dfecf96Smrg break; 8765dfecf96Smrg case XBC_PUSH_UNSPEC: 8775dfecf96Smrg strcpy(ptr, "PUSH #<UNSPEC>"); 8785dfecf96Smrg break; 8795dfecf96Smrg case XBC_PUSH_T: 8805dfecf96Smrg strcpy(ptr, "PUSH T"); 8815dfecf96Smrg break; 8825dfecf96Smrg case XBC_PUSH_NIL_N: 8835dfecf96Smrg strcpy(ptr, "PUSH NIL "); 8845dfecf96Smrg ptr += strlen(ptr); 8855dfecf96Smrg sprintf(ptr, "%d", (int)(*stream++)); 8865dfecf96Smrg break; 8875dfecf96Smrg case XBC_PUSH_UNSPEC_N: 8885dfecf96Smrg strcpy(ptr, "PUSH #<UNSPEC> "); 8895dfecf96Smrg ptr += strlen(ptr); 8905dfecf96Smrg sprintf(ptr, "%d", (int)(*stream++)); 8915dfecf96Smrg break; 8925dfecf96Smrg case XBC_LET: 8935dfecf96Smrg strcpy(ptr, "LET"); 8945dfecf96Smrg/* update sym0 */ 8955dfecf96Smrgsymbol: 8965dfecf96Smrg offsets[j++] = &sym0; 8975dfecf96Smrg/* update <offsets> - print [byte] */ 8985dfecf96Smrgoffset: 8995dfecf96Smrg ptr += strlen(ptr); 9005dfecf96Smrg i = *stream++; 9015dfecf96Smrg *(offsets[j - 1]) = i; 9025dfecf96Smrg sprintf(ptr, " [%d]", i); 9035dfecf96Smrg break; 9045dfecf96Smrg case XBC_LETX: 9055dfecf96Smrg strcpy(ptr, "LET*"); 9065dfecf96Smrg goto symbol; 9075dfecf96Smrg case XBC_LET_NIL: 9085dfecf96Smrg strcpy(ptr, "LET NIL"); 9095dfecf96Smrg goto symbol; 9105dfecf96Smrg case XBC_LETX_NIL: 9115dfecf96Smrg strcpy(ptr, "LET* NIL"); 9125dfecf96Smrg goto symbol; 9135dfecf96Smrg case XBC_LETBIND: 9145dfecf96Smrg strcpy(ptr, "LETBIND"); 9155dfecf96Smrg/* print byte */ 9165dfecf96Smrgvalue: 9175dfecf96Smrg ptr += strlen(ptr); 9185dfecf96Smrg sprintf(ptr, " %d", (int)(*stream++)); 9195dfecf96Smrg break; 9205dfecf96Smrg case XBC_UNLET:strcpy(ptr, "UNLET"); goto value; 9215dfecf96Smrg case XBC_LOAD: 9225dfecf96Smrg strcpy(ptr, "LOAD"); 9235dfecf96Smrg/* print (byte) */ 9245dfecf96Smrgreference: 9255dfecf96Smrg ptr += strlen(ptr); 9265dfecf96Smrg i = *stream++; 9275dfecf96Smrg sprintf(ptr, " (%d)", i); 9285dfecf96Smrg break; 9295dfecf96Smrg case XBC_LOAD_CAR: 9305dfecf96Smrg strcpy(ptr, "LOAD&CAR"); 9315dfecf96Smrg goto reference; 9325dfecf96Smrg case XBC_LOAD_CDR: 9335dfecf96Smrg strcpy(ptr, "LOAD&CDR"); 9345dfecf96Smrg goto reference; 9355dfecf96Smrg case XBC_LOAD_CAR_STORE: 9365dfecf96Smrg strcpy(ptr, "LOAD&CAR&STORE"); 9375dfecf96Smrg goto reference; 9385dfecf96Smrg case XBC_LOAD_CDR_STORE: 9395dfecf96Smrg strcpy(ptr, "LOAD&CDR&STORE"); 9405dfecf96Smrg goto reference; 9415dfecf96Smrg case XBC_LOAD_LET: 9425dfecf96Smrg strcpy(ptr, "LOAD&LET"); 9435dfecf96Smrgload_let: 9445dfecf96Smrg offsets[j++] = &sym0; 9455dfecf96Smrg i = *stream++; 9465dfecf96Smrg ptr += strlen(ptr); 9475dfecf96Smrg sprintf(ptr, " (%d)", i); 9485dfecf96Smrg goto offset; 9495dfecf96Smrg case XBC_LOAD_LETX: 9505dfecf96Smrg strcpy(ptr, "LOAD&LET*"); 9515dfecf96Smrg goto load_let; 9525dfecf96Smrg case XBC_STRUCT: 9535dfecf96Smrg strcpy(ptr, "STRUCT"); 9545dfecf96Smrg offsets[j++] = &strf; 9555dfecf96Smrg offsets[j++] = &strd; 9565dfecf96Smrg/* update <offsets> - print [byte] - update <offsets> - print [byte] */ 9575dfecf96Smrgoffset_offset: 9585dfecf96Smrg ptr += strlen(ptr); 9595dfecf96Smrg i = *stream++; 9605dfecf96Smrg *(offsets[j - 2]) = i; 9615dfecf96Smrg sprintf(ptr, " [%d]", i); 9625dfecf96Smrg goto offset; 9635dfecf96Smrg case XBC_LOAD_PUSH: 9645dfecf96Smrg strcpy(ptr, "LOAD&PUSH"); 9655dfecf96Smrg goto reference; 9665dfecf96Smrg case XBC_LOADCON: 9675dfecf96Smrg strcpy(ptr, "LOADCON"); 9685dfecf96Smrgconstant: 9695dfecf96Smrg offsets[j++] = &con0; 9705dfecf96Smrg goto offset; 9715dfecf96Smrg case XBC_LOADCON_SET: 9725dfecf96Smrg strcpy(ptr, "LOADCON&SET"); 9735dfecf96Smrg offsets[j++] = &con0; 9745dfecf96Smrg/* update <offsets> - print [byte] - print (byte) */ 9755dfecf96Smrgoffset_reference: 9765dfecf96Smrg i = *stream++; 9775dfecf96Smrg *(offsets[j - 1]) = i; 9785dfecf96Smrg ptr += strlen(ptr); 9795dfecf96Smrg sprintf(ptr, " [%d]", i); 9805dfecf96Smrg goto reference; 9815dfecf96Smrg case XBC_STRUCTP: 9825dfecf96Smrg strcpy(ptr, "STRUCTP"); 9835dfecf96Smrg offsets[j++] = &strd; 9845dfecf96Smrg goto offset; 9855dfecf96Smrg case XBC_LOADCON_LET: 9865dfecf96Smrg strcpy(ptr, "LOADCON&LET"); 9875dfecf96Smrgloadcon_let: 9885dfecf96Smrg offsets[j++] = &con0; 9895dfecf96Smrg offsets[j++] = &sym0; 9905dfecf96Smrg goto offset_offset; 9915dfecf96Smrg case XBC_LOADCON_LETX: 9925dfecf96Smrg strcpy(ptr, "LOADCON&LET*"); 9935dfecf96Smrg goto loadcon_let; 9945dfecf96Smrg case XBC_LOADCON_PUSH: 9955dfecf96Smrg strcpy(ptr, "LOADCON&PUSH"); 9965dfecf96Smrg goto constant; 9975dfecf96Smrg case XBC_LOADSYM: 9985dfecf96Smrg strcpy(ptr, "LOADSYM"); 9995dfecf96Smrg goto symbol; 10005dfecf96Smrg case XBC_LOADSYM_LET: 10015dfecf96Smrg strcpy(ptr, "LOADSYM&LET"); 10025dfecf96Smrgloadsym_let: 10035dfecf96Smrg offsets[j++] = &sym0; 10045dfecf96Smrg offsets[j++] = &sym1; 10055dfecf96Smrg goto offset_offset; 10065dfecf96Smrg case XBC_LOADSYM_LETX: 10075dfecf96Smrg strcpy(ptr, "LOADSYM&LET*"); 10085dfecf96Smrg goto loadsym_let; 10095dfecf96Smrg case XBC_LOADSYM_PUSH: 10105dfecf96Smrg strcpy(ptr, "LOADSYM&PUSH"); 10115dfecf96Smrg goto symbol; 10125dfecf96Smrg case XBC_LOAD_SET: 10135dfecf96Smrg strcpy(ptr, "LOAD&SET"); 10145dfecf96Smrg/* print (byte) - print (byte) */ 10155dfecf96Smrgreference_reference: 10165dfecf96Smrg ptr += strlen(ptr); 10175dfecf96Smrg i = *stream++; 10185dfecf96Smrg sprintf(ptr, " (%d)", i); 10195dfecf96Smrg goto reference; 10205dfecf96Smrg case XBC_LOAD_CAR_SET: 10215dfecf96Smrg strcpy(ptr, "LOAD&CAR&SET"); 10225dfecf96Smrg goto reference_reference; 10235dfecf96Smrg case XBC_LOAD_CDR_SET: 10245dfecf96Smrg strcpy(ptr, "LOAD&CDR&SET"); 10255dfecf96Smrg goto reference_reference; 10265dfecf96Smrg case XBC_CAR_SET: 10275dfecf96Smrg strcpy(ptr, "CAR&SET"); 10285dfecf96Smrg goto reference; 10295dfecf96Smrg case XBC_CDR_SET: 10305dfecf96Smrg strcpy(ptr, "CDR&SET"); 10315dfecf96Smrg goto reference; 10325dfecf96Smrg case XBC_SET: 10335dfecf96Smrg strcpy(ptr, "SET"); 10345dfecf96Smrg goto reference; 10355dfecf96Smrg case XBC_SETSYM: 10365dfecf96Smrg strcpy(ptr, "SETSYM"); 10375dfecf96Smrg goto symbol; 10385dfecf96Smrg case XBC_SET_NIL: 10395dfecf96Smrg strcpy(ptr, "SET NIL"); 10405dfecf96Smrg goto reference; 10415dfecf96Smrg case XBC_CALL: 10425dfecf96Smrg strcpy(ptr, "CALL"); 10435dfecf96Smrg ptr += strlen(ptr); 10445dfecf96Smrg sprintf(ptr, " %d", (int)(*stream++)); 10455dfecf96Smrg offsets[j++] = &bui0; 10465dfecf96Smrg goto offset; 10475dfecf96Smrg case XBC_CALL_SET: 10485dfecf96Smrg strcpy(ptr, "CALL&SET"); 10495dfecf96Smrg ptr += strlen(ptr); 10505dfecf96Smrg sprintf(ptr, " %d", (int)(*stream++)); 10515dfecf96Smrg offsets[j++] = &bui0; 10525dfecf96Smrg goto offset_reference; 10535dfecf96Smrg case XBC_BYTECALL: 10545dfecf96Smrg strcpy(ptr, "BYTECALL"); 10555dfecf96Smrg ptr += strlen(ptr); 10565dfecf96Smrg sprintf(ptr, " %d", (int)(*stream++)); 10575dfecf96Smrg offsets[j++] = &byt0; 10585dfecf96Smrg goto offset; 10595dfecf96Smrg case XBC_FUNCALL: 10605dfecf96Smrg strcpy(ptr, "FUNCALL"); 10615dfecf96Smrgconstant_constant: 10625dfecf96Smrg offsets[j++] = &con0; 10635dfecf96Smrg offsets[j++] = &con1; 10645dfecf96Smrg goto offset_offset; 10655dfecf96Smrg case XBC_CCONS: 10665dfecf96Smrg strcpy(ptr, "CCONS"); 10675dfecf96Smrg goto constant_constant; 10685dfecf96Smrg case XBC_CSTAR: strcpy(ptr, "CSTAR"); break; 10695dfecf96Smrg case XBC_CFINI: strcpy(ptr, "CFINI"); break; 10705dfecf96Smrg case XBC_LSTAR: strcpy(ptr, "LSTAR"); break; 10715dfecf96Smrg case XBC_LCONS: strcpy(ptr, "LCONS"); break; 10725dfecf96Smrg case XBC_LFINI: strcpy(ptr, "LFINI"); break; 10735dfecf96Smrg case XBC_BCONS: strcpy(ptr, "BCONS"); break; 10745dfecf96Smrg case XBC_BCONS1: case XBC_BCONS2: case XBC_BCONS3: 10755dfecf96Smrg case XBC_BCONS4: case XBC_BCONS5: case XBC_BCONS6: 10765dfecf96Smrg case XBC_BCONS7: 10775dfecf96Smrg strcpy(ptr, "BCONS"); 10785dfecf96Smrg ptr += strlen(ptr); 10795dfecf96Smrg sprintf(ptr, "%d", (int)(stream[-1] - XBC_BCONS)); 10805dfecf96Smrg break; 10815dfecf96Smrg case XBC_JUMP: 10825dfecf96Smrg strcpy(ptr, "JUMP"); 10835dfecf96Smrginteger: 10845dfecf96Smrg ptr += strlen(ptr); 10855dfecf96Smrg sprintf(ptr, " %d", *(signed short*)stream); 10865dfecf96Smrg stream += sizeof(short); 10875dfecf96Smrg break; 10885dfecf96Smrg case XBC_JUMPT: 10895dfecf96Smrg strcpy(ptr, "JUMPT"); 10905dfecf96Smrg goto integer; 10915dfecf96Smrg case XBC_JUMPNIL: 10925dfecf96Smrg strcpy(ptr, "JUMPNIL"); 10935dfecf96Smrg goto integer; 10945dfecf96Smrg case XBC_LETREC: 10955dfecf96Smrg strcpy(ptr, "LETREC"); 10965dfecf96Smrg ptr += strlen(ptr); 10975dfecf96Smrg sprintf(ptr, " %d", (int)*stream++); 10985dfecf96Smrg break; 10995dfecf96Smrg case XBC_RETURN: 11005dfecf96Smrg strcpy(ptr, "RETURN"); 11015dfecf96Smrg done = 1; 11025dfecf96Smrg break; 11035dfecf96Smrg } 11045dfecf96Smrg i = ptr - buffer + strlen(ptr); 11055dfecf96Smrg LispWriteStr(NIL, buffer, i); 11065dfecf96Smrg if (j) { 11075dfecf96Smrg 11085dfecf96Smrg /* Pad */ 11095dfecf96Smrg LispWriteChars(NIL, ' ', 28 - i); 11105dfecf96Smrg LispWriteChar(NIL, ';'); 11115dfecf96Smrg 11125dfecf96Smrg ptr = buffer; 11135dfecf96Smrg 11145dfecf96Smrg /* Structure */ 11155dfecf96Smrg if (strf >= 0) { 11165dfecf96Smrg /* strd is valid if strf set */ 11175dfecf96Smrg LispObj *fields = constants[strd]; 11185dfecf96Smrg 11195dfecf96Smrg for (; strf >= 0; strf--) 11205dfecf96Smrg fields = CDR(fields); 11215dfecf96Smrg strcpy(ptr, " "); ptr += 2; 1122f14f4646Smrg strcpy(ptr, CAR(fields)->data.atom->key->value); 11235dfecf96Smrg ptr += strlen(ptr); 11245dfecf96Smrg } 11255dfecf96Smrg if (strd >= 0) { 11265dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11275dfecf96Smrg strcpy(ptr, STROBJ(CAR(constants[strd]))); 11285dfecf96Smrg ptr += strlen(ptr); 11295dfecf96Smrg } 11305dfecf96Smrg 11315dfecf96Smrg /* Constants */ 11325dfecf96Smrg if (con0 >= 0) { 11335dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11345dfecf96Smrg strcpy(ptr, STROBJ(constants[con0])); 11355dfecf96Smrg ptr += strlen(ptr); 11365dfecf96Smrg if (con1 >= 0) { 11375dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11385dfecf96Smrg strcpy(ptr, STROBJ(constants[con1])); 11395dfecf96Smrg ptr += strlen(ptr); 11405dfecf96Smrg } 11415dfecf96Smrg } 11425dfecf96Smrg 11435dfecf96Smrg /* Builtin */ 11445dfecf96Smrg if (bui0 >= 0) { 11455dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11465dfecf96Smrg strcpy(ptr, STROBJ(builtins[bui0]->symbol)); 11475dfecf96Smrg ptr += strlen(ptr); 11485dfecf96Smrg } 11495dfecf96Smrg 11505dfecf96Smrg /* Bytecode */ 11515dfecf96Smrg if (byt0 >= 0) { 11525dfecf96Smrg strcpy(ptr, " "); ptr += 2; 11535dfecf96Smrg strcpy(ptr, STROBJ(names[byt0])); 11545dfecf96Smrg ptr += strlen(ptr); 11555dfecf96Smrg } 11565dfecf96Smrg 11575dfecf96Smrg /* Symbols */ 11585dfecf96Smrg if (sym0 >= 0) { 11595dfecf96Smrg strcpy(ptr, " "); ptr += 2; 1160f14f4646Smrg strcpy(ptr, XSTRING(symbols[sym0]->key)); 11615dfecf96Smrg ptr += strlen(ptr); 11625dfecf96Smrg if (sym1 >= 0) { 11635dfecf96Smrg strcpy(ptr, " "); ptr += 2; 1164f14f4646Smrg strcpy(ptr, XSTRING(symbols[sym1]->key)); 11655dfecf96Smrg ptr += strlen(ptr); 11665dfecf96Smrg } 11675dfecf96Smrg } 11685dfecf96Smrg 11695dfecf96Smrg i = ptr - buffer; 11705dfecf96Smrg LispWriteStr(NIL, buffer, i); 11715dfecf96Smrg } 11725dfecf96Smrg LispWriteChar(NIL, '\n'); 11735dfecf96Smrg continue; 11745dfecf96Smrgpredicate: 11755dfecf96Smrg switch (*stream++) { 11765dfecf96Smrg case XBP_CONSP: strcpy(ptr, "CONSP"); break; 11775dfecf96Smrg case XBP_LISTP: strcpy(ptr, "LISTP"); break; 11785dfecf96Smrg case XBP_NUMBERP: strcpy(ptr, "NUMBERP"); break; 11795dfecf96Smrg } 11805dfecf96Smrg LispWriteStr(NIL, buffer, ptr - buffer + strlen(ptr)); 11815dfecf96Smrg LispWriteChar(NIL, '\n'); 11825dfecf96Smrg } 11835dfecf96Smrg#undef XSTRING 11845dfecf96Smrg } 11855dfecf96Smrg 11865dfecf96Smrg return (function); 11875dfecf96Smrg} 11885dfecf96Smrg 11895dfecf96Smrg 11905dfecf96Smrg 11915dfecf96SmrgLispObj * 11925dfecf96SmrgLispCompileForm(LispObj *form) 11935dfecf96Smrg{ 11945dfecf96Smrg GC_ENTER(); 11955dfecf96Smrg int failed; 11965dfecf96Smrg LispCom com; 11975dfecf96Smrg 11985dfecf96Smrg if (!CONSP(form)) 11995dfecf96Smrg /* Incorrect call or NIL */ 12005dfecf96Smrg return (form); 12015dfecf96Smrg 12025dfecf96Smrg memset(&com, 0, sizeof(LispCom)); 12035dfecf96Smrg 12045dfecf96Smrg com.toplevel = com.block = LispCalloc(1, sizeof(CodeBlock)); 12055dfecf96Smrg com.block->type = LispBlockNone; 12065dfecf96Smrg com.lex = lisp__data.env.lex; 12075dfecf96Smrg 12085dfecf96Smrg com.plist = CONS(NIL, NIL); 12095dfecf96Smrg GC_PROTECT(com.plist); 12105dfecf96Smrg 12115dfecf96Smrg failed = 1; 12125dfecf96Smrg if (setjmp(com.jmp) == 0) { 12135dfecf96Smrg for (; CONSP(form); form = CDR(form)) { 12145dfecf96Smrg com.form = form; 12155dfecf96Smrg ComEval(&com, CAR(form)); 12165dfecf96Smrg } 12175dfecf96Smrg failed = 0; 12185dfecf96Smrg } 12195dfecf96Smrg GC_LEAVE(); 12205dfecf96Smrg 12215dfecf96Smrg return (failed ? NIL : MakeBytecodeObject(&com, NIL, NIL)); 12225dfecf96Smrg} 12235dfecf96Smrg 12245dfecf96SmrgLispObj * 12255dfecf96SmrgLispExecuteBytecode(LispObj *object) 12265dfecf96Smrg{ 12275dfecf96Smrg if (!BYTECODEP(object)) 12285dfecf96Smrg return (EVAL(object)); 12295dfecf96Smrg 12305dfecf96Smrg return (ExecuteBytecode(object->data.bytecode.bytecode->code)); 12315dfecf96Smrg} 12325dfecf96Smrg 12335dfecf96Smrgstatic LispObj * 12345dfecf96SmrgMakeBytecodeObject(LispCom *com, LispObj *name, LispObj *plist) 12355dfecf96Smrg{ 12365dfecf96Smrg LispObj *object; 12375dfecf96Smrg LispBytecode *bytecode; 12385dfecf96Smrg 12395dfecf96Smrg GC_ENTER(); 12405dfecf96Smrg unsigned char *stream; 12415dfecf96Smrg short i, num_constants; 12425dfecf96Smrg LispObj **constants, *code, *cons, *prev; 12435dfecf96Smrg 12445dfecf96Smrg /* Resolve dependencies, optimize and create byte stream */ 12455dfecf96Smrg LinkBytecode(com); 12465dfecf96Smrg 12475dfecf96Smrg object = LispNew(NIL, NIL); 12485dfecf96Smrg GC_PROTECT(object); 12495dfecf96Smrg bytecode = LispMalloc(sizeof(LispBytecode)); 12505dfecf96Smrg bytecode->code = com->bytecode; 12515dfecf96Smrg bytecode->length = com->length; 12525dfecf96Smrg 12535dfecf96Smrg 12545dfecf96Smrg stream = bytecode->code; 12555dfecf96Smrg 12565dfecf96Smrg /* Skip stack information */ 12575dfecf96Smrg stream += sizeof(short) * 3; 12585dfecf96Smrg 12595dfecf96Smrg /* Get information */ 12605dfecf96Smrg num_constants = *(short*)stream; 12615dfecf96Smrg stream += sizeof(short) * 4; 12625dfecf96Smrg constants = (LispObj**)stream; 12635dfecf96Smrg 12645dfecf96Smrg GC_PROTECT(plist); 12655dfecf96Smrg code = cons = prev = NIL; 12665dfecf96Smrg for (i = 0; i < num_constants; i++) { 12675dfecf96Smrg if (POINTERP(constants[i]) && !XSYMBOLP(constants[i])) { 12685dfecf96Smrg if (code == NIL) { 12695dfecf96Smrg code = cons = prev = CONS(constants[i], NIL); 12705dfecf96Smrg GC_PROTECT(code); 12715dfecf96Smrg } 12725dfecf96Smrg else { 12735dfecf96Smrg RPLACD(cons, CONS(constants[i], NIL)); 12745dfecf96Smrg prev = cons; 12755dfecf96Smrg cons = CDR(cons); 12765dfecf96Smrg } 12775dfecf96Smrg } 12785dfecf96Smrg } 12795dfecf96Smrg 12805dfecf96Smrg /* Protect this in case the function is redefined */ 12815dfecf96Smrg for (i = 0; i < com->table.num_bytecodes; i++) { 12825dfecf96Smrg if (code == NIL) { 12835dfecf96Smrg code = cons = prev = CONS(com->table.bytecodes[i], NIL); 12845dfecf96Smrg GC_PROTECT(code); 12855dfecf96Smrg } 12865dfecf96Smrg else { 12875dfecf96Smrg RPLACD(cons, CONS(com->table.bytecodes[i], NIL)); 12885dfecf96Smrg prev = cons; 12895dfecf96Smrg cons = CDR(cons); 12905dfecf96Smrg } 12915dfecf96Smrg } 12925dfecf96Smrg 12935dfecf96Smrg /* Free everything, but the LispCom structure and the generated bytecode */ 12945dfecf96Smrg CompileFreeState(com); 12955dfecf96Smrg 12965dfecf96Smrg /* Allocate the minimum required number of cons cells to protect objects */ 12975dfecf96Smrg if (!CONSP(code)) 12985dfecf96Smrg code = plist; 12995dfecf96Smrg else if (CONSP(plist)) { 13005dfecf96Smrg if (code == cons) 13015dfecf96Smrg RPLACD(code, plist); 13025dfecf96Smrg else 13035dfecf96Smrg RPLACD(cons, plist); 13045dfecf96Smrg } 13055dfecf96Smrg else { 13065dfecf96Smrg if (code == cons) 13075dfecf96Smrg code = CAR(code); 13085dfecf96Smrg else 13095dfecf96Smrg CDR(prev) = CAR(cons); 13105dfecf96Smrg } 13115dfecf96Smrg 13125dfecf96Smrg object->data.bytecode.bytecode = bytecode; 13135dfecf96Smrg /* Byte code references this object, so it cannot be garbage collected */ 13145dfecf96Smrg object->data.bytecode.code = code; 13155dfecf96Smrg object->data.bytecode.name = name; 13165dfecf96Smrg object->type = LispBytecode_t; 13175dfecf96Smrg 13185dfecf96Smrg LispMused(bytecode); 13195dfecf96Smrg LispMused(bytecode->code); 13205dfecf96Smrg GC_LEAVE(); 13215dfecf96Smrg 13225dfecf96Smrg return (object); 13235dfecf96Smrg} 13245dfecf96Smrg 13255dfecf96Smrgstatic void 13265dfecf96SmrgCompileFreeTree(CodeTree *tree) 13275dfecf96Smrg{ 13285dfecf96Smrg if (tree->type == CodeTreeBlock) 13295dfecf96Smrg CompileFreeBlock(tree->data.block); 13305dfecf96Smrg LispFree(tree); 13315dfecf96Smrg} 13325dfecf96Smrg 13335dfecf96Smrgstatic void 13345dfecf96SmrgCompileFreeBlock(CodeBlock *block) 13355dfecf96Smrg{ 13365dfecf96Smrg CodeTree *tree = block->tree, *next; 13375dfecf96Smrg 13385dfecf96Smrg while (tree) { 13395dfecf96Smrg next = tree->next; 13405dfecf96Smrg CompileFreeTree(tree); 13415dfecf96Smrg tree = next; 13425dfecf96Smrg } 13435dfecf96Smrg if (block->type == LispBlockBody) { 13445dfecf96Smrg LispFree(block->tagbody.labels); 13455dfecf96Smrg LispFree(block->tagbody.codes); 13465dfecf96Smrg } 13475dfecf96Smrg LispFree(block->variables.symbols); 13485dfecf96Smrg LispFree(block->variables.flags); 13495dfecf96Smrg LispFree(block); 13505dfecf96Smrg} 13515dfecf96Smrg 13525dfecf96Smrgstatic void 13535dfecf96SmrgCompileFreeState(LispCom *com) 13545dfecf96Smrg{ 13555dfecf96Smrg CompileFreeBlock(com->block); 13565dfecf96Smrg LispFree(com->table.constants); 13575dfecf96Smrg LispFree(com->table.symbols); 13585dfecf96Smrg LispFree(com->table.builtins); 13595dfecf96Smrg LispFree(com->table.bytecodes); 13605dfecf96Smrg} 13615dfecf96Smrg 13625dfecf96Smrg/* XXX Put a breakpoint here when changing the macro expansion code. 13635dfecf96Smrg * No opcodes should be generated during macro expansion. */ 13645dfecf96Smrgstatic CodeTree * 13655dfecf96SmrgCompileNewTree(LispCom *com, CodeTreeType type) 13665dfecf96Smrg{ 13675dfecf96Smrg CodeTree *tree = LispMalloc(sizeof(CodeTree)); 13685dfecf96Smrg 13695dfecf96Smrg tree->type = type; 13705dfecf96Smrg tree->next = NULL; 13715dfecf96Smrg tree->block = com->block; 13725dfecf96Smrg if (com->block->tree == NULL) 13735dfecf96Smrg com->block->tree = tree; 13745dfecf96Smrg else 13755dfecf96Smrg com->block->tail->next = tree; 13765dfecf96Smrg com->block->tail = tree; 13775dfecf96Smrg 13785dfecf96Smrg return (tree); 13795dfecf96Smrg} 13805dfecf96Smrg 13815dfecf96Smrgstatic void 13825dfecf96SmrgCompileIniBlock(LispCom *com, LispBlockType type, LispObj *tag) 13835dfecf96Smrg{ 13845dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBlock); 13855dfecf96Smrg CodeBlock *block = LispCalloc(1, sizeof(CodeBlock)); 13865dfecf96Smrg 13875dfecf96Smrg tree->data.block = block; 13885dfecf96Smrg 13895dfecf96Smrg block->type = type; 13905dfecf96Smrg block->tag = tag; 13915dfecf96Smrg block->prev = com->block; 13925dfecf96Smrg block->parent = tree; 13935dfecf96Smrg block->level = com->level; 13945dfecf96Smrg com->block = block; 13955dfecf96Smrg 13965dfecf96Smrg if (type == LispBlockBody) 13975dfecf96Smrg com->tagbody = com->level; 13985dfecf96Smrg} 13995dfecf96Smrg 14005dfecf96Smrgstatic void 14015dfecf96SmrgCompileFiniBlock(LispCom *com) 14025dfecf96Smrg{ 14035dfecf96Smrg com->block = com->block->prev; 14045dfecf96Smrg if (com->block && com->block->type == LispBlockBody) 14055dfecf96Smrg com->tagbody = com->block->level; 14065dfecf96Smrg} 14075dfecf96Smrg 14085dfecf96Smrgstatic void 14095dfecf96Smrgcom_BytecodeChar(LispCom *com, LispByteOpcode code, char value) 14105dfecf96Smrg{ 14115dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14125dfecf96Smrg 14135dfecf96Smrg tree->code = code; 14145dfecf96Smrg tree->data.signed_char = value; 14155dfecf96Smrg} 14165dfecf96Smrg 14175dfecf96Smrgstatic void 14185dfecf96Smrgcom_BytecodeShort(LispCom *com, LispByteOpcode code, short value) 14195dfecf96Smrg{ 14205dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14215dfecf96Smrg 14225dfecf96Smrg tree->code = code; 14235dfecf96Smrg tree->data.signed_short = value; 14245dfecf96Smrg} 14255dfecf96Smrg 14265dfecf96Smrgstatic void 14275dfecf96Smrgcom_BytecodeAtom(LispCom *com, LispByteOpcode code, LispAtom *atom) 14285dfecf96Smrg{ 14295dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14305dfecf96Smrg 14315dfecf96Smrg tree->code = code; 14325dfecf96Smrg tree->data.atom = atom; 14335dfecf96Smrg} 14345dfecf96Smrg 14355dfecf96Smrgstatic void 14365dfecf96Smrgcom_BytecodeObject(LispCom *com, LispByteOpcode code, LispObj *object) 14375dfecf96Smrg{ 14385dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14395dfecf96Smrg 14405dfecf96Smrg tree->code = code; 14415dfecf96Smrg tree->data.object = object; 14425dfecf96Smrg} 14435dfecf96Smrg 14445dfecf96Smrgstatic void 14455dfecf96Smrgcom_BytecodeCons(LispCom *com, LispByteOpcode code, LispObj *car, LispObj *cdr) 14465dfecf96Smrg{ 14475dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14485dfecf96Smrg 14495dfecf96Smrg tree->code = code; 14505dfecf96Smrg tree->data.cons.car = car; 14515dfecf96Smrg tree->data.cons.cdr = cdr; 14525dfecf96Smrg} 14535dfecf96Smrg 14545dfecf96Smrgstatic void 14555dfecf96Smrgcom_Bytecode(LispCom *com, LispByteOpcode code) 14565dfecf96Smrg{ 14575dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14585dfecf96Smrg 14595dfecf96Smrg tree->code = code; 14605dfecf96Smrg} 14615dfecf96Smrg 14625dfecf96Smrgstatic void 14635dfecf96Smrgcom_Load(LispCom *com, short offset) 14645dfecf96Smrg{ 14655dfecf96Smrg com_BytecodeShort(com, XBC_LOAD, offset); 14665dfecf96Smrg} 14675dfecf96Smrg 14685dfecf96Smrgstatic void 14695dfecf96Smrgcom_LoadLet(LispCom *com, short offset, LispAtom *name) 14705dfecf96Smrg{ 14715dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 14725dfecf96Smrg 14735dfecf96Smrg tree->code = XBC_LOAD_LET; 14745dfecf96Smrg tree->data.let.offset = offset; 14755dfecf96Smrg tree->data.let.name = name; 14765dfecf96Smrg} 14775dfecf96Smrg 14785dfecf96Smrgstatic void 14795dfecf96Smrgcom_LoadPush(LispCom *com, short offset) 14805dfecf96Smrg{ 14815dfecf96Smrg com_BytecodeShort(com, XBC_LOAD_PUSH, offset); 14825dfecf96Smrg} 14835dfecf96Smrg 14845dfecf96Smrgstatic void 14855dfecf96Smrgcom_Let(LispCom *com, LispAtom *name) 14865dfecf96Smrg{ 14875dfecf96Smrg com_BytecodeAtom(com, XBC_LET, name); 14885dfecf96Smrg} 14895dfecf96Smrg 14905dfecf96Smrgstatic void 14915dfecf96Smrgcom_Bind(LispCom *com, short count) 14925dfecf96Smrg{ 14935dfecf96Smrg if (count) 14945dfecf96Smrg com_BytecodeShort(com, XBC_LETBIND, count); 14955dfecf96Smrg} 14965dfecf96Smrg 14975dfecf96Smrgstatic void 14985dfecf96Smrgcom_Unbind(LispCom *com, short count) 14995dfecf96Smrg{ 15005dfecf96Smrg if (count) 15015dfecf96Smrg com_BytecodeShort(com, XBC_UNLET, count); 15025dfecf96Smrg} 15035dfecf96Smrg 15045dfecf96Smrgstatic void 15055dfecf96Smrgcom_LoadSym(LispCom *com, LispAtom *atom) 15065dfecf96Smrg{ 15075dfecf96Smrg com_BytecodeAtom(com, XBC_LOADSYM, atom); 15085dfecf96Smrg} 15095dfecf96Smrg 15105dfecf96Smrgstatic void 15115dfecf96Smrgcom_LoadSymLet(LispCom *com, LispAtom *symbol, LispAtom *name) 15125dfecf96Smrg{ 15135dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 15145dfecf96Smrg 15155dfecf96Smrg tree->code = XBC_LOADSYM_LET; 15165dfecf96Smrg tree->data.let_sym.symbol = symbol; 15175dfecf96Smrg tree->data.let_sym.name = name; 15185dfecf96Smrg} 15195dfecf96Smrg 15205dfecf96Smrgstatic void 15215dfecf96Smrgcom_LoadSymPush(LispCom *com, LispAtom *name) 15225dfecf96Smrg{ 15235dfecf96Smrg com_BytecodeAtom(com, XBC_LOADSYM_PUSH, name); 15245dfecf96Smrg} 15255dfecf96Smrg 15265dfecf96Smrgstatic void 15275dfecf96Smrgcom_LoadCon(LispCom *com, LispObj *constant) 15285dfecf96Smrg{ 15295dfecf96Smrg if (constant == NIL) 15305dfecf96Smrg com_Bytecode(com, XBC_NIL); 15315dfecf96Smrg else if (constant == T) 15325dfecf96Smrg com_Bytecode(com, XBC_T); 15335dfecf96Smrg else if (constant == UNSPEC) { 15345dfecf96Smrg COMPILE_FAILURE("internal error: loading #<UNSPEC>"); 15355dfecf96Smrg } 15365dfecf96Smrg else 15375dfecf96Smrg com_BytecodeObject(com, XBC_LOADCON, constant); 15385dfecf96Smrg} 15395dfecf96Smrg 15405dfecf96Smrgstatic void 15415dfecf96Smrgcom_LoadConLet(LispCom *com, LispObj *constant, LispAtom *name) 15425dfecf96Smrg{ 15435dfecf96Smrg if (constant == NIL) 15445dfecf96Smrg com_BytecodeAtom(com, XBC_LET_NIL, name); 15455dfecf96Smrg else { 15465dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 15475dfecf96Smrg 15485dfecf96Smrg tree->code = XBC_LOADCON_LET; 15495dfecf96Smrg tree->data.let_con.object = constant; 15505dfecf96Smrg tree->data.let_con.name = name; 15515dfecf96Smrg } 15525dfecf96Smrg} 15535dfecf96Smrg 15545dfecf96Smrgstatic void 15555dfecf96Smrgcom_LoadConPush(LispCom *com, LispObj *constant) 15565dfecf96Smrg{ 15575dfecf96Smrg if (constant == NIL) 15585dfecf96Smrg com_Bytecode(com, XBC_PUSH_NIL); 15595dfecf96Smrg else if (constant == T) 15605dfecf96Smrg com_Bytecode(com, XBC_PUSH_T); 15615dfecf96Smrg else if (constant == UNSPEC) 15625dfecf96Smrg com_Bytecode(com, XBC_PUSH_UNSPEC); 15635dfecf96Smrg else 15645dfecf96Smrg com_BytecodeObject(com, XBC_LOADCON_PUSH, constant); 15655dfecf96Smrg} 15665dfecf96Smrg 15675dfecf96Smrgstatic void 15685dfecf96Smrgcom_Set(LispCom *com, short offset) 15695dfecf96Smrg{ 15705dfecf96Smrg com_BytecodeShort(com, XBC_SET, offset); 15715dfecf96Smrg} 15725dfecf96Smrg 15735dfecf96Smrgstatic void 15745dfecf96Smrgcom_SetSym(LispCom *com, LispAtom *symbol) 15755dfecf96Smrg{ 15765dfecf96Smrg com_BytecodeAtom(com, XBC_SETSYM, symbol); 15775dfecf96Smrg} 15785dfecf96Smrg 15795dfecf96Smrgstatic void 15805dfecf96Smrgcom_Struct(LispCom *com, short offset, LispObj *definition) 15815dfecf96Smrg{ 15825dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 15835dfecf96Smrg 15845dfecf96Smrg tree->code = XBC_STRUCT; 15855dfecf96Smrg tree->data.struc.offset = offset; 15865dfecf96Smrg tree->data.struc.definition = definition; 15875dfecf96Smrg} 15885dfecf96Smrg 15895dfecf96Smrgstatic void 15905dfecf96Smrgcom_Structp(LispCom *com, LispObj *definition) 15915dfecf96Smrg{ 15925dfecf96Smrg com_BytecodeObject(com, XBC_STRUCTP, definition); 15935dfecf96Smrg} 15945dfecf96Smrg 15955dfecf96Smrgstatic void 15965dfecf96Smrgcom_Call(LispCom *com, unsigned char num_arguments, LispBuiltin *builtin) 15975dfecf96Smrg{ 15985dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 15995dfecf96Smrg 16005dfecf96Smrg tree->code = XBC_CALL; 16015dfecf96Smrg tree->data.builtin.num_arguments = num_arguments; 16025dfecf96Smrg tree->data.builtin.builtin = builtin; 16035dfecf96Smrg} 16045dfecf96Smrg 16055dfecf96Smrgstatic void 16065dfecf96Smrgcom_Bytecall(LispCom *com, unsigned char num_arguments, LispObj *code) 16075dfecf96Smrg{ 16085dfecf96Smrg CodeTree *tree = NEW_TREE(CodeTreeBytecode); 16095dfecf96Smrg 16105dfecf96Smrg tree->code = XBC_BYTECALL; 16115dfecf96Smrg tree->data.bytecall.num_arguments = num_arguments; 16125dfecf96Smrg tree->data.bytecall.code = code; 16135dfecf96Smrg} 16145dfecf96Smrg 16155dfecf96Smrgstatic void 16165dfecf96Smrgcom_Funcall(LispCom *com, LispObj *function, LispObj *arguments) 16175dfecf96Smrg{ 16185dfecf96Smrg com_BytecodeCons(com, XBC_FUNCALL, function, arguments); 16195dfecf96Smrg} 16205dfecf96Smrg 16215dfecf96Smrgstatic void 16225dfecf96SmrgCompileStackEnter(LispCom *com, int count, int builtin) 16235dfecf96Smrg{ 16245dfecf96Smrg if (!com->macro) { 16255dfecf96Smrg if (builtin) { 16265dfecf96Smrg com->stack.cbstack += count; 16275dfecf96Smrg if (com->stack.bstack < com->stack.cbstack) 16285dfecf96Smrg com->stack.bstack = com->stack.cbstack; 16295dfecf96Smrg } 16305dfecf96Smrg else { 16315dfecf96Smrg com->stack.cstack += count; 16325dfecf96Smrg if (com->stack.stack < com->stack.cstack) 16335dfecf96Smrg com->stack.stack = com->stack.cstack; 16345dfecf96Smrg } 16355dfecf96Smrg } 16365dfecf96Smrg} 16375dfecf96Smrg 16385dfecf96Smrgstatic void 16395dfecf96SmrgCompileStackLeave(LispCom *com, int count, int builtin) 16405dfecf96Smrg{ 16415dfecf96Smrg if (!com->macro) { 16425dfecf96Smrg if (builtin) 16435dfecf96Smrg com->stack.cbstack -= count; 16445dfecf96Smrg else 16455dfecf96Smrg com->stack.cstack -= count; 16465dfecf96Smrg } 16475dfecf96Smrg} 16485dfecf96Smrg 16495dfecf96Smrgstatic void 16505dfecf96SmrgLinkWarnUnused(LispCom *com, CodeBlock *block) 16515dfecf96Smrg{ 16525dfecf96Smrg int i; 16535dfecf96Smrg CodeTree *tree; 16545dfecf96Smrg 16555dfecf96Smrg for (tree = block->tree; tree; tree = tree->next) { 16565dfecf96Smrg if (tree->type == CodeTreeBlock) 16575dfecf96Smrg LinkWarnUnused(com, tree->data.block); 16585dfecf96Smrg } 16595dfecf96Smrg 16605dfecf96Smrg for (i = 0; i < block->variables.length; i++) 16615dfecf96Smrg if (!(block->variables.flags[i] & (VARIABLE_USED | VARIABLE_ARGUMENT))) { 16625dfecf96Smrg ++com->warnings; 16635dfecf96Smrg LispWarning("the variable %s is unused", 1664f14f4646Smrg block->variables.symbols[i]->key->value); 16655dfecf96Smrg } 16665dfecf96Smrg} 16675dfecf96Smrg 16685dfecf96Smrg#define INTERNAL_ERROR_STRING "COMPILE: internal error #%d" 16695dfecf96Smrg#define INTERNAL_ERROR(value) LispDestroy(INTERNAL_ERROR_STRING, value) 16705dfecf96Smrgstatic long 16715dfecf96SmrgLinkBuildOffsets(LispCom *com, CodeTree *tree, long offset) 16725dfecf96Smrg{ 16735dfecf96Smrg for (; tree; tree = tree->next) { 16745dfecf96Smrg tree->offset = offset; 16755dfecf96Smrg switch (tree->type) { 16765dfecf96Smrg case CodeTreeBytecode: 16775dfecf96Smrg switch (tree->code) { 16785dfecf96Smrg case XBC_NOOP: 16795dfecf96Smrg INTERNAL_ERROR(__LINE__); 16805dfecf96Smrg break; 16815dfecf96Smrg 16825dfecf96Smrg /* byte */ 16835dfecf96Smrg case XBC_BCONS: 16845dfecf96Smrg case XBC_BCONS1: 16855dfecf96Smrg case XBC_BCONS2: 16865dfecf96Smrg case XBC_BCONS3: 16875dfecf96Smrg case XBC_BCONS4: 16885dfecf96Smrg case XBC_BCONS5: 16895dfecf96Smrg case XBC_BCONS6: 16905dfecf96Smrg case XBC_BCONS7: 16915dfecf96Smrg case XBC_INV: 16925dfecf96Smrg case XBC_NIL: 16935dfecf96Smrg case XBC_T: 16945dfecf96Smrg case XBC_PUSH: 16955dfecf96Smrg case XBC_CAR_PUSH: 16965dfecf96Smrg case XBC_CDR_PUSH: 16975dfecf96Smrg case XBC_PUSH_NIL: 16985dfecf96Smrg case XBC_PUSH_UNSPEC: 16995dfecf96Smrg case XBC_PUSH_T: 17005dfecf96Smrg case XBC_LSTAR: 17015dfecf96Smrg case XBC_LCONS: 17025dfecf96Smrg case XBC_LFINI: 17035dfecf96Smrg case XBC_RETURN: 17045dfecf96Smrg case XBC_CSTAR: 17055dfecf96Smrg case XBC_CFINI: 17065dfecf96Smrg case XBC_CAR: 17075dfecf96Smrg case XBC_CDR: 17085dfecf96Smrg case XBC_RPLACA: 17095dfecf96Smrg case XBC_RPLACD: 17105dfecf96Smrg case XBC_EQ: 17115dfecf96Smrg case XBC_EQL: 17125dfecf96Smrg case XBC_EQUAL: 17135dfecf96Smrg case XBC_EQUALP: 17145dfecf96Smrg case XBC_LENGTH: 17155dfecf96Smrg case XBC_LAST: 17165dfecf96Smrg case XBC_NTHCDR: 17175dfecf96Smrg ++offset; 17185dfecf96Smrg break; 17195dfecf96Smrg 17205dfecf96Smrg /* byte + byte */ 17215dfecf96Smrg case XBC_PUSH_NIL_N: 17225dfecf96Smrg case XBC_PUSH_UNSPEC_N: 17235dfecf96Smrg case XBC_PRED: 17245dfecf96Smrg case XBC_LETREC: 17255dfecf96Smrg case XBC_LOAD_PUSH: 17265dfecf96Smrg case XBC_CAR_SET: 17275dfecf96Smrg case XBC_CDR_SET: 17285dfecf96Smrg case XBC_SET: 17295dfecf96Smrg case XBC_SET_NIL: 17305dfecf96Smrg case XBC_LETBIND: 17315dfecf96Smrg case XBC_UNLET: 17325dfecf96Smrg case XBC_LOAD: 17335dfecf96Smrg case XBC_LOAD_CAR: 17345dfecf96Smrg case XBC_LOAD_CDR: 17355dfecf96Smrg case XBC_LOAD_CAR_STORE: 17365dfecf96Smrg case XBC_LOAD_CDR_STORE: 17375dfecf96Smrg case XBC_LET: 17385dfecf96Smrg case XBC_LETX: 17395dfecf96Smrg case XBC_LET_NIL: 17405dfecf96Smrg case XBC_LETX_NIL: 17415dfecf96Smrg case XBC_STRUCTP: 17425dfecf96Smrg case XBC_SETSYM: 17435dfecf96Smrg case XBC_LOADCON_PUSH: 17445dfecf96Smrg case XBC_LOADSYM_PUSH: 17455dfecf96Smrg case XBC_LOADCON: 17465dfecf96Smrg case XBC_LOADSYM: 17475dfecf96Smrg offset += 2; 17485dfecf96Smrg break; 17495dfecf96Smrg 17505dfecf96Smrg /* byte + byte + byte */ 17515dfecf96Smrg case XBC_CALL: 17525dfecf96Smrg case XBC_BYTECALL: 17535dfecf96Smrg case XBC_LOAD_SET: 17545dfecf96Smrg case XBC_LOAD_CAR_SET: 17555dfecf96Smrg case XBC_LOAD_CDR_SET: 17565dfecf96Smrg case XBC_LOADCON_SET: 17575dfecf96Smrg case XBC_LOAD_LET: 17585dfecf96Smrg case XBC_LOAD_LETX: 17595dfecf96Smrg case XBC_STRUCT: 17605dfecf96Smrg case XBC_LOADCON_LET: 17615dfecf96Smrg case XBC_LOADCON_LETX: 17625dfecf96Smrg case XBC_LOADSYM_LET: 17635dfecf96Smrg case XBC_LOADSYM_LETX: 17645dfecf96Smrg case XBC_CCONS: 17655dfecf96Smrg case XBC_FUNCALL: 17665dfecf96Smrg offset += 3; 17675dfecf96Smrg break; 17685dfecf96Smrg 17695dfecf96Smrg /* byte + short */ 17705dfecf96Smrg case XBC_JUMP: 17715dfecf96Smrg case XBC_JUMPT: 17725dfecf96Smrg case XBC_JUMPNIL: 17735dfecf96Smrg /* XXX this is likely a jump to random address here */ 17745dfecf96Smrg INTERNAL_ERROR(__LINE__); 17755dfecf96Smrg offset += sizeof(short) + 1; 17765dfecf96Smrg break; 17775dfecf96Smrg 17785dfecf96Smrg /* byte + byte + byte + byte */ 17795dfecf96Smrg case XBC_CALL_SET: 17805dfecf96Smrg offset += 4; 17815dfecf96Smrg break; 17825dfecf96Smrg } 17835dfecf96Smrg break; 17845dfecf96Smrg case CodeTreeLabel: 17855dfecf96Smrg /* Labels are not loaded */ 17865dfecf96Smrg break; 17875dfecf96Smrg case CodeTreeJump: 17885dfecf96Smrg case CodeTreeJumpIf: 17895dfecf96Smrg case CodeTreeCond: 17905dfecf96Smrg /* If not the point where the conditional block finishes */ 17915dfecf96Smrg if (tree->code != XBC_NOOP) 17925dfecf96Smrg /* Reserve space for the jump opcode */ 17935dfecf96Smrg offset += sizeof(short) + 1; 17945dfecf96Smrg break; 17955dfecf96Smrg case CodeTreeGo: 17965dfecf96Smrg case CodeTreeReturn: 17975dfecf96Smrg /* Reserve space for the jump opcode */ 17985dfecf96Smrg offset += sizeof(short) + 1; 17995dfecf96Smrg break; 18005dfecf96Smrg case CodeTreeBlock: 18015dfecf96Smrg offset = LinkBuildOffsets(com, tree->data.block->tree, offset); 18025dfecf96Smrg break; 18035dfecf96Smrg } 18045dfecf96Smrg } 18055dfecf96Smrg 18065dfecf96Smrg return (offset); 18075dfecf96Smrg} 18085dfecf96Smrg 18095dfecf96Smrgstatic void 18105dfecf96SmrgLinkDoOptimize_0(LispCom *com, CodeBlock *block) 18115dfecf96Smrg{ 18125dfecf96Smrg CodeTree *tree, *prev, *next; 18135dfecf96Smrg 18145dfecf96Smrg /* Remove redundant or join opcodes that can be joined. Do it here 18155dfecf96Smrg * because some of these are hard to detect earlier, and/or would 18165dfecf96Smrg * require a lot of duplicated code or more time. */ 18175dfecf96Smrg tree = prev = block->tree; 18185dfecf96Smrg while (tree) { 18195dfecf96Smrg next = tree->next; 18205dfecf96Smrg 18215dfecf96Smrg /* LET -> LET* */ 18225dfecf96Smrg if (next && 18235dfecf96Smrg next->type == CodeTreeBytecode && 18245dfecf96Smrg next->code == XBC_LETBIND && 18255dfecf96Smrg next->data.signed_short == 1) { 18265dfecf96Smrg switch (tree->code) { 18275dfecf96Smrg case XBC_LET: 18285dfecf96Smrg tree->code = XBC_LETX; 18295dfecf96Smrg goto remove_next_label; 18305dfecf96Smrg case XBC_LET_NIL: 18315dfecf96Smrg tree->code = XBC_LETX_NIL; 18325dfecf96Smrg goto remove_next_label; 18335dfecf96Smrg case XBC_LOAD_LET: 18345dfecf96Smrg tree->code = XBC_LOAD_LETX; 18355dfecf96Smrg goto remove_next_label; 18365dfecf96Smrg case XBC_LOADCON_LET: 18375dfecf96Smrg tree->code = XBC_LOADCON_LETX; 18385dfecf96Smrg goto remove_next_label; 18395dfecf96Smrg case XBC_LOADSYM_LET: 18405dfecf96Smrg tree->code = XBC_LOADSYM_LETX; 18415dfecf96Smrg goto remove_next_label; 18425dfecf96Smrg default: 18435dfecf96Smrg break; 18445dfecf96Smrg } 18455dfecf96Smrg } 18465dfecf96Smrg 18475dfecf96Smrg switch (tree->type) { 18485dfecf96Smrg case CodeTreeBytecode: 18495dfecf96Smrg switch (tree->code) { 18505dfecf96Smrg case XBC_LOADCON: 18515dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 18525dfecf96Smrg switch (next->code) { 18535dfecf96Smrg case XBC_LET: 18545dfecf96Smrg next->code = XBC_LOADCON_LET; 18555dfecf96Smrg next->data.let_con.name = 18565dfecf96Smrg next->data.atom; 18575dfecf96Smrg next->data.let_con.object = 18585dfecf96Smrg tree->data.object; 18595dfecf96Smrg goto remove_label; 18605dfecf96Smrg case XBC_PUSH: 18615dfecf96Smrg next->code = XBC_LOADCON_PUSH; 18625dfecf96Smrg next->data.object = tree->data.object; 18635dfecf96Smrg goto remove_label; 18645dfecf96Smrg case XBC_CAR: 18655dfecf96Smrg if (tree->data.object != NIL) { 18665dfecf96Smrg if (!CONSP(tree->data.object)) 18675dfecf96Smrg LispDestroy("CAR: %s is not a list", 18685dfecf96Smrg STROBJ( 18695dfecf96Smrg tree->data.object)); 18705dfecf96Smrg next->code = XBC_LOADCON; 18715dfecf96Smrg next->data.object = 18725dfecf96Smrg CAR(tree->data.object); 18735dfecf96Smrg } 18745dfecf96Smrg goto remove_label; 18755dfecf96Smrg case XBC_CDR: 18765dfecf96Smrg if (tree->data.object != NIL) { 18775dfecf96Smrg if (!CONSP(tree->data.object)) 18785dfecf96Smrg LispDestroy("CAR: %s is not a list", 18795dfecf96Smrg STROBJ( 18805dfecf96Smrg tree->data.object)); 18815dfecf96Smrg next->code = XBC_LOADCON; 18825dfecf96Smrg next->data.object = 18835dfecf96Smrg CDR(tree->data.object); 18845dfecf96Smrg } 18855dfecf96Smrg goto remove_label; 18865dfecf96Smrg case XBC_SET: 18875dfecf96Smrg next->code = XBC_LOADCON_SET; 18885dfecf96Smrg next->data.load_con_set.offset = 18895dfecf96Smrg next->data.signed_short; 18905dfecf96Smrg next->data.load_con_set.object = 18915dfecf96Smrg tree->data.object; 18925dfecf96Smrg goto remove_label; 18935dfecf96Smrg default: 18945dfecf96Smrg break; 18955dfecf96Smrg } 18965dfecf96Smrg } 18975dfecf96Smrg break; 18985dfecf96Smrg case XBC_LOADSYM: 18995dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 19005dfecf96Smrg switch (next->code) { 19015dfecf96Smrg case XBC_LET: 19025dfecf96Smrg next->code = XBC_LOADSYM_LET; 19035dfecf96Smrg next->data.let_sym.name = 19045dfecf96Smrg next->data.atom; 19055dfecf96Smrg next->data.let_sym.symbol = 19065dfecf96Smrg tree->data.atom; 19075dfecf96Smrg goto remove_label; 19085dfecf96Smrg case XBC_PUSH: 19095dfecf96Smrg next->code = XBC_LOADSYM_PUSH; 19105dfecf96Smrg next->data.atom = tree->data.atom; 19115dfecf96Smrg goto remove_label; 19125dfecf96Smrg default: 19135dfecf96Smrg break; 19145dfecf96Smrg } 19155dfecf96Smrg } 19165dfecf96Smrg break; 19175dfecf96Smrg case XBC_LOAD: 19185dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 19195dfecf96Smrg switch (next->code) { 19205dfecf96Smrg case XBC_SET: 19215dfecf96Smrg next->code = XBC_LOAD_SET; 19225dfecf96Smrg next->data.load_set.set = 19235dfecf96Smrg next->data.signed_short; 19245dfecf96Smrg next->data.load_set.load = 19255dfecf96Smrg tree->data.signed_short; 19265dfecf96Smrg goto remove_label; 19275dfecf96Smrg /* TODO add XBC_LOAD_SETSYM */ 19285dfecf96Smrg case XBC_CAR: 19295dfecf96Smrg next->code = XBC_LOAD_CAR; 19305dfecf96Smrg next->data.signed_short = 19315dfecf96Smrg tree->data.signed_short; 19325dfecf96Smrg goto remove_label; 19335dfecf96Smrg case XBC_CDR: 19345dfecf96Smrg next->code = XBC_LOAD_CDR; 19355dfecf96Smrg next->data.signed_short = 19365dfecf96Smrg tree->data.signed_short; 19375dfecf96Smrg goto remove_label; 19385dfecf96Smrg case XBC_PUSH: 19395dfecf96Smrg tree->code = XBC_LOAD_PUSH; 19405dfecf96Smrg goto remove_next_label; 19415dfecf96Smrg case XBC_LET: 19425dfecf96Smrg next->code = XBC_LOAD_LET; 19435dfecf96Smrg next->data.let.name = next->data.atom; 19445dfecf96Smrg next->data.let.offset = 19455dfecf96Smrg tree->data.signed_short; 19465dfecf96Smrg goto remove_label; 19475dfecf96Smrg default: 19485dfecf96Smrg break; 19495dfecf96Smrg } 19505dfecf96Smrg } 19515dfecf96Smrg break; 19525dfecf96Smrg case XBC_LOAD_CAR: 19535dfecf96Smrg if (next && next->type == CodeTreeBytecode && 19545dfecf96Smrg next->code == XBC_SET) { 19555dfecf96Smrg if (next->data.signed_short == 19565dfecf96Smrg tree->data.signed_short) 19575dfecf96Smrg next->code = XBC_LOAD_CAR_STORE; 19585dfecf96Smrg else { 19595dfecf96Smrg next->code = XBC_LOAD_CAR_SET; 19605dfecf96Smrg next->data.load_set.set = 19615dfecf96Smrg next->data.signed_short; 19625dfecf96Smrg next->data.load_set.load = 19635dfecf96Smrg tree->data.signed_short; 19645dfecf96Smrg } 19655dfecf96Smrg goto remove_label; 19665dfecf96Smrg } 19675dfecf96Smrg break; 19685dfecf96Smrg case XBC_LOAD_CDR: 19695dfecf96Smrg if (next && next->type == CodeTreeBytecode && 19705dfecf96Smrg next->code == XBC_SET) { 19715dfecf96Smrg if (next->data.signed_short == 19725dfecf96Smrg tree->data.signed_short) 19735dfecf96Smrg next->code = XBC_LOAD_CDR_STORE; 19745dfecf96Smrg else { 19755dfecf96Smrg next->code = XBC_LOAD_CDR_SET; 19765dfecf96Smrg next->data.load_set.set = 19775dfecf96Smrg next->data.signed_short; 19785dfecf96Smrg next->data.load_set.load = 19795dfecf96Smrg tree->data.signed_short; 19805dfecf96Smrg } 19815dfecf96Smrg goto remove_label; 19825dfecf96Smrg } 19835dfecf96Smrg break; 19845dfecf96Smrg case XBC_CALL: 19855dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 19865dfecf96Smrg switch (next->code) { 19875dfecf96Smrg case XBC_SET: 19885dfecf96Smrg next->code = XBC_CALL_SET; 19895dfecf96Smrg next->data.builtin.offset = 19905dfecf96Smrg next->data.signed_short; 19915dfecf96Smrg next->data.builtin.num_arguments = 19925dfecf96Smrg tree->data.builtin.num_arguments; 19935dfecf96Smrg next->data.builtin.builtin = 19945dfecf96Smrg tree->data.builtin.builtin; 19955dfecf96Smrg goto remove_label; 19965dfecf96Smrg /* TODO add XBC_CALL_SETSYM */ 19975dfecf96Smrg default: 19985dfecf96Smrg break; 19995dfecf96Smrg } 20005dfecf96Smrg } 20015dfecf96Smrg break; 20025dfecf96Smrg case XBC_CAR: 20035dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 20045dfecf96Smrg switch (next->code) { 20055dfecf96Smrg case XBC_SET: 20065dfecf96Smrg next->code = XBC_CAR_SET; 20075dfecf96Smrg goto remove_label; 20085dfecf96Smrg /* TODO add XBC_CAR_SETSYM */ 20095dfecf96Smrg case XBC_PUSH: 20105dfecf96Smrg next->code = XBC_CAR_PUSH; 20115dfecf96Smrg goto remove_label; 20125dfecf96Smrg default: 20135dfecf96Smrg break; 20145dfecf96Smrg } 20155dfecf96Smrg } 20165dfecf96Smrg break; 20175dfecf96Smrg case XBC_CDR: 20185dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 20195dfecf96Smrg switch (next->code) { 20205dfecf96Smrg case XBC_SET: 20215dfecf96Smrg next->code = XBC_CDR_SET; 20225dfecf96Smrg goto remove_label; 20235dfecf96Smrg /* TODO add XBC_CDR_SETSYM */ 20245dfecf96Smrg case XBC_PUSH: 20255dfecf96Smrg next->code = XBC_CDR_PUSH; 20265dfecf96Smrg goto remove_label; 20275dfecf96Smrg default: 20285dfecf96Smrg break; 20295dfecf96Smrg } 20305dfecf96Smrg } 20315dfecf96Smrg break; 20325dfecf96Smrg case XBC_NIL: 20335dfecf96Smrg if (next && next->type == CodeTreeBytecode) { 20345dfecf96Smrg switch (next->code) { 20355dfecf96Smrg case XBC_SET: 20365dfecf96Smrg next->code = XBC_SET_NIL; 20375dfecf96Smrg goto remove_label; 20385dfecf96Smrg /* TODO add XBC_SETSYM_NIL */ 20395dfecf96Smrg default: 20405dfecf96Smrg break; 20415dfecf96Smrg } 20425dfecf96Smrg } 20435dfecf96Smrg break; 20445dfecf96Smrg case XBC_PUSH_NIL: 20455dfecf96Smrg if (next && next->type == CodeTreeBytecode && 20465dfecf96Smrg next->code == XBC_PUSH_NIL) { 20475dfecf96Smrg next->code = XBC_PUSH_NIL_N; 20485dfecf96Smrg next->data.signed_char = 2; 20495dfecf96Smrg goto remove_label; 20505dfecf96Smrg } 20515dfecf96Smrg break; 20525dfecf96Smrg case XBC_PUSH_NIL_N: 20535dfecf96Smrg if (next && next->type == CodeTreeBytecode && 20545dfecf96Smrg next->code == XBC_PUSH_NIL) { 20555dfecf96Smrg next->code = XBC_PUSH_NIL_N; 20565dfecf96Smrg next->data.signed_char = tree->data.signed_char + 1; 20575dfecf96Smrg goto remove_label; 20585dfecf96Smrg } 20595dfecf96Smrg break; 20605dfecf96Smrg case XBC_PUSH_UNSPEC: 20615dfecf96Smrg if (next && next->type == CodeTreeBytecode && 20625dfecf96Smrg next->code == XBC_PUSH_UNSPEC) { 20635dfecf96Smrg next->code = XBC_PUSH_UNSPEC_N; 20645dfecf96Smrg next->data.signed_char = 2; 20655dfecf96Smrg goto remove_label; 20665dfecf96Smrg } 20675dfecf96Smrg break; 20685dfecf96Smrg case XBC_PUSH_UNSPEC_N: 20695dfecf96Smrg if (next && next->type == CodeTreeBytecode && 20705dfecf96Smrg next->code == XBC_PUSH_UNSPEC) { 20715dfecf96Smrg next->code = XBC_PUSH_UNSPEC_N; 20725dfecf96Smrg next->data.signed_char = tree->data.signed_char + 1; 20735dfecf96Smrg goto remove_label; 20745dfecf96Smrg } 20755dfecf96Smrg break; 20765dfecf96Smrg default: 20775dfecf96Smrg break; 20785dfecf96Smrg } 20795dfecf96Smrg break; 20805dfecf96Smrg case CodeTreeBlock: 20815dfecf96Smrg LinkDoOptimize_0(com, tree->data.block); 20825dfecf96Smrg break; 20835dfecf96Smrg default: 20845dfecf96Smrg break; 20855dfecf96Smrg } 20865dfecf96Smrg goto update_label; 20875dfecf96Smrgremove_label: 20885dfecf96Smrg if (tree == block->tree) { 20895dfecf96Smrg block->tree = prev = next; 20905dfecf96Smrg if (tree == block->tail) 20915dfecf96Smrg block->tail = tree; 20925dfecf96Smrg } 20935dfecf96Smrg else 20945dfecf96Smrg prev->next = next; 20955dfecf96Smrg CompileFreeTree(tree); 20965dfecf96Smrg tree = next; 20975dfecf96Smrg continue; 20985dfecf96Smrgremove_next_label: 20995dfecf96Smrg tree->next = next->next; 21005dfecf96Smrg CompileFreeTree(next); 21015dfecf96Smrg continue; 21025dfecf96Smrgupdate_label: 21035dfecf96Smrg prev = tree; 21045dfecf96Smrg tree = tree->next; 21055dfecf96Smrg } 21065dfecf96Smrg} 21075dfecf96Smrg 21085dfecf96Smrgstatic void 21095dfecf96SmrgLinkOptimize_0(LispCom *com) 21105dfecf96Smrg{ 21115dfecf96Smrg /* Recursive */ 21125dfecf96Smrg LinkDoOptimize_0(com, com->block); 21135dfecf96Smrg} 21145dfecf96Smrg 21155dfecf96Smrgstatic void 21165dfecf96SmrgLinkResolveLabels(LispCom *com, CodeBlock *block) 21175dfecf96Smrg{ 21185dfecf96Smrg int i; 21195dfecf96Smrg CodeTree *tree = block->tree; 21205dfecf96Smrg 21215dfecf96Smrg for (; tree; tree = tree->next) { 21225dfecf96Smrg if (tree->type == CodeTreeBlock) 21235dfecf96Smrg LinkResolveLabels(com, tree->data.block); 21245dfecf96Smrg else if (tree->type == CodeTreeLabel) { 21255dfecf96Smrg for (i = 0; i < block->tagbody.length; i++) 21265dfecf96Smrg if (tree->data.object == block->tagbody.labels[i]) { 21275dfecf96Smrg block->tagbody.codes[i] = tree; 21285dfecf96Smrg break; 21295dfecf96Smrg } 21305dfecf96Smrg } 21315dfecf96Smrg } 21325dfecf96Smrg} 21335dfecf96Smrg 21345dfecf96Smrgstatic void 21355dfecf96SmrgLinkResolveJumps(LispCom *com, CodeBlock *block) 21365dfecf96Smrg{ 21375dfecf96Smrg int i; 21385dfecf96Smrg CodeBlock *body = block; 21395dfecf96Smrg CodeTree *ptr, *tree = block->tree; 21405dfecf96Smrg 21415dfecf96Smrg /* Check if there is a tagbody. Error checking already done */ 21425dfecf96Smrg while (body && body->type != LispBlockBody) 21435dfecf96Smrg body = body->prev; 21445dfecf96Smrg 21455dfecf96Smrg for (; tree; tree = tree->next) { 21465dfecf96Smrg switch (tree->type) { 21475dfecf96Smrg case CodeTreeBytecode: 21485dfecf96Smrg case CodeTreeLabel: 21495dfecf96Smrg break; 21505dfecf96Smrg 21515dfecf96Smrg case CodeTreeBlock: 21525dfecf96Smrg LinkResolveJumps(com, tree->data.block); 21535dfecf96Smrg break; 21545dfecf96Smrg 21555dfecf96Smrg case CodeTreeGo: 21565dfecf96Smrg for (i = 0; i < body->tagbody.length; i++) 21575dfecf96Smrg if (tree->data.object == body->tagbody.labels[i]) 21585dfecf96Smrg break; 21595dfecf96Smrg if (i == body->tagbody.length) 21605dfecf96Smrg LispDestroy("COMPILE: no visible tag %s to GO", 21615dfecf96Smrg STROBJ(tree->data.object)); 21625dfecf96Smrg /* Now the jump code is known */ 21635dfecf96Smrg tree->data.tree = body->tagbody.codes[i]; 21645dfecf96Smrg break; 21655dfecf96Smrg 21665dfecf96Smrg case CodeTreeCond: 21675dfecf96Smrg if (tree->code == XBC_JUMPNIL) 21685dfecf96Smrg /* If test is NIL, go to next test */ 21695dfecf96Smrg tree->data.tree = tree->group->next; 21705dfecf96Smrg else if (tree->code == XBC_JUMPT) { 21715dfecf96Smrg /* After executing code, test was T */ 21725dfecf96Smrg for (ptr = tree->group; 21735dfecf96Smrg ptr->code != XBC_NOOP; 21745dfecf96Smrg ptr = ptr->group) 21755dfecf96Smrg ; 21765dfecf96Smrg tree->data.tree = ptr; 21775dfecf96Smrg } 21785dfecf96Smrg break; 21795dfecf96Smrg 21805dfecf96Smrg case CodeTreeJumpIf: 21815dfecf96Smrg if (tree->code != XBC_NOOP) { 21825dfecf96Smrg for (ptr = tree->group; 21835dfecf96Smrg ptr->code != XBC_NOOP; 21845dfecf96Smrg ptr = ptr->group) { 21855dfecf96Smrg if (ptr->type == CodeTreeJump) { 21865dfecf96Smrg /* ELSE code of IF */ 21875dfecf96Smrg ptr = ptr->next; 21885dfecf96Smrg /* Skip inconditional jump node */ 21895dfecf96Smrg break; 21905dfecf96Smrg } 21915dfecf96Smrg } 21925dfecf96Smrg tree->data.tree = ptr; 21935dfecf96Smrg } 21945dfecf96Smrg break; 21955dfecf96Smrg 21965dfecf96Smrg case CodeTreeJump: 21975dfecf96Smrg if (tree->code != XBC_NOOP) 21985dfecf96Smrg tree->data.tree = tree->group; 21995dfecf96Smrg break; 22005dfecf96Smrg 22015dfecf96Smrg case CodeTreeReturn: 22025dfecf96Smrg /* One bytecode is guaranteed to exist in the code tree */ 22035dfecf96Smrg if (tree->data.block->parent == NULL) 22045dfecf96Smrg /* Returning from the function or toplevel form */ 22055dfecf96Smrg tree->data.tree = tree->data.block->tail; 22065dfecf96Smrg else { 22075dfecf96Smrg for (;;) { 22085dfecf96Smrg ptr = tree->data.block->parent->next; 22095dfecf96Smrg if (ptr) { 22105dfecf96Smrg tree->data.tree = ptr; 22115dfecf96Smrg break; 22125dfecf96Smrg } 22135dfecf96Smrg else 22145dfecf96Smrg /* Move one BLOCK up */ 22155dfecf96Smrg tree->data.block = tree->data.block->prev; 22165dfecf96Smrg } 22175dfecf96Smrg } 22185dfecf96Smrg break; 22195dfecf96Smrg } 22205dfecf96Smrg } 22215dfecf96Smrg} 22225dfecf96Smrg 22235dfecf96Smrgstatic long 22245dfecf96SmrgLinkPad(long offset, long adjust, int preffix, int datalen) 22255dfecf96Smrg{ 22265dfecf96Smrg /* If byte or aligned data */ 22275dfecf96Smrg if (datalen <= preffix || ((offset + adjust + preffix) % datalen) == 0) 22285dfecf96Smrg return (adjust); 22295dfecf96Smrg 22305dfecf96Smrg return (adjust + (datalen - ((offset + adjust + preffix) % datalen))); 22315dfecf96Smrg} 22325dfecf96Smrg 22335dfecf96Smrgstatic long 22345dfecf96SmrgLinkFixupOffsets(LispCom *com, CodeTree *tree, long adjust) 22355dfecf96Smrg{ 22365dfecf96Smrg for (; tree; tree = tree->next) { 22375dfecf96Smrg switch (tree->type) { 22385dfecf96Smrg case CodeTreeBytecode: 22395dfecf96Smrg switch (tree->code) { 22405dfecf96Smrg /* byte + short */ 22415dfecf96Smrg case XBC_JUMP: 22425dfecf96Smrg case XBC_JUMPT: 22435dfecf96Smrg case XBC_JUMPNIL: 22445dfecf96Smrg adjust = LinkPad(tree->offset, adjust, 1, 22455dfecf96Smrg sizeof(short)); 22465dfecf96Smrg /*FALLTROUGH*/ 22475dfecf96Smrg default: 22485dfecf96Smrg tree->offset += adjust; 22495dfecf96Smrg break; 22505dfecf96Smrg } 22515dfecf96Smrg break; 22525dfecf96Smrg case CodeTreeLabel: 22535dfecf96Smrg /* Labels are not loaded, just adjust offset */ 22545dfecf96Smrg tree->offset += adjust; 22555dfecf96Smrg break; 22565dfecf96Smrg case CodeTreeJump: 22575dfecf96Smrg case CodeTreeCond: 22585dfecf96Smrg case CodeTreeJumpIf: 22595dfecf96Smrg /* If an opcode will be generated. */ 22605dfecf96Smrg if (tree->code != XBC_NOOP) 22615dfecf96Smrg adjust = LinkPad(tree->offset, adjust, 1, sizeof(short)); 22625dfecf96Smrg tree->offset += adjust; 22635dfecf96Smrg break; 22645dfecf96Smrg case CodeTreeGo: 22655dfecf96Smrg case CodeTreeReturn: 22665dfecf96Smrg adjust = LinkPad(tree->offset, adjust, 1, sizeof(short)); 22675dfecf96Smrg tree->offset += adjust; 22685dfecf96Smrg break; 22695dfecf96Smrg case CodeTreeBlock: 22705dfecf96Smrg adjust = LinkFixupOffsets(com, tree->data.block->tree, adjust); 22715dfecf96Smrg break; 22725dfecf96Smrg } 22735dfecf96Smrg } 22745dfecf96Smrg 22755dfecf96Smrg return (adjust); 22765dfecf96Smrg} 22775dfecf96Smrg 22785dfecf96Smrgstatic void 22795dfecf96SmrgLinkSkipPadding(LispCom *com, CodeTree *tree) 22805dfecf96Smrg{ 22815dfecf96Smrg int found; 22825dfecf96Smrg CodeTree *ptr; 22835dfecf96Smrg 22845dfecf96Smrg /* Recurse to adjust forward jumps or jumps to the start of the block */ 22855dfecf96Smrg for (ptr = tree; ptr; ptr = ptr->next) { 22865dfecf96Smrg if (ptr->type == CodeTreeBlock) { 22875dfecf96Smrg LinkSkipPadding(com, ptr->data.block->tree); 22885dfecf96Smrg ptr->offset = ptr->data.block->tree->offset; 22895dfecf96Smrg } 22905dfecf96Smrg } 22915dfecf96Smrg 22925dfecf96Smrg /* Adjust the nodes offsets */ 22935dfecf96Smrg for (; tree; tree = tree->next) { 22945dfecf96Smrg switch (tree->type) { 22955dfecf96Smrg case CodeTreeBytecode: 22965dfecf96Smrg case CodeTreeBlock: 22975dfecf96Smrg case CodeTreeGo: 22985dfecf96Smrg case CodeTreeReturn: 22995dfecf96Smrg break; 23005dfecf96Smrg case CodeTreeJump: 23015dfecf96Smrg case CodeTreeCond: 23025dfecf96Smrg case CodeTreeJumpIf: 23035dfecf96Smrg if (tree->code != XBC_NOOP) 23045dfecf96Smrg /* If code will be generated */ 23055dfecf96Smrg break; 23065dfecf96Smrg case CodeTreeLabel: 23075dfecf96Smrg /* This should be done in reversed order, but to avoid 23085dfecf96Smrg * the requirement of a prev pointer, do the job in a 23095dfecf96Smrg * harder way here. */ 23105dfecf96Smrg for (found = 0, ptr = tree->next; ptr; ptr = ptr->next) { 23115dfecf96Smrg switch (ptr->type) { 23125dfecf96Smrg case CodeTreeBytecode: 23135dfecf96Smrg case CodeTreeBlock: 23145dfecf96Smrg case CodeTreeGo: 23155dfecf96Smrg case CodeTreeReturn: 23165dfecf96Smrg found = 1; 23175dfecf96Smrg break; 23185dfecf96Smrg case CodeTreeJump: 23195dfecf96Smrg case CodeTreeCond: 23205dfecf96Smrg case CodeTreeJumpIf: 23215dfecf96Smrg if (ptr->code != XBC_NOOP) 23225dfecf96Smrg found = 1; 23235dfecf96Smrg break; 23245dfecf96Smrg case CodeTreeLabel: 23255dfecf96Smrg break; 23265dfecf96Smrg } 23275dfecf96Smrg if (found) 23285dfecf96Smrg break; 23295dfecf96Smrg } 23305dfecf96Smrg if (found) 23315dfecf96Smrg tree->offset = ptr->offset; 23325dfecf96Smrg break; 23335dfecf96Smrg } 23345dfecf96Smrg } 23355dfecf96Smrg} 23365dfecf96Smrg 23375dfecf96Smrgstatic void 23385dfecf96SmrgLinkCalculateJump(LispCom *com, CodeTree *tree, LispByteOpcode code) 23395dfecf96Smrg{ 23405dfecf96Smrg long jumpto, offset, distance; 23415dfecf96Smrg 23425dfecf96Smrg tree->type = CodeTreeBytecode; 23435dfecf96Smrg /* After the opcode */ 23445dfecf96Smrg offset = tree->offset + 1; 23455dfecf96Smrg jumpto = tree->data.tree->offset; 23465dfecf96Smrg /* Effective distance */ 23475dfecf96Smrg distance = jumpto - offset; 23485dfecf96Smrg tree->code = code; 23495dfecf96Smrg if (distance < -32768 || distance > 32767) { 23505dfecf96Smrg COMPILE_FAILURE("jump too long"); 23515dfecf96Smrg } 23525dfecf96Smrg tree->data.signed_int = distance; 23535dfecf96Smrg} 23545dfecf96Smrg 23555dfecf96Smrgstatic void 23565dfecf96SmrgLinkFixupJumps(LispCom *com, CodeTree *tree) 23575dfecf96Smrg{ 23585dfecf96Smrg for (; tree; tree = tree->next) { 23595dfecf96Smrg switch (tree->type) { 23605dfecf96Smrg case CodeTreeBytecode: 23615dfecf96Smrg case CodeTreeLabel: 23625dfecf96Smrg break; 23635dfecf96Smrg case CodeTreeCond: 23645dfecf96Smrg if (tree->code == XBC_JUMPNIL) 23655dfecf96Smrg /* Go to next test if NIL */ 23665dfecf96Smrg LinkCalculateJump(com, tree, XBC_JUMPNIL); 23675dfecf96Smrg else if (tree->code == XBC_JUMPT) 23685dfecf96Smrg /* After executing T code */ 23695dfecf96Smrg LinkCalculateJump(com, tree, XBC_JUMP); 23705dfecf96Smrg break; 23715dfecf96Smrg case CodeTreeJumpIf: 23725dfecf96Smrg if (tree->code != XBC_NOOP) 23735dfecf96Smrg LinkCalculateJump(com, tree, tree->code); 23745dfecf96Smrg break; 23755dfecf96Smrg case CodeTreeGo: 23765dfecf96Smrg /* Inconditional jump */ 23775dfecf96Smrg LinkCalculateJump(com, tree, XBC_JUMP); 23785dfecf96Smrg break; 23795dfecf96Smrg case CodeTreeReturn: 23805dfecf96Smrg /* Inconditional jump */ 23815dfecf96Smrg if (tree->data.tree != tree) 23825dfecf96Smrg /* If need to skip something */ 23835dfecf96Smrg LinkCalculateJump(com, tree, XBC_JUMP); 23845dfecf96Smrg break; 23855dfecf96Smrg case CodeTreeBlock: 23865dfecf96Smrg LinkFixupJumps(com, tree->data.block->tree); 23875dfecf96Smrg break; 23885dfecf96Smrg case CodeTreeJump: 23895dfecf96Smrg if (tree->code != XBC_NOOP) 23905dfecf96Smrg LinkCalculateJump(com, tree, tree->code); 23915dfecf96Smrg } 23925dfecf96Smrg } 23935dfecf96Smrg} 23945dfecf96Smrg 23955dfecf96Smrgstatic void 23965dfecf96SmrgLinkBuildTableSymbol(LispCom *com, LispAtom *symbol) 23975dfecf96Smrg{ 23985dfecf96Smrg if (BuildTablePointer(symbol, (void***)&com->table.symbols, 23995dfecf96Smrg &com->table.num_symbols) > 0xff) { 24005dfecf96Smrg COMPILE_FAILURE("more than 256 symbols"); 24015dfecf96Smrg } 24025dfecf96Smrg} 24035dfecf96Smrg 24045dfecf96Smrgstatic void 24055dfecf96SmrgLinkBuildTableConstant(LispCom *com, LispObj *constant) 24065dfecf96Smrg{ 24075dfecf96Smrg if (BuildTablePointer(constant, (void***)&com->table.constants, 24085dfecf96Smrg &com->table.num_constants) > 0xff) { 24095dfecf96Smrg COMPILE_FAILURE("more than 256 constants"); 24105dfecf96Smrg } 24115dfecf96Smrg} 24125dfecf96Smrg 24135dfecf96Smrgstatic void 24145dfecf96SmrgLinkBuildTableBuiltin(LispCom *com, LispBuiltin *builtin) 24155dfecf96Smrg{ 24165dfecf96Smrg if (BuildTablePointer(builtin, (void***)&com->table.builtins, 24175dfecf96Smrg &com->table.num_builtins) > 0xff) { 24185dfecf96Smrg COMPILE_FAILURE("more than 256 functions"); 24195dfecf96Smrg } 24205dfecf96Smrg} 24215dfecf96Smrg 24225dfecf96Smrgstatic void 24235dfecf96SmrgLinkBuildTableBytecode(LispCom *com, LispObj *bytecode) 24245dfecf96Smrg{ 24255dfecf96Smrg if (BuildTablePointer(bytecode, (void***)&com->table.bytecodes, 24265dfecf96Smrg &com->table.num_bytecodes) > 0xff) { 24275dfecf96Smrg COMPILE_FAILURE("more than 256 bytecode functions"); 24285dfecf96Smrg } 24295dfecf96Smrg} 24305dfecf96Smrg 24315dfecf96Smrgstatic void 24325dfecf96SmrgLinkBuildTables(LispCom *com, CodeBlock *block) 24335dfecf96Smrg{ 24345dfecf96Smrg CodeTree *tree; 24355dfecf96Smrg 24365dfecf96Smrg for (tree = block->tree; tree; tree = tree->next) { 24375dfecf96Smrg switch (tree->type) { 24385dfecf96Smrg case CodeTreeBytecode: 24395dfecf96Smrg switch (tree->code) { 24405dfecf96Smrg case XBC_LET: 24415dfecf96Smrg case XBC_LETX: 24425dfecf96Smrg case XBC_LET_NIL: 24435dfecf96Smrg case XBC_LETX_NIL: 24445dfecf96Smrg case XBC_SETSYM: 24455dfecf96Smrg case XBC_LOADSYM: 24465dfecf96Smrg case XBC_LOADSYM_PUSH: 24475dfecf96Smrg LinkBuildTableSymbol(com, tree->data.atom); 24485dfecf96Smrg break; 24495dfecf96Smrg case XBC_STRUCTP: 24505dfecf96Smrg case XBC_LOADCON: 24515dfecf96Smrg case XBC_LOADCON_PUSH: 24525dfecf96Smrg LinkBuildTableConstant(com, tree->data.object); 24535dfecf96Smrg break; 24545dfecf96Smrg case XBC_LOADCON_SET: 24555dfecf96Smrg LinkBuildTableConstant(com, tree->data.load_con_set.object); 24565dfecf96Smrg break; 24575dfecf96Smrg case XBC_CALL: 24585dfecf96Smrg case XBC_CALL_SET: 24595dfecf96Smrg LinkBuildTableBuiltin(com, tree->data.builtin.builtin); 24605dfecf96Smrg break; 24615dfecf96Smrg case XBC_BYTECALL: 24625dfecf96Smrg LinkBuildTableBytecode(com, tree->data.bytecall.code); 24635dfecf96Smrg break; 24645dfecf96Smrg case XBC_LOAD_LET: 24655dfecf96Smrg case XBC_LOAD_LETX: 24665dfecf96Smrg LinkBuildTableSymbol(com, tree->data.let.name); 24675dfecf96Smrg break; 24685dfecf96Smrg case XBC_STRUCT: 24695dfecf96Smrg LinkBuildTableConstant(com, tree->data.struc.definition); 24705dfecf96Smrg break; 24715dfecf96Smrg case XBC_LOADSYM_LET: 24725dfecf96Smrg case XBC_LOADSYM_LETX: 24735dfecf96Smrg LinkBuildTableSymbol(com, tree->data.let_sym.symbol); 24745dfecf96Smrg LinkBuildTableSymbol(com, tree->data.let_sym.name); 24755dfecf96Smrg break; 24765dfecf96Smrg case XBC_LOADCON_LET: 24775dfecf96Smrg case XBC_LOADCON_LETX: 24785dfecf96Smrg LinkBuildTableConstant(com, tree->data.let_con.object); 24795dfecf96Smrg LinkBuildTableSymbol(com, tree->data.let_con.name); 24805dfecf96Smrg break; 24815dfecf96Smrg case XBC_CCONS: 24825dfecf96Smrg case XBC_FUNCALL: 24835dfecf96Smrg LinkBuildTableConstant(com, tree->data.cons.car); 24845dfecf96Smrg LinkBuildTableConstant(com, tree->data.cons.cdr); 24855dfecf96Smrg break; 24865dfecf96Smrg default: 24875dfecf96Smrg break; 24885dfecf96Smrg } 24895dfecf96Smrg break; 24905dfecf96Smrg case CodeTreeBlock: 24915dfecf96Smrg LinkBuildTables(com, tree->data.block); 24925dfecf96Smrg break; 24935dfecf96Smrg default: 24945dfecf96Smrg break; 24955dfecf96Smrg } 24965dfecf96Smrg } 24975dfecf96Smrg} 24985dfecf96Smrg 24995dfecf96Smrgstatic long 25005dfecf96SmrgLinkEmmitBytecode(LispCom *com, CodeTree *tree, 25015dfecf96Smrg unsigned char *bytecode, long offset) 25025dfecf96Smrg{ 25035dfecf96Smrg short i; 25045dfecf96Smrg 25055dfecf96Smrg for (; tree; tree = tree->next) { 25065dfecf96Smrg /* Fill padding */ 25075dfecf96Smrg while (offset < tree->offset) 25085dfecf96Smrg bytecode[offset++] = XBC_NOOP; 25095dfecf96Smrg 25105dfecf96Smrg switch (tree->type) { 25115dfecf96Smrg case CodeTreeBytecode: 25125dfecf96Smrg bytecode[offset++] = tree->code; 25135dfecf96Smrg switch (tree->code) { 25145dfecf96Smrg /* Noop should not enter the CodeTree */ 25155dfecf96Smrg case XBC_NOOP: 25165dfecf96Smrg INTERNAL_ERROR(__LINE__); 25175dfecf96Smrg break; 25185dfecf96Smrg 25195dfecf96Smrg /* byte */ 25205dfecf96Smrg case XBC_BCONS: 25215dfecf96Smrg case XBC_BCONS1: 25225dfecf96Smrg case XBC_BCONS2: 25235dfecf96Smrg case XBC_BCONS3: 25245dfecf96Smrg case XBC_BCONS4: 25255dfecf96Smrg case XBC_BCONS5: 25265dfecf96Smrg case XBC_BCONS6: 25275dfecf96Smrg case XBC_BCONS7: 25285dfecf96Smrg case XBC_INV: 25295dfecf96Smrg case XBC_NIL: 25305dfecf96Smrg case XBC_T: 25315dfecf96Smrg case XBC_PUSH_NIL: 25325dfecf96Smrg case XBC_PUSH_UNSPEC: 25335dfecf96Smrg case XBC_PUSH_T: 25345dfecf96Smrg case XBC_CAR_PUSH: 25355dfecf96Smrg case XBC_CDR_PUSH: 25365dfecf96Smrg case XBC_PUSH: 25375dfecf96Smrg case XBC_LSTAR: 25385dfecf96Smrg case XBC_LCONS: 25395dfecf96Smrg case XBC_LFINI: 25405dfecf96Smrg case XBC_RETURN: 25415dfecf96Smrg case XBC_CSTAR: 25425dfecf96Smrg case XBC_CFINI: 25435dfecf96Smrg case XBC_CAR: 25445dfecf96Smrg case XBC_CDR: 25455dfecf96Smrg case XBC_RPLACA: 25465dfecf96Smrg case XBC_RPLACD: 25475dfecf96Smrg case XBC_EQ: 25485dfecf96Smrg case XBC_EQL: 25495dfecf96Smrg case XBC_EQUAL: 25505dfecf96Smrg case XBC_EQUALP: 25515dfecf96Smrg case XBC_LENGTH: 25525dfecf96Smrg case XBC_LAST: 25535dfecf96Smrg case XBC_NTHCDR: 25545dfecf96Smrg break; 25555dfecf96Smrg 25565dfecf96Smrg /* byte + byte */ 25575dfecf96Smrg case XBC_LETREC: 25585dfecf96Smrg case XBC_PRED: 25595dfecf96Smrg case XBC_PUSH_NIL_N: 25605dfecf96Smrg case XBC_PUSH_UNSPEC_N: 25615dfecf96Smrg bytecode[offset++] = tree->data.signed_char; 25625dfecf96Smrg break; 25635dfecf96Smrg 25645dfecf96Smrg /* byte + byte */ 25655dfecf96Smrg case XBC_CAR_SET: 25665dfecf96Smrg case XBC_CDR_SET: 25675dfecf96Smrg case XBC_SET: 25685dfecf96Smrg case XBC_SET_NIL: 25695dfecf96Smrg case XBC_LETBIND: 25705dfecf96Smrg case XBC_UNLET: 25715dfecf96Smrg case XBC_LOAD_PUSH: 25725dfecf96Smrg case XBC_LOAD: 25735dfecf96Smrg case XBC_LOAD_CAR: 25745dfecf96Smrg case XBC_LOAD_CDR: 25755dfecf96Smrg case XBC_LOAD_CAR_STORE: 25765dfecf96Smrg case XBC_LOAD_CDR_STORE: 25775dfecf96Smrg bytecode[offset++] = tree->data.signed_short; 25785dfecf96Smrg break; 25795dfecf96Smrg 25805dfecf96Smrg /* byte + byte + byte */ 25815dfecf96Smrg case XBC_LOAD_SET: 25825dfecf96Smrg case XBC_LOAD_CAR_SET: 25835dfecf96Smrg case XBC_LOAD_CDR_SET: 25845dfecf96Smrg bytecode[offset++] = tree->data.load_set.load; 25855dfecf96Smrg bytecode[offset++] = tree->data.load_set.set; 25865dfecf96Smrg break; 25875dfecf96Smrg 25885dfecf96Smrg /* byte + short */ 25895dfecf96Smrg case XBC_JUMP: 25905dfecf96Smrg case XBC_JUMPT: 25915dfecf96Smrg case XBC_JUMPNIL: 25925dfecf96Smrg *(short*)(bytecode + offset) = tree->data.signed_int; 25935dfecf96Smrg offset += sizeof(short); 25945dfecf96Smrg break; 25955dfecf96Smrg 25965dfecf96Smrg /* byte + byte */ 25975dfecf96Smrg case XBC_LET: 25985dfecf96Smrg case XBC_LETX: 25995dfecf96Smrg case XBC_LET_NIL: 26005dfecf96Smrg case XBC_LETX_NIL: 26015dfecf96Smrg case XBC_SETSYM: 26025dfecf96Smrg case XBC_LOADSYM: 26035dfecf96Smrg case XBC_LOADSYM_PUSH: 26045dfecf96Smrg i = FindIndex(tree->data.atom, 26055dfecf96Smrg (void**)com->table.symbols, 26065dfecf96Smrg com->table.num_symbols); 26075dfecf96Smrg bytecode[offset++] = i; 26085dfecf96Smrg break; 26095dfecf96Smrg 26105dfecf96Smrg /* byte + byte */ 26115dfecf96Smrg case XBC_STRUCTP: 26125dfecf96Smrg case XBC_LOADCON: 26135dfecf96Smrg case XBC_LOADCON_PUSH: 26145dfecf96Smrg i = FindIndex(tree->data.object, 26155dfecf96Smrg (void**)com->table.constants, 26165dfecf96Smrg com->table.num_constants); 26175dfecf96Smrg bytecode[offset++] = i; 26185dfecf96Smrg break; 26195dfecf96Smrg 26205dfecf96Smrg /* byte + byte + byte */ 26215dfecf96Smrg case XBC_LOADCON_SET: 26225dfecf96Smrg i = FindIndex(tree->data.load_con_set.object, 26235dfecf96Smrg (void**)com->table.constants, 26245dfecf96Smrg com->table.num_constants); 26255dfecf96Smrg bytecode[offset++] = i; 26265dfecf96Smrg bytecode[offset++] = tree->data.load_con_set.offset; 26275dfecf96Smrg break; 26285dfecf96Smrg 26295dfecf96Smrg /* byte + byte + byte */ 26305dfecf96Smrg case XBC_CALL: 26315dfecf96Smrg bytecode[offset++] = tree->data.builtin.num_arguments; 26325dfecf96Smrg i = FindIndex(tree->data.builtin.builtin, 26335dfecf96Smrg (void**)com->table.builtins, 26345dfecf96Smrg com->table.num_builtins); 26355dfecf96Smrg bytecode[offset++] = i; 26365dfecf96Smrg break; 26375dfecf96Smrg 26385dfecf96Smrg /* byte + byte + byte */ 26395dfecf96Smrg case XBC_BYTECALL: 26405dfecf96Smrg bytecode[offset++] = tree->data.bytecall.num_arguments; 26415dfecf96Smrg i = FindIndex(tree->data.bytecall.code, 26425dfecf96Smrg (void**)com->table.bytecodes, 26435dfecf96Smrg com->table.num_bytecodes); 26445dfecf96Smrg bytecode[offset++] = i; 26455dfecf96Smrg break; 26465dfecf96Smrg 26475dfecf96Smrg /* byte + byte + byte + byte */ 26485dfecf96Smrg case XBC_CALL_SET: 26495dfecf96Smrg bytecode[offset++] = tree->data.builtin.num_arguments; 26505dfecf96Smrg i = FindIndex(tree->data.builtin.builtin, 26515dfecf96Smrg (void**)com->table.builtins, 26525dfecf96Smrg com->table.num_builtins); 26535dfecf96Smrg bytecode[offset++] = i; 26545dfecf96Smrg bytecode[offset++] = tree->data.builtin.offset; 26555dfecf96Smrg break; 26565dfecf96Smrg 26575dfecf96Smrg /* byte + byte + byte */ 26585dfecf96Smrg case XBC_LOAD_LET: 26595dfecf96Smrg case XBC_LOAD_LETX: 26605dfecf96Smrg bytecode[offset++] = tree->data.let.offset; 26615dfecf96Smrg i = FindIndex(tree->data.let.name, 26625dfecf96Smrg (void**)com->table.symbols, 26635dfecf96Smrg com->table.num_symbols); 26645dfecf96Smrg bytecode[offset++] = i; 26655dfecf96Smrg break; 26665dfecf96Smrg 26675dfecf96Smrg /* byte + byte + byte */ 26685dfecf96Smrg case XBC_STRUCT: 26695dfecf96Smrg bytecode[offset++] = tree->data.struc.offset; 26705dfecf96Smrg i = FindIndex(tree->data.struc.definition, 26715dfecf96Smrg (void**)com->table.constants, 26725dfecf96Smrg com->table.num_constants); 26735dfecf96Smrg bytecode[offset++] = i; 26745dfecf96Smrg break; 26755dfecf96Smrg 26765dfecf96Smrg /* byte + byte + byte */ 26775dfecf96Smrg case XBC_LOADSYM_LET: 26785dfecf96Smrg case XBC_LOADSYM_LETX: 26795dfecf96Smrg i = FindIndex(tree->data.let_sym.symbol, 26805dfecf96Smrg (void**)com->table.symbols, 26815dfecf96Smrg com->table.num_symbols); 26825dfecf96Smrg bytecode[offset++] = i; 26835dfecf96Smrg i = FindIndex(tree->data.let_sym.name, 26845dfecf96Smrg (void**)com->table.symbols, 26855dfecf96Smrg com->table.num_symbols); 26865dfecf96Smrg bytecode[offset++] = i; 26875dfecf96Smrg break; 26885dfecf96Smrg 26895dfecf96Smrg /* byte + byte + byte */ 26905dfecf96Smrg case XBC_LOADCON_LET: 26915dfecf96Smrg case XBC_LOADCON_LETX: 26925dfecf96Smrg i = FindIndex(tree->data.let_con.object, 26935dfecf96Smrg (void**)com->table.constants, 26945dfecf96Smrg com->table.num_constants); 26955dfecf96Smrg bytecode[offset++] = i; 26965dfecf96Smrg i = FindIndex(tree->data.let_con.name, 26975dfecf96Smrg (void**)com->table.symbols, 26985dfecf96Smrg com->table.num_symbols); 26995dfecf96Smrg bytecode[offset++] = i; 27005dfecf96Smrg break; 27015dfecf96Smrg 27025dfecf96Smrg /* byte + byte + byte */ 27035dfecf96Smrg case XBC_CCONS: 27045dfecf96Smrg case XBC_FUNCALL: 27055dfecf96Smrg i = FindIndex(tree->data.cons.car, 27065dfecf96Smrg (void**)com->table.constants, 27075dfecf96Smrg com->table.num_constants); 27085dfecf96Smrg bytecode[offset++] = i; 27095dfecf96Smrg i = FindIndex(tree->data.cons.cdr, 27105dfecf96Smrg (void**)com->table.constants, 27115dfecf96Smrg com->table.num_constants); 27125dfecf96Smrg bytecode[offset++] = i; 27135dfecf96Smrg break; 27145dfecf96Smrg } 27155dfecf96Smrg break; 27165dfecf96Smrg case CodeTreeLabel: 27175dfecf96Smrg /* Labels are not loaded */ 27185dfecf96Smrg break; 27195dfecf96Smrg case CodeTreeCond: 27205dfecf96Smrg case CodeTreeJump: 27215dfecf96Smrg case CodeTreeJumpIf: 27225dfecf96Smrg if (tree->code != XBC_NOOP) 27235dfecf96Smrg INTERNAL_ERROR(__LINE__); 27245dfecf96Smrg break; 27255dfecf96Smrg case CodeTreeGo: 27265dfecf96Smrg INTERNAL_ERROR(__LINE__); 27275dfecf96Smrg break; 27285dfecf96Smrg case CodeTreeReturn: 27295dfecf96Smrg if (tree->data.tree != tree) 27305dfecf96Smrg INTERNAL_ERROR(__LINE__); 27315dfecf96Smrg break; 27325dfecf96Smrg case CodeTreeBlock: 27335dfecf96Smrg offset = LinkEmmitBytecode(com, tree->data.block->tree, 27345dfecf96Smrg bytecode, offset); 27355dfecf96Smrg break; 27365dfecf96Smrg } 27375dfecf96Smrg } 27385dfecf96Smrg 27395dfecf96Smrg return (offset); 27405dfecf96Smrg} 27415dfecf96Smrg 27425dfecf96Smrgstatic void 27435dfecf96SmrgLinkBytecode(LispCom *com) 27445dfecf96Smrg{ 27455dfecf96Smrg long offset, count; 27465dfecf96Smrg unsigned char **codes; 27475dfecf96Smrg LispObj **names; 27485dfecf96Smrg 27495dfecf96Smrg /* Close bytecode */ 27505dfecf96Smrg com_Bytecode(com, XBC_RETURN); 27515dfecf96Smrg 27525dfecf96Smrg /* The only usage of this information for now, and still may generate 27535dfecf96Smrg * false positives because arguments to unamed functions are not being 27545dfecf96Smrg * parsed as well as arguments to yet undefined function/maros. 27555dfecf96Smrg * XXX should also add declaim/declare to let the code specify that 27565dfecf96Smrg * the argument is unused */ 27575dfecf96Smrg LinkWarnUnused(com, com->block); 27585dfecf96Smrg 27595dfecf96Smrg /* First level optimization */ 27605dfecf96Smrg LinkOptimize_0(com); 27615dfecf96Smrg 27625dfecf96Smrg /* Resolve tagbody labels */ 27635dfecf96Smrg LinkResolveLabels(com, com->block); 27645dfecf96Smrg 27655dfecf96Smrg /* Resolve any pending jumps */ 27665dfecf96Smrg LinkResolveJumps(com, com->block); 27675dfecf96Smrg 27685dfecf96Smrg /* Calculate unpadded offsets */ 27695dfecf96Smrg LinkBuildOffsets(com, com->block->tree, 0); 27705dfecf96Smrg 27715dfecf96Smrg /* Do padding for aligned memory reads */ 27725dfecf96Smrg LinkFixupOffsets(com, com->block->tree, 0); 27735dfecf96Smrg 27745dfecf96Smrg /* Jumps normally are to a node that does not generate code, 27755dfecf96Smrg * and due to padding, the jump may go to a address with a 27765dfecf96Smrg * XBC_NOOP, so adjust the jump to the next useful opcode. */ 27775dfecf96Smrg LinkSkipPadding(com, com->block->tree); 27785dfecf96Smrg 27795dfecf96Smrg /* Now addresses are known */ 27805dfecf96Smrg LinkFixupJumps(com, com->block->tree); 27815dfecf96Smrg 27825dfecf96Smrg /* Build symbol, constant and builtin tables */ 27835dfecf96Smrg LinkBuildTables(com, com->block); 27845dfecf96Smrg 27855dfecf96Smrg /* Stack info */ 27865dfecf96Smrg com->length = sizeof(short) * 3; 27875dfecf96Smrg /* Tables info */ 27885dfecf96Smrg com->length += sizeof(short) * 4; 27895dfecf96Smrg com->length += com->table.num_constants * sizeof(LispObj*); 27905dfecf96Smrg com->length += com->table.num_symbols * sizeof(LispAtom*); 27915dfecf96Smrg com->length += com->table.num_builtins * sizeof(LispBuiltin*); 27925dfecf96Smrg com->length += com->table.num_bytecodes * sizeof(unsigned char*); 27935dfecf96Smrg com->length += com->table.num_bytecodes * sizeof(LispObj*); 27945dfecf96Smrg 27955dfecf96Smrg /* Allocate space for the bytecode stream */ 27965dfecf96Smrg com->length += com->block->tail->offset + 1; 27975dfecf96Smrg com->bytecode = LispMalloc(com->length); 27985dfecf96Smrg 27995dfecf96Smrg /* Add header */ 28005dfecf96Smrg offset = 0; 28015dfecf96Smrg *(short*)(com->bytecode + offset) = com->stack.stack; 28025dfecf96Smrg offset += sizeof(short); 28035dfecf96Smrg *(short*)(com->bytecode + offset) = com->stack.bstack; 28045dfecf96Smrg offset += sizeof(short); 28055dfecf96Smrg *(short*)(com->bytecode + offset) = com->stack.pstack; 28065dfecf96Smrg offset += sizeof(short); 28075dfecf96Smrg 28085dfecf96Smrg *(short*)(com->bytecode + offset) = com->table.num_constants; 28095dfecf96Smrg offset += sizeof(short); 28105dfecf96Smrg *(short*)(com->bytecode + offset) = com->table.num_symbols; 28115dfecf96Smrg offset += sizeof(short); 28125dfecf96Smrg *(short*)(com->bytecode + offset) = com->table.num_builtins; 28135dfecf96Smrg offset += sizeof(short); 28145dfecf96Smrg *(short*)(com->bytecode + offset) = com->table.num_bytecodes; 28155dfecf96Smrg offset += sizeof(short); 28165dfecf96Smrg 28175dfecf96Smrg count = sizeof(LispObj*) * com->table.num_constants; 28185dfecf96Smrg memcpy(com->bytecode + offset, com->table.constants, count); 28195dfecf96Smrg offset += count; 28205dfecf96Smrg count = sizeof(LispAtom*) * com->table.num_symbols; 28215dfecf96Smrg memcpy(com->bytecode + offset, com->table.symbols, count); 28225dfecf96Smrg offset += count; 28235dfecf96Smrg count = sizeof(LispBuiltin*) * com->table.num_builtins; 28245dfecf96Smrg memcpy(com->bytecode + offset, com->table.builtins, count); 28255dfecf96Smrg offset += count; 28265dfecf96Smrg 28275dfecf96Smrg /* Store bytecode information */ 28285dfecf96Smrg for (count = 0, codes = (unsigned char**)(com->bytecode + offset); 28295dfecf96Smrg count < com->table.num_bytecodes; count++, codes++) 28305dfecf96Smrg *codes = com->table.bytecodes[count]->data.bytecode.bytecode->code; 28315dfecf96Smrg offset += com->table.num_bytecodes * sizeof(unsigned char*); 28325dfecf96Smrg /* Store names, only useful for disassemble but may also be used 28335dfecf96Smrg * to check if a function was redefined, and the bytecode is referencing 28345dfecf96Smrg * the older version, the current version can be checked looking at 28355dfecf96Smrg * <name>->data.atom */ 28365dfecf96Smrg for (count = 0, names = (LispObj**)(com->bytecode + offset); 28375dfecf96Smrg count < com->table.num_bytecodes; count++, names++) 28385dfecf96Smrg *names = com->table.bytecodes[count]->data.bytecode.name; 28395dfecf96Smrg offset += com->table.num_bytecodes * sizeof(LispObj*); 28405dfecf96Smrg 28415dfecf96Smrg /* Generate it */ 28425dfecf96Smrg LinkEmmitBytecode(com, com->block->tree, com->bytecode + offset, 0); 28435dfecf96Smrg} 28445dfecf96Smrg 28455dfecf96Smrgstatic LispObj * 28465dfecf96SmrgExecuteBytecode(register unsigned char *stream) 28475dfecf96Smrg{ 28485dfecf96Smrg register LispObj *reg0; 28495dfecf96Smrg register LispAtom *atom; 28505dfecf96Smrg register short offset; 28515dfecf96Smrg LispObj *reg1; 28525dfecf96Smrg LispBuiltin *builtin; 28535dfecf96Smrg LispObj *lambda; 28545dfecf96Smrg LispObj *arguments; 28555dfecf96Smrg unsigned char *bytecode; 28565dfecf96Smrg 28575dfecf96Smrg LispObj **constants; 28585dfecf96Smrg LispAtom **symbols; 28595dfecf96Smrg LispBuiltin **builtins; 28605dfecf96Smrg unsigned char **codes; 28615dfecf96Smrg short num_constants, num_symbols, num_builtins, num_codes; 28625dfecf96Smrg 28635dfecf96Smrg int lex, len; 28645dfecf96Smrg 28655dfecf96Smrg /* To control gc protected slots */ 28665dfecf96Smrg int phead, pbase; 28675dfecf96Smrg 28685dfecf96Smrg long fixnum = 0; 28695dfecf96Smrg 28705dfecf96Smrg#if defined(__GNUC__) && !defined(ANSI_SOURCE) 28715dfecf96Smrg#define ALLOW_GOTO_ADDRESS 28725dfecf96Smrg#endif 28735dfecf96Smrg 28745dfecf96Smrg#ifdef ALLOW_GOTO_ADDRESS 28755dfecf96Smrg#define JUMP_ADDRESS(label) &&label 28765dfecf96Smrg static const void *opcode_labels[] = { 28775dfecf96Smrg JUMP_ADDRESS(XBC_NOOP), 28785dfecf96Smrg JUMP_ADDRESS(XBC_INV), 28795dfecf96Smrg JUMP_ADDRESS(XBC_NIL), 28805dfecf96Smrg JUMP_ADDRESS(XBC_T), 28815dfecf96Smrg JUMP_ADDRESS(XBC_PRED), 28825dfecf96Smrg JUMP_ADDRESS(XBC_CAR), 28835dfecf96Smrg JUMP_ADDRESS(XBC_CDR), 28845dfecf96Smrg JUMP_ADDRESS(XBC_CAR_SET), 28855dfecf96Smrg JUMP_ADDRESS(XBC_CDR_SET), 28865dfecf96Smrg JUMP_ADDRESS(XBC_RPLACA), 28875dfecf96Smrg JUMP_ADDRESS(XBC_RPLACD), 28885dfecf96Smrg JUMP_ADDRESS(XBC_EQ), 28895dfecf96Smrg JUMP_ADDRESS(XBC_EQL), 28905dfecf96Smrg JUMP_ADDRESS(XBC_EQUAL), 28915dfecf96Smrg JUMP_ADDRESS(XBC_EQUALP), 28925dfecf96Smrg JUMP_ADDRESS(XBC_LENGTH), 28935dfecf96Smrg JUMP_ADDRESS(XBC_LAST), 28945dfecf96Smrg JUMP_ADDRESS(XBC_NTHCDR), 28955dfecf96Smrg JUMP_ADDRESS(XBC_CAR_PUSH), 28965dfecf96Smrg JUMP_ADDRESS(XBC_CDR_PUSH), 28975dfecf96Smrg JUMP_ADDRESS(XBC_PUSH), 28985dfecf96Smrg JUMP_ADDRESS(XBC_PUSH_NIL), 28995dfecf96Smrg JUMP_ADDRESS(XBC_PUSH_UNSPEC), 29005dfecf96Smrg JUMP_ADDRESS(XBC_PUSH_T), 29015dfecf96Smrg JUMP_ADDRESS(XBC_PUSH_NIL_N), 29025dfecf96Smrg JUMP_ADDRESS(XBC_PUSH_UNSPEC_N), 29035dfecf96Smrg JUMP_ADDRESS(XBC_LET), 29045dfecf96Smrg JUMP_ADDRESS(XBC_LETX), 29055dfecf96Smrg JUMP_ADDRESS(XBC_LET_NIL), 29065dfecf96Smrg JUMP_ADDRESS(XBC_LETX_NIL), 29075dfecf96Smrg JUMP_ADDRESS(XBC_LETBIND), 29085dfecf96Smrg JUMP_ADDRESS(XBC_UNLET), 29095dfecf96Smrg JUMP_ADDRESS(XBC_LOAD), 29105dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_LET), 29115dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_LETX), 29125dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_PUSH), 29135dfecf96Smrg JUMP_ADDRESS(XBC_LOADCON), 29145dfecf96Smrg JUMP_ADDRESS(XBC_LOADCON_LET), 29155dfecf96Smrg JUMP_ADDRESS(XBC_LOADCON_LETX), 29165dfecf96Smrg JUMP_ADDRESS(XBC_LOADCON_PUSH), 29175dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CAR), 29185dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CDR), 29195dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CAR_STORE), 29205dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CDR_STORE), 29215dfecf96Smrg JUMP_ADDRESS(XBC_LOADCON_SET), 29225dfecf96Smrg JUMP_ADDRESS(XBC_LOADSYM), 29235dfecf96Smrg JUMP_ADDRESS(XBC_LOADSYM_LET), 29245dfecf96Smrg JUMP_ADDRESS(XBC_LOADSYM_LETX), 29255dfecf96Smrg JUMP_ADDRESS(XBC_LOADSYM_PUSH), 29265dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_SET), 29275dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CAR_SET), 29285dfecf96Smrg JUMP_ADDRESS(XBC_LOAD_CDR_SET), 29295dfecf96Smrg JUMP_ADDRESS(XBC_SET), 29305dfecf96Smrg JUMP_ADDRESS(XBC_SETSYM), 29315dfecf96Smrg JUMP_ADDRESS(XBC_SET_NIL), 29325dfecf96Smrg JUMP_ADDRESS(XBC_CALL), 29335dfecf96Smrg JUMP_ADDRESS(XBC_CALL_SET), 29345dfecf96Smrg JUMP_ADDRESS(XBC_BYTECALL), 29355dfecf96Smrg JUMP_ADDRESS(XBC_FUNCALL), 29365dfecf96Smrg JUMP_ADDRESS(XBC_LETREC), 29375dfecf96Smrg JUMP_ADDRESS(XBC_BCONS), 29385dfecf96Smrg JUMP_ADDRESS(XBC_BCONS1), 29395dfecf96Smrg JUMP_ADDRESS(XBC_BCONS2), 29405dfecf96Smrg JUMP_ADDRESS(XBC_BCONS3), 29415dfecf96Smrg JUMP_ADDRESS(XBC_BCONS4), 29425dfecf96Smrg JUMP_ADDRESS(XBC_BCONS5), 29435dfecf96Smrg JUMP_ADDRESS(XBC_BCONS6), 29445dfecf96Smrg JUMP_ADDRESS(XBC_BCONS7), 29455dfecf96Smrg JUMP_ADDRESS(XBC_CCONS), 29465dfecf96Smrg JUMP_ADDRESS(XBC_CSTAR), 29475dfecf96Smrg JUMP_ADDRESS(XBC_CFINI), 29485dfecf96Smrg JUMP_ADDRESS(XBC_LSTAR), 29495dfecf96Smrg JUMP_ADDRESS(XBC_LCONS), 29505dfecf96Smrg JUMP_ADDRESS(XBC_LFINI), 29515dfecf96Smrg JUMP_ADDRESS(XBC_JUMP), 29525dfecf96Smrg JUMP_ADDRESS(XBC_JUMPT), 29535dfecf96Smrg JUMP_ADDRESS(XBC_JUMPNIL), 29545dfecf96Smrg JUMP_ADDRESS(XBC_STRUCT), 29555dfecf96Smrg JUMP_ADDRESS(XBC_STRUCTP), 29565dfecf96Smrg JUMP_ADDRESS(XBC_RETURN) 29575dfecf96Smrg }; 29585dfecf96Smrg static const void *predicate_opcode_labels[] = { 29595dfecf96Smrg JUMP_ADDRESS(XBP_CONSP), 29605dfecf96Smrg JUMP_ADDRESS(XBP_LISTP), 29615dfecf96Smrg JUMP_ADDRESS(XBP_NUMBERP) 29625dfecf96Smrg }; 29635dfecf96Smrg#endif 29645dfecf96Smrg 29655dfecf96Smrg reg0 = NIL; 29665dfecf96Smrg 29675dfecf96Smrg bytecode = stream; 29685dfecf96Smrg pbase = lisp__data.protect.length; 29695dfecf96Smrg 29705dfecf96Smrg /* stack */ 29715dfecf96Smrg offset = *(short*)stream; 29725dfecf96Smrg stream += sizeof(short); 29735dfecf96Smrg if (lisp__data.env.length + offset > lisp__data.env.space) { 29745dfecf96Smrg do 29755dfecf96Smrg LispMoreEnvironment(); 29765dfecf96Smrg while (lisp__data.env.length + offset >= lisp__data.env.space); 29775dfecf96Smrg } 29785dfecf96Smrg /* builtin stack */ 29795dfecf96Smrg offset = *(short*)stream; 29805dfecf96Smrg stream += sizeof(short); 29815dfecf96Smrg if (lisp__data.stack.length + offset >= lisp__data.stack.space) { 29825dfecf96Smrg do 29835dfecf96Smrg LispMoreStack(); 29845dfecf96Smrg while (lisp__data.stack.length + offset >= lisp__data.stack.space); 29855dfecf96Smrg } 29865dfecf96Smrg /* protect stack */ 29875dfecf96Smrg phead = *(short*)stream; 29885dfecf96Smrg stream += sizeof(short); 29895dfecf96Smrg if (lisp__data.protect.length + phead > lisp__data.protect.space) { 29905dfecf96Smrg do 29915dfecf96Smrg LispMoreProtects(); 29925dfecf96Smrg while (lisp__data.protect.length + phead >= lisp__data.protect.space); 29935dfecf96Smrg } 29945dfecf96Smrg 29955dfecf96Smrg num_constants = *(short*)stream; 29965dfecf96Smrg stream += sizeof(short); 29975dfecf96Smrg num_symbols = *(short*)stream; 29985dfecf96Smrg stream += sizeof(short); 29995dfecf96Smrg num_builtins = *(short*)stream; 30005dfecf96Smrg stream += sizeof(short); 30015dfecf96Smrg num_codes = *(short*)stream; 30025dfecf96Smrg stream += sizeof(short); 30035dfecf96Smrg 30045dfecf96Smrg constants = (LispObj**)stream; 30055dfecf96Smrg stream += num_constants * sizeof(LispObj*); 30065dfecf96Smrg symbols = (LispAtom**)stream; 30075dfecf96Smrg stream += num_symbols * sizeof(LispAtom*); 30085dfecf96Smrg builtins = (LispBuiltin**)stream; 30095dfecf96Smrg stream += num_builtins * sizeof(LispBuiltin*); 30105dfecf96Smrg codes = (unsigned char**)stream; 30115dfecf96Smrg stream += num_codes * (sizeof(unsigned char*) + sizeof(LispObj*)); 30125dfecf96Smrg 30135dfecf96Smrg for (; phead > 0; phead--) 30145dfecf96Smrg lisp__data.protect.objects[lisp__data.protect.length++] = NIL; 30155dfecf96Smrg phead = pbase; 30165dfecf96Smrg 30175dfecf96Smrg#ifdef ALLOW_GOTO_ADDRESS 30185dfecf96Smrg#define OPCODE_LABEL(label) label 30195dfecf96Smrg#define NEXT_OPCODE() goto *opcode_labels[*stream++] 30205dfecf96Smrg#define GOTO_PREDICATE() goto *predicate_opcode_labels[*stream++] 30215dfecf96Smrg#else 30225dfecf96Smrg#define OPCODE_LABEL(label) case label 30235dfecf96Smrg#define NEXT_OPCODE() goto next_opcode 30245dfecf96Smrg#define GOTO_PREDICATE() goto predicate_label 30255dfecf96Smrg for (;;) { 30265dfecf96Smrgnext_opcode: 30275dfecf96Smrg switch (*stream++) { 30285dfecf96Smrg#endif /* ALLOW_GOTO_ADDRESS */ 30295dfecf96Smrg 30305dfecf96SmrgOPCODE_LABEL(XBC_NOOP): 30315dfecf96Smrg NEXT_OPCODE(); 30325dfecf96Smrg 30335dfecf96SmrgOPCODE_LABEL(XBC_PRED): 30345dfecf96Smrg GOTO_PREDICATE(); 30355dfecf96Smrg 30365dfecf96SmrgOPCODE_LABEL(XBC_INV): 30375dfecf96Smrg reg0 = reg0 == NIL ? T : NIL; 30385dfecf96Smrg NEXT_OPCODE(); 30395dfecf96Smrg 30405dfecf96SmrgOPCODE_LABEL(XBC_NIL): 30415dfecf96Smrg reg0 = NIL; 30425dfecf96Smrg NEXT_OPCODE(); 30435dfecf96Smrg 30445dfecf96SmrgOPCODE_LABEL(XBC_T): 30455dfecf96Smrg reg0 = T; 30465dfecf96Smrg NEXT_OPCODE(); 30475dfecf96Smrg 30485dfecf96SmrgOPCODE_LABEL(XBC_CAR): 30495dfecf96Smrgcar: 30505dfecf96Smrg if (reg0 != NIL) { 30515dfecf96Smrg if (!CONSP(reg0)) 30525dfecf96Smrg LispDestroy("CAR: %s is not a list", STROBJ(reg0)); 30535dfecf96Smrg reg0 = CAR(reg0); 30545dfecf96Smrg } 30555dfecf96Smrg NEXT_OPCODE(); 30565dfecf96Smrg 30575dfecf96SmrgOPCODE_LABEL(XBC_CDR): 30585dfecf96Smrgcdr: 30595dfecf96Smrg if (reg0 != NIL) { 30605dfecf96Smrg if (!CONSP(reg0)) 30615dfecf96Smrg LispDestroy("CDR: %s is not a list", STROBJ(reg0)); 30625dfecf96Smrg reg0 = CDR(reg0); 30635dfecf96Smrg } 30645dfecf96Smrg NEXT_OPCODE(); 30655dfecf96Smrg 30665dfecf96SmrgOPCODE_LABEL(XBC_RPLACA): 30675dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 30685dfecf96Smrg if (!CONSP(reg1)) 30695dfecf96Smrg LispDestroy("RPLACA: %s is not a cons", STROBJ(reg1)); 30705dfecf96Smrg RPLACA(reg1, reg0); 30715dfecf96Smrg reg0 = reg1; 30725dfecf96Smrg NEXT_OPCODE(); 30735dfecf96Smrg 30745dfecf96SmrgOPCODE_LABEL(XBC_RPLACD): 30755dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 30765dfecf96Smrg if (!CONSP(reg1)) 30775dfecf96Smrg LispDestroy("RPLACD: %s is not a cons", STROBJ(reg1)); 30785dfecf96Smrg RPLACD(reg1, reg0); 30795dfecf96Smrg reg0 = reg1; 30805dfecf96Smrg NEXT_OPCODE(); 30815dfecf96Smrg 30825dfecf96SmrgOPCODE_LABEL(XBC_BCONS): 30835dfecf96Smrg CAR(cons) = reg0; 30845dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = cons; 30855dfecf96Smrg NEXT_OPCODE(); 30865dfecf96Smrg 30875dfecf96SmrgOPCODE_LABEL(XBC_BCONS1): 30885dfecf96Smrg offset = lisp__data.stack.length - 1; 30895dfecf96Smrg CAR(cons) = reg0; 30905dfecf96Smrg CAR(cons1) = lisp__data.stack.values[offset]; 30915dfecf96Smrg lisp__data.stack.values[offset] = cons1; 30925dfecf96Smrg NEXT_OPCODE(); 30935dfecf96Smrg 30945dfecf96SmrgOPCODE_LABEL(XBC_BCONS2): 30955dfecf96Smrg offset = lisp__data.stack.length; 30965dfecf96Smrg CAR(cons) = reg0; 30975dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 30985dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 30995dfecf96Smrg lisp__data.stack.values[offset] = cons2; 31005dfecf96Smrg lisp__data.stack.length = offset + 1; 31015dfecf96Smrg NEXT_OPCODE(); 31025dfecf96Smrg 31035dfecf96SmrgOPCODE_LABEL(XBC_BCONS3): 31045dfecf96Smrg offset = lisp__data.stack.length; 31055dfecf96Smrg CAR(cons) = reg0; 31065dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 31075dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 31085dfecf96Smrg CAR(cons3) = lisp__data.stack.values[--offset]; 31095dfecf96Smrg lisp__data.stack.values[offset] = cons3; 31105dfecf96Smrg lisp__data.stack.length = offset + 1; 31115dfecf96Smrg NEXT_OPCODE(); 31125dfecf96Smrg 31135dfecf96SmrgOPCODE_LABEL(XBC_BCONS4): 31145dfecf96Smrg offset = lisp__data.stack.length; 31155dfecf96Smrg CAR(cons) = reg0; 31165dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 31175dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 31185dfecf96Smrg CAR(cons3) = lisp__data.stack.values[--offset]; 31195dfecf96Smrg CAR(cons4) = lisp__data.stack.values[--offset]; 31205dfecf96Smrg lisp__data.stack.values[offset] = cons4; 31215dfecf96Smrg lisp__data.stack.length = offset + 1; 31225dfecf96Smrg NEXT_OPCODE(); 31235dfecf96Smrg 31245dfecf96SmrgOPCODE_LABEL(XBC_BCONS5): 31255dfecf96Smrg offset = lisp__data.stack.length; 31265dfecf96Smrg CAR(cons) = reg0; 31275dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 31285dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 31295dfecf96Smrg CAR(cons3) = lisp__data.stack.values[--offset]; 31305dfecf96Smrg CAR(cons4) = lisp__data.stack.values[--offset]; 31315dfecf96Smrg CAR(cons5) = lisp__data.stack.values[--offset]; 31325dfecf96Smrg lisp__data.stack.values[offset] = cons5; 31335dfecf96Smrg lisp__data.stack.length = offset + 1; 31345dfecf96Smrg NEXT_OPCODE(); 31355dfecf96Smrg 31365dfecf96SmrgOPCODE_LABEL(XBC_BCONS6): 31375dfecf96Smrg offset = lisp__data.stack.length; 31385dfecf96Smrg CAR(cons) = reg0; 31395dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 31405dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 31415dfecf96Smrg CAR(cons3) = lisp__data.stack.values[--offset]; 31425dfecf96Smrg CAR(cons4) = lisp__data.stack.values[--offset]; 31435dfecf96Smrg CAR(cons5) = lisp__data.stack.values[--offset]; 31445dfecf96Smrg CAR(cons6) = lisp__data.stack.values[--offset]; 31455dfecf96Smrg lisp__data.stack.values[offset] = cons6; 31465dfecf96Smrg lisp__data.stack.length = offset + 1; 31475dfecf96Smrg NEXT_OPCODE(); 31485dfecf96Smrg 31495dfecf96SmrgOPCODE_LABEL(XBC_BCONS7): 31505dfecf96Smrg offset = lisp__data.stack.length; 31515dfecf96Smrg CAR(cons) = reg0; 31525dfecf96Smrg CAR(cons1) = lisp__data.stack.values[--offset]; 31535dfecf96Smrg CAR(cons2) = lisp__data.stack.values[--offset]; 31545dfecf96Smrg CAR(cons3) = lisp__data.stack.values[--offset]; 31555dfecf96Smrg CAR(cons4) = lisp__data.stack.values[--offset]; 31565dfecf96Smrg CAR(cons5) = lisp__data.stack.values[--offset]; 31575dfecf96Smrg CAR(cons6) = lisp__data.stack.values[--offset]; 31585dfecf96Smrg CAR(cons7) = lisp__data.stack.values[--offset]; 31595dfecf96Smrg lisp__data.stack.values[offset] = cons7; 31605dfecf96Smrg lisp__data.stack.length = offset + 1; 31615dfecf96Smrg NEXT_OPCODE(); 31625dfecf96Smrg 31635dfecf96SmrgOPCODE_LABEL(XBC_EQ): 31645dfecf96Smrg reg0 = reg0 == lisp__data.stack.values[--lisp__data.stack.length] ? T : NIL; 31655dfecf96Smrg NEXT_OPCODE(); 31665dfecf96Smrg 31675dfecf96SmrgOPCODE_LABEL(XBC_EQL): 31685dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 31695dfecf96Smrg reg0 = XEQL(reg1, reg0); 31705dfecf96Smrg NEXT_OPCODE(); 31715dfecf96Smrg 31725dfecf96SmrgOPCODE_LABEL(XBC_EQUAL): 31735dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 31745dfecf96Smrg reg0 = XEQUAL(reg1, reg0); 31755dfecf96Smrg NEXT_OPCODE(); 31765dfecf96Smrg 31775dfecf96SmrgOPCODE_LABEL(XBC_EQUALP): 31785dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 31795dfecf96Smrg reg0 = XEQUALP(reg1, reg0); 31805dfecf96Smrg NEXT_OPCODE(); 31815dfecf96Smrg 31825dfecf96SmrgOPCODE_LABEL(XBC_LENGTH): 31835dfecf96Smrg reg0 = FIXNUM(LispLength(reg0)); 31845dfecf96Smrg NEXT_OPCODE(); 31855dfecf96Smrg 31865dfecf96SmrgOPCODE_LABEL(XBC_LAST): 31875dfecf96Smrg { 31885dfecf96Smrg long length; 31895dfecf96Smrg 31905dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 31915dfecf96Smrg if (CONSP(reg1)) { 31925dfecf96Smrg if (reg0 != NIL) { 31935dfecf96Smrg if (!FIXNUMP(reg0) || (fixnum = FIXNUM_VALUE(reg0)) < 0) 31945dfecf96Smrg LispDestroy("LAST: %s is not a positive fixnum", 31955dfecf96Smrg STROBJ(reg0)); 31965dfecf96Smrg } 31975dfecf96Smrg else 31985dfecf96Smrg fixnum = 1; 31995dfecf96Smrg reg0 = reg1; 32005dfecf96Smrg for (reg0 = reg1, length = 0; 32015dfecf96Smrg CONSP(reg0); 32025dfecf96Smrg reg0 = CDR(reg0), length++) 32035dfecf96Smrg ; 32045dfecf96Smrg for (length -= fixnum, reg0 = reg1; length > 0; length--) 32055dfecf96Smrg reg0 = CDR(reg0); 32065dfecf96Smrg } 32075dfecf96Smrg else 32085dfecf96Smrg reg0 = reg1; 32095dfecf96Smrg } NEXT_OPCODE(); 32105dfecf96Smrg 32115dfecf96SmrgOPCODE_LABEL(XBC_NTHCDR): 32125dfecf96Smrg reg1 = lisp__data.stack.values[--lisp__data.stack.length]; 32135dfecf96Smrg if (!FIXNUMP(reg1) || (fixnum = FIXNUM_VALUE(reg1)) < 0) 32145dfecf96Smrg LispDestroy("NTHCDR: %s is not a positive fixnum", 32155dfecf96Smrg STROBJ(reg1)); 32165dfecf96Smrg if (reg0 != NIL) { 32175dfecf96Smrg if (!CONSP(reg0)) 32185dfecf96Smrg LispDestroy("NTHCDR: %s is not a list", STROBJ(reg0)); 32195dfecf96Smrg for (; fixnum > 0; fixnum--) { 32205dfecf96Smrg if (!CONSP(reg0)) 32215dfecf96Smrg break; 32225dfecf96Smrg reg0 = CDR(reg0); 32235dfecf96Smrg } 32245dfecf96Smrg } 32255dfecf96Smrg NEXT_OPCODE(); 32265dfecf96Smrg 32275dfecf96Smrg /* Push to builtin stack */ 32285dfecf96SmrgOPCODE_LABEL(XBC_CAR_PUSH): 32295dfecf96Smrg if (reg0 != NIL) { 32305dfecf96Smrg if (!CONSP(reg0)) 32315dfecf96Smrg LispDestroy("CAR: %s is not a list", STROBJ(reg0)); 32325dfecf96Smrg reg0 = CAR(reg0); 32335dfecf96Smrg } 32345dfecf96Smrg goto push_builtin; 32355dfecf96Smrg 32365dfecf96SmrgOPCODE_LABEL(XBC_CDR_PUSH): 32375dfecf96Smrg if (reg0 != NIL) { 32385dfecf96Smrg if (!CONSP(reg0)) 32395dfecf96Smrg LispDestroy("CDR: %s is not a list", STROBJ(reg0)); 32405dfecf96Smrg reg0 = CDR(reg0); 32415dfecf96Smrg } 32425dfecf96Smrg /*FALLTROUGH*/ 32435dfecf96Smrg 32445dfecf96SmrgOPCODE_LABEL(XBC_PUSH): 32455dfecf96Smrgpush_builtin: 32465dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = reg0; 32475dfecf96Smrg NEXT_OPCODE(); 32485dfecf96Smrg 32495dfecf96SmrgOPCODE_LABEL(XBC_PUSH_NIL): 32505dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = NIL; 32515dfecf96Smrg NEXT_OPCODE(); 32525dfecf96Smrg 32535dfecf96SmrgOPCODE_LABEL(XBC_PUSH_UNSPEC): 32545dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = UNSPEC; 32555dfecf96Smrg NEXT_OPCODE(); 32565dfecf96Smrg 32575dfecf96SmrgOPCODE_LABEL(XBC_PUSH_T): 32585dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = T; 32595dfecf96Smrg NEXT_OPCODE(); 32605dfecf96Smrg 32615dfecf96SmrgOPCODE_LABEL(XBC_PUSH_NIL_N): 32625dfecf96Smrg for (offset = *stream++; offset > 0; offset--) 32635dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = NIL; 32645dfecf96Smrg NEXT_OPCODE(); 32655dfecf96Smrg 32665dfecf96SmrgOPCODE_LABEL(XBC_PUSH_UNSPEC_N): 32675dfecf96Smrg for (offset = *stream++; offset > 0; offset--) 32685dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = UNSPEC; 32695dfecf96Smrg NEXT_OPCODE(); 32705dfecf96Smrg 32715dfecf96SmrgOPCODE_LABEL(XBC_LET): 32725dfecf96Smrglet_argument: 32735dfecf96Smrg /* The global object value is not changed, so it does not 32745dfecf96Smrg * matter if it is a constant symbol. An error would be 32755dfecf96Smrg * generated if it was declared as constant at the time of 32765dfecf96Smrg * bytecode generation. Check can be done looking at the 32775dfecf96Smrg * atom->constant field. */ 32785dfecf96Smrg atom = symbols[*stream++]; 32795dfecf96Smrg atom->offset = lisp__data.env.length; 3280f14f4646Smrg lisp__data.env.names[lisp__data.env.length] = atom->key; 32815dfecf96Smrg lisp__data.env.values[lisp__data.env.length++] = reg0; 32825dfecf96Smrg NEXT_OPCODE(); 32835dfecf96Smrg 32845dfecf96SmrgOPCODE_LABEL(XBC_LETX): 32855dfecf96Smrgletx_argument: 32865dfecf96Smrg atom = symbols[*stream++]; 32875dfecf96Smrg atom->offset = lisp__data.env.length; 3288f14f4646Smrg lisp__data.env.names[lisp__data.env.length] = atom->key; 32895dfecf96Smrg lisp__data.env.values[lisp__data.env.length++] = reg0; 32905dfecf96Smrg lisp__data.env.head++; 32915dfecf96Smrg NEXT_OPCODE(); 32925dfecf96Smrg 32935dfecf96SmrgOPCODE_LABEL(XBC_LET_NIL): 32945dfecf96Smrg atom = symbols[*stream++]; 32955dfecf96Smrg atom->offset = lisp__data.env.length; 3296f14f4646Smrg lisp__data.env.names[lisp__data.env.length] = atom->key; 32975dfecf96Smrg lisp__data.env.values[lisp__data.env.length++] = NIL; 32985dfecf96Smrg NEXT_OPCODE(); 32995dfecf96Smrg 33005dfecf96SmrgOPCODE_LABEL(XBC_LETX_NIL): 33015dfecf96Smrg atom = symbols[*stream++]; 33025dfecf96Smrg atom->offset = lisp__data.env.length; 3303f14f4646Smrg lisp__data.env.names[lisp__data.env.length] = atom->key; 33045dfecf96Smrg lisp__data.env.values[lisp__data.env.length++] = NIL; 33055dfecf96Smrg lisp__data.env.head++; 33065dfecf96Smrg NEXT_OPCODE(); 33075dfecf96Smrg 33085dfecf96Smrg /* Bind locally added variables to a block */ 33095dfecf96SmrgOPCODE_LABEL(XBC_LETBIND): 33105dfecf96Smrg offset = *stream++; 33115dfecf96Smrg lisp__data.env.head += offset; 33125dfecf96Smrg NEXT_OPCODE(); 33135dfecf96Smrg 33145dfecf96Smrg /* Unbind locally added variables to a block */ 33155dfecf96SmrgOPCODE_LABEL(XBC_UNLET): 33165dfecf96Smrg offset = *stream++; 33175dfecf96Smrg lisp__data.env.head -= offset; 33185dfecf96Smrg lisp__data.env.length -= offset; 33195dfecf96Smrg NEXT_OPCODE(); 33205dfecf96Smrg 33215dfecf96Smrg /* Load value from stack */ 33225dfecf96SmrgOPCODE_LABEL(XBC_LOAD): 33235dfecf96Smrg offset = *stream++; 33245dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33255dfecf96Smrg NEXT_OPCODE(); 33265dfecf96Smrg 33275dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CAR): 33285dfecf96Smrg offset = *stream++; 33295dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33305dfecf96Smrg goto car; 33315dfecf96Smrg 33325dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CDR): 33335dfecf96Smrg offset = *stream++; 33345dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33355dfecf96Smrg goto cdr; 33365dfecf96Smrg 33375dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CAR_STORE): 33385dfecf96Smrg offset = *stream++; 33395dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33405dfecf96Smrg if (reg0 != NIL) { 33415dfecf96Smrg if (!CONSP(reg0)) 33425dfecf96Smrg LispDestroy("CAR: %s is not a list", STROBJ(reg0)); 33435dfecf96Smrg reg0 = CAR(reg0); 33445dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = reg0; 33455dfecf96Smrg } 33465dfecf96Smrg NEXT_OPCODE(); 33475dfecf96Smrg 33485dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CDR_STORE): 33495dfecf96Smrg offset = *stream++; 33505dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33515dfecf96Smrg if (reg0 != NIL) { 33525dfecf96Smrg if (!CONSP(reg0)) 33535dfecf96Smrg LispDestroy("CDR: %s is not a list", STROBJ(reg0)); 33545dfecf96Smrg reg0 = CDR(reg0); 33555dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = reg0; 33565dfecf96Smrg } 33575dfecf96Smrg NEXT_OPCODE(); 33585dfecf96Smrg 33595dfecf96SmrgOPCODE_LABEL(XBC_LOAD_LET): 33605dfecf96Smrg offset = *stream++; 33615dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33625dfecf96Smrg goto let_argument; 33635dfecf96Smrg 33645dfecf96SmrgOPCODE_LABEL(XBC_LOAD_LETX): 33655dfecf96Smrg offset = *stream++; 33665dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33675dfecf96Smrg goto letx_argument; 33685dfecf96Smrg 33695dfecf96SmrgOPCODE_LABEL(XBC_LOAD_PUSH): 33705dfecf96Smrg offset = *stream++; 33715dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 33725dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = reg0; 33735dfecf96Smrg NEXT_OPCODE(); 33745dfecf96Smrg 33755dfecf96Smrg /* Load pointer to constant */ 33765dfecf96SmrgOPCODE_LABEL(XBC_LOADCON): 33775dfecf96Smrg reg0 = constants[*stream++]; 33785dfecf96Smrg NEXT_OPCODE(); 33795dfecf96Smrg 33805dfecf96SmrgOPCODE_LABEL(XBC_LOADCON_LET): 33815dfecf96Smrg reg0 = constants[*stream++]; 33825dfecf96Smrg goto let_argument; 33835dfecf96Smrg 33845dfecf96SmrgOPCODE_LABEL(XBC_LOADCON_LETX): 33855dfecf96Smrg reg0 = constants[*stream++]; 33865dfecf96Smrg goto letx_argument; 33875dfecf96Smrg 33885dfecf96SmrgOPCODE_LABEL(XBC_LOADCON_PUSH): 33895dfecf96Smrg reg0 = constants[*stream++]; 33905dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = reg0; 33915dfecf96Smrg NEXT_OPCODE(); 33925dfecf96Smrg 33935dfecf96SmrgOPCODE_LABEL(XBC_LOADCON_SET): 33945dfecf96Smrg reg0 = constants[*stream++]; 33955dfecf96Smrg offset = *stream++; 33965dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = reg0; 33975dfecf96Smrg NEXT_OPCODE(); 33985dfecf96Smrg 33995dfecf96Smrg /* Change value of local variable */ 34005dfecf96SmrgOPCODE_LABEL(XBC_CAR_SET): 34015dfecf96Smrgcar_set: 34025dfecf96Smrg if (reg0 != NIL) { 34035dfecf96Smrg if (!CONSP(reg0)) 34045dfecf96Smrg LispDestroy("CAR: %s is not a list", STROBJ(reg0)); 34055dfecf96Smrg reg0 = CAR(reg0); 34065dfecf96Smrg } 34075dfecf96Smrg goto set_local_variable; 34085dfecf96Smrg 34095dfecf96SmrgOPCODE_LABEL(XBC_CDR_SET): 34105dfecf96Smrgcdr_set: 34115dfecf96Smrg if (reg0 != NIL) { 34125dfecf96Smrg if (!CONSP(reg0)) 34135dfecf96Smrg LispDestroy("CDR: %s is not a list", STROBJ(reg0)); 34145dfecf96Smrg reg0 = CDR(reg0); 34155dfecf96Smrg } 34165dfecf96Smrg goto set_local_variable; 34175dfecf96Smrg 34185dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CAR_SET): 34195dfecf96Smrg offset = *stream++; 34205dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 34215dfecf96Smrg goto car_set; 34225dfecf96Smrg 34235dfecf96SmrgOPCODE_LABEL(XBC_LOAD_CDR_SET): 34245dfecf96Smrg offset = *stream++; 34255dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 34265dfecf96Smrg goto cdr_set; 34275dfecf96Smrg 34285dfecf96SmrgOPCODE_LABEL(XBC_LOAD_SET): 34295dfecf96Smrg offset = *stream++; 34305dfecf96Smrg reg0 = lisp__data.env.values[lisp__data.env.lex + offset]; 34315dfecf96Smrg /*FALLTROUGH*/ 34325dfecf96Smrg 34335dfecf96SmrgOPCODE_LABEL(XBC_SET): 34345dfecf96Smrgset_local_variable: 34355dfecf96Smrg offset = *stream++; 34365dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = reg0; 34375dfecf96Smrg NEXT_OPCODE(); 34385dfecf96Smrg 34395dfecf96SmrgOPCODE_LABEL(XBC_SET_NIL): 34405dfecf96Smrg offset = *stream++; 34415dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = NIL; 34425dfecf96Smrg NEXT_OPCODE(); 34435dfecf96Smrg 34445dfecf96Smrg /* Change value of a global/special variable */ 34455dfecf96SmrgOPCODE_LABEL(XBC_SETSYM): 34465dfecf96Smrg atom = symbols[*stream++]; 34475dfecf96Smrg if (atom->dyn) { 34485dfecf96Smrg /* atom->dyn and atom->constant are exclusive, no 34495dfecf96Smrg * need to check if variable declared as constant. */ 34505dfecf96Smrg if (atom->offset < lisp__data.env.head && 3451f14f4646Smrg lisp__data.env.names[atom->offset] == atom->key) 34525dfecf96Smrg lisp__data.env.values[atom->offset] = reg0; 34535dfecf96Smrg else { 34545dfecf96Smrg if (atom->watch) 34555dfecf96Smrg LispSetAtomObjectProperty(atom, reg0); 34565dfecf96Smrg else 34575dfecf96Smrg SETVALUE(atom, reg0); 34585dfecf96Smrg } 34595dfecf96Smrg } 34605dfecf96Smrg else if (atom->a_object) { 34615dfecf96Smrg if (atom->constant) 34625dfecf96Smrg LispDestroy("EVAL: %s is a constant", 34635dfecf96Smrg STROBJ(atom->object)); 34645dfecf96Smrg else if (atom->watch) 34655dfecf96Smrg LispSetAtomObjectProperty(atom, reg0); 34665dfecf96Smrg else 34675dfecf96Smrg SETVALUE(atom, reg0); 34685dfecf96Smrg } 34695dfecf96Smrg else { 34705dfecf96Smrg /* Create new global variable */ 34715dfecf96Smrg LispPackage *pack; 34725dfecf96Smrg 34735dfecf96Smrg LispWarning("the variable %s was not declared", 3474f14f4646Smrg atom->key->value); 34755dfecf96Smrg LispSetAtomObjectProperty(atom, reg0); 34765dfecf96Smrg pack = atom->package->data.package.package; 34775dfecf96Smrg if (pack->glb.length >= pack->glb.space) 34785dfecf96Smrg LispMoreGlobals(pack); 34795dfecf96Smrg pack->glb.pairs[pack->glb.length++] = atom->object; 34805dfecf96Smrg } 34815dfecf96Smrg NEXT_OPCODE(); 34825dfecf96Smrg 34835dfecf96Smrg/* Resolve symbol value at runtime */ 34845dfecf96Smrg#define LOAD_SYMBOL_VALUE() \ 34855dfecf96Smrg atom = symbols[*stream++]; \ 34865dfecf96Smrg if (atom->dyn) { \ 34875dfecf96Smrg if (atom->offset < lisp__data.env.head && \ 3488f14f4646Smrg lisp__data.env.names[atom->offset] == atom->key) \ 34895dfecf96Smrg reg0 = lisp__data.env.values[atom->offset]; \ 34905dfecf96Smrg else { \ 34915dfecf96Smrg reg0 = atom->property->value; \ 34925dfecf96Smrg if (reg0 == UNBOUND) \ 34935dfecf96Smrg LispDestroy("EVAL: the symbol %s is unbound", \ 34945dfecf96Smrg STROBJ(atom->object)); \ 34955dfecf96Smrg } \ 34965dfecf96Smrg } \ 34975dfecf96Smrg else { \ 34985dfecf96Smrg if (atom->a_object) \ 34995dfecf96Smrg reg0 = atom->property->value; \ 35005dfecf96Smrg else \ 35015dfecf96Smrg LispDestroy("EVAL: the symbol %s is unbound", \ 35025dfecf96Smrg STROBJ(atom->object)); \ 35035dfecf96Smrg } 35045dfecf96Smrg 35055dfecf96SmrgOPCODE_LABEL(XBC_LOADSYM): 35065dfecf96Smrg LOAD_SYMBOL_VALUE(); 35075dfecf96Smrg NEXT_OPCODE(); 35085dfecf96Smrg 35095dfecf96SmrgOPCODE_LABEL(XBC_LOADSYM_LET): 35105dfecf96Smrg LOAD_SYMBOL_VALUE(); 35115dfecf96Smrg goto let_argument; 35125dfecf96Smrg 35135dfecf96SmrgOPCODE_LABEL(XBC_LOADSYM_LETX): 35145dfecf96Smrg LOAD_SYMBOL_VALUE(); 35155dfecf96Smrg goto letx_argument; 35165dfecf96Smrg 35175dfecf96SmrgOPCODE_LABEL(XBC_LOADSYM_PUSH): 35185dfecf96Smrg LOAD_SYMBOL_VALUE(); 35195dfecf96Smrg lisp__data.stack.values[lisp__data.stack.length++] = reg0; 35205dfecf96Smrg NEXT_OPCODE(); 35215dfecf96Smrg 35225dfecf96Smrg /* Builtin function */ 35235dfecf96SmrgOPCODE_LABEL(XBC_CALL): 35245dfecf96Smrg offset = *stream++; 35255dfecf96Smrg lisp__data.stack.base = lisp__data.stack.length - offset; 35265dfecf96Smrg builtin = builtins[*stream++]; 35275dfecf96Smrg if (builtin->multiple_values) { 35285dfecf96Smrg RETURN_COUNT = 0; 35295dfecf96Smrg reg0 = builtin->function(builtin); 35305dfecf96Smrg } 35315dfecf96Smrg else { 35325dfecf96Smrg reg0 = builtin->function(builtin); 35335dfecf96Smrg RETURN_COUNT = 0; 35345dfecf96Smrg } 35355dfecf96Smrg lisp__data.stack.length -= offset; 35365dfecf96Smrg NEXT_OPCODE(); 35375dfecf96Smrg 35385dfecf96SmrgOPCODE_LABEL(XBC_CALL_SET): 35395dfecf96Smrg offset = *stream++; 35405dfecf96Smrg lisp__data.stack.base = lisp__data.stack.length - offset; 35415dfecf96Smrg builtin = builtins[*stream++]; 35425dfecf96Smrg if (builtin->multiple_values) { 35435dfecf96Smrg RETURN_COUNT = 0; 35445dfecf96Smrg reg0 = builtin->function(builtin); 35455dfecf96Smrg } 35465dfecf96Smrg else { 35475dfecf96Smrg reg0 = builtin->function(builtin); 35485dfecf96Smrg RETURN_COUNT = 0; 35495dfecf96Smrg } 35505dfecf96Smrg lisp__data.stack.length -= offset; 35515dfecf96Smrg offset = *stream++; 35525dfecf96Smrg lisp__data.env.values[lisp__data.env.lex + offset] = reg0; 35535dfecf96Smrg NEXT_OPCODE(); 35545dfecf96Smrg 35555dfecf96Smrg /* Bytecode call */ 35565dfecf96SmrgOPCODE_LABEL(XBC_BYTECALL): 35575dfecf96Smrg lex = lisp__data.env.lex; 35585dfecf96Smrg offset = *stream++; 35595dfecf96Smrg lisp__data.env.head = lisp__data.env.length; 35605dfecf96Smrg len = lisp__data.env.lex = lisp__data.env.length - offset; 35615dfecf96Smrg reg0 = ExecuteBytecode(codes[*stream++]); 35625dfecf96Smrg lisp__data.env.length = lisp__data.env.head = len; 35635dfecf96Smrg lisp__data.env.lex = lex; 35645dfecf96Smrg NEXT_OPCODE(); 35655dfecf96Smrg 35665dfecf96Smrg /* Unimplemented function/macro call */ 35675dfecf96SmrgOPCODE_LABEL(XBC_FUNCALL): 35685dfecf96Smrg lambda = constants[*stream++]; 35695dfecf96Smrg arguments = constants[*stream++]; 35705dfecf96Smrg reg0 = LispFuncall(lambda, arguments, 1); 35715dfecf96Smrg NEXT_OPCODE(); 35725dfecf96Smrg 35735dfecf96SmrgOPCODE_LABEL(XBC_JUMP): 35745dfecf96Smrg stream += *(signed short*)stream; 35755dfecf96Smrg NEXT_OPCODE(); 35765dfecf96Smrg 35775dfecf96SmrgOPCODE_LABEL(XBC_JUMPT): 35785dfecf96Smrg if (reg0 != NIL) 35795dfecf96Smrg stream += *(signed short*)stream; 35805dfecf96Smrg else 35815dfecf96Smrg /* skip jump relative offset */ 35825dfecf96Smrg stream += sizeof(signed short); 35835dfecf96Smrg NEXT_OPCODE(); 35845dfecf96Smrg 35855dfecf96SmrgOPCODE_LABEL(XBC_JUMPNIL): 35865dfecf96Smrg if (reg0 == NIL) 35875dfecf96Smrg stream += *(signed short*)stream; 35885dfecf96Smrg else 35895dfecf96Smrg /* skip jump relative offset */ 35905dfecf96Smrg stream += sizeof(signed short); 35915dfecf96Smrg NEXT_OPCODE(); 35925dfecf96Smrg 35935dfecf96Smrg /* Build CONS of two constant arguments */ 35945dfecf96SmrgOPCODE_LABEL(XBC_CCONS): 35955dfecf96Smrg reg0 = constants[*stream++]; 35965dfecf96Smrg reg1 = constants[*stream++]; 35975dfecf96Smrg reg0 = CONS(reg0, reg1); 35985dfecf96Smrg NEXT_OPCODE(); 35995dfecf96Smrg 36005dfecf96Smrg /* Start CONS */ 36015dfecf96SmrgOPCODE_LABEL(XBC_CSTAR): 36025dfecf96Smrg /* This the CAR of the CONS */ 36035dfecf96Smrg lisp__data.protect.objects[phead++] = reg0; 36045dfecf96Smrg NEXT_OPCODE(); 36055dfecf96Smrg 36065dfecf96Smrg /* Finish CONS */ 36075dfecf96SmrgOPCODE_LABEL(XBC_CFINI): 36085dfecf96Smrg reg0 = CONS(lisp__data.protect.objects[--phead], reg0); 36095dfecf96Smrg NEXT_OPCODE(); 36105dfecf96Smrg 36115dfecf96Smrg /* Start building list */ 36125dfecf96SmrgOPCODE_LABEL(XBC_LSTAR): 36135dfecf96Smrg reg1 = CONS(reg0, NIL); 36145dfecf96Smrg /* Start of list stored here */ 36155dfecf96Smrg lisp__data.protect.objects[phead++] = reg1; 36165dfecf96Smrg /* Tail of list stored here */ 36175dfecf96Smrg lisp__data.protect.objects[phead++] = reg1; 36185dfecf96Smrg NEXT_OPCODE(); 36195dfecf96Smrg 36205dfecf96Smrg /* Add to list */ 36215dfecf96SmrgOPCODE_LABEL(XBC_LCONS): 36225dfecf96Smrg reg1 = lisp__data.protect.objects[phead - 2]; 36235dfecf96Smrg RPLACD(reg1, CONS(reg0, NIL)); 36245dfecf96Smrg lisp__data.protect.objects[phead - 2] = CDR(reg1); 36255dfecf96Smrg NEXT_OPCODE(); 36265dfecf96Smrg 36275dfecf96Smrg /* Finish list */ 36285dfecf96SmrgOPCODE_LABEL(XBC_LFINI): 36295dfecf96Smrg phead -= 2; 36305dfecf96Smrg reg0 = lisp__data.protect.objects[phead + 1]; 36315dfecf96Smrg NEXT_OPCODE(); 36325dfecf96Smrg 36335dfecf96SmrgOPCODE_LABEL(XBC_STRUCT): 36345dfecf96Smrg offset = *stream++; 36355dfecf96Smrg reg1 = constants[*stream++]; 36365dfecf96Smrg if (!STRUCTP(reg0) || reg0->data.struc.def != reg1) { 3637f14f4646Smrg char *name = ATOMID(CAR(reg1))->value; 36385dfecf96Smrg 36395dfecf96Smrg for (reg1 = CDR(reg1); offset; offset--) 36405dfecf96Smrg reg1 = CDR(reg1); 36415dfecf96Smrg LispDestroy("%s-%s: %s is not a %s", 3642f14f4646Smrg name, ATOMID(CAR(reg1))->value, STROBJ(reg0), name); 36435dfecf96Smrg } 36445dfecf96Smrg for (reg0 = reg0->data.struc.fields; offset; offset--) 36455dfecf96Smrg reg0 = CDR(reg0); 36465dfecf96Smrg reg0 = CAR(reg0); 36475dfecf96Smrg NEXT_OPCODE(); 36485dfecf96Smrg 36495dfecf96SmrgOPCODE_LABEL(XBC_STRUCTP): 36505dfecf96Smrg reg1 = constants[*stream++]; 36515dfecf96Smrg reg0 = STRUCTP(reg0) && reg0->data.struc.def == reg1 ? T : NIL; 36525dfecf96Smrg NEXT_OPCODE(); 36535dfecf96Smrg 36545dfecf96SmrgOPCODE_LABEL(XBC_LETREC): 36555dfecf96Smrg /* XXX could/should optimize, shouldn't need to parse 36565dfecf96Smrg * the bytecode header again */ 36575dfecf96Smrg lex = lisp__data.env.lex; 36585dfecf96Smrg offset = *stream++; 36595dfecf96Smrg lisp__data.env.head = lisp__data.env.length; 36605dfecf96Smrg len = lisp__data.env.lex = lisp__data.env.length - offset; 36615dfecf96Smrg reg0 = ExecuteBytecode(bytecode); 36625dfecf96Smrg lisp__data.env.length = lisp__data.env.head = len; 36635dfecf96Smrg lisp__data.env.lex = lex; 36645dfecf96Smrg NEXT_OPCODE(); 36655dfecf96Smrg 36665dfecf96SmrgOPCODE_LABEL(XBC_RETURN): 36675dfecf96Smrg lisp__data.protect.length = pbase; 36685dfecf96Smrg return (reg0); 36695dfecf96Smrg 36705dfecf96Smrg#ifndef ALLOW_GOTO_ADDRESS 36715dfecf96Smrg } /* end of switch */ 36725dfecf96Smrg 36735dfecf96Smrgpredicate_label: 36745dfecf96Smrg switch (*stream++) { 36755dfecf96Smrg#endif 36765dfecf96Smrg 36775dfecf96SmrgOPCODE_LABEL(XBP_CONSP): 36785dfecf96Smrg reg0 = CONSP(reg0) ? T : NIL; 36795dfecf96Smrg NEXT_OPCODE(); 36805dfecf96Smrg 36815dfecf96SmrgOPCODE_LABEL(XBP_LISTP): 36825dfecf96Smrg reg0 = LISTP(reg0) ? T : NIL; 36835dfecf96Smrg NEXT_OPCODE(); 36845dfecf96Smrg 36855dfecf96SmrgOPCODE_LABEL(XBP_NUMBERP): 36865dfecf96Smrg reg0 = NUMBERP(reg0) ? T : NIL; 36875dfecf96Smrg NEXT_OPCODE(); 36885dfecf96Smrg 36895dfecf96Smrg#ifndef ALLOW_GOTO_ADDRESS 36905dfecf96Smrg } /* end of switch */ 36915dfecf96Smrg } 36925dfecf96Smrg#endif 36935dfecf96Smrg 36945dfecf96Smrg /*NOTREACHED*/ 36955dfecf96Smrg return (reg0); 36965dfecf96Smrg} 3697