1 /* 2 * code.h - Virtual machine code 3 * 4 * Copyright (c) 2005-2020 Shiro Kawai <shiro@acm.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the authors nor the names of its contributors 18 * may be used to endorse or promote products derived from this 19 * software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #ifndef GAUCHE_CODE_H 35 #define GAUCHE_CODE_H 36 37 SCM_DECL_BEGIN 38 39 #include <gauche/vm.h> 40 41 /* 42 * Compiled code packet 43 */ 44 45 struct ScmCompiledCodeRec { 46 SCM_HEADER; 47 ScmWord *code; /* Code vector (*1). This is allocated as 48 atomic, to prevent GC from scanning it. 49 (*2) */ 50 ScmObj *constants; /* Constant vector. this isn't used during 51 execution, but kept here so that the 52 constants in the code vector won't be 53 GC-ed. (*2) */ 54 int codeSize; /* size of code vector */ 55 int constantSize; /* size of constant vector (*2) */ 56 int maxstack; /* maximum runtime stack depth */ 57 u_short requiredArgs; /* # of required args, if this code is the 58 body of a closure. Otherwise 0. */ 59 u_short optionalArgs; /* 1 if this code is the body of a closure. 60 that takes rest arg. Otherwise 0. */ 61 ScmObj name; /* If this is the body of a closure, holds 62 its name. Otherwise #f. */ 63 ScmObj debugInfo; /* debug info, that associates instructions 64 and source code / other metainfo. May be 65 () if no info is available. (*3) */ 66 ScmObj signatureInfo; /* signature info, a metainfo related to the 67 interface of this closure. Maybe #f 68 if no info is available. (*4) */ 69 ScmObj parent; /* ScmCompiledCode if this code is compiled 70 within other code chunk. #f otherwise. */ 71 ScmObj intermediateForm; /* A packed IForm of the body (see compile.scm 72 for the details of IForm). It is used 73 to inline this procedure. Only set if 74 the procedure is defined with define-inline. 75 #f otherwise. (*5) */ 76 void *builder; /* An opaque data used during consturcting 77 the code vector. Usually NULL. */ 78 }; 79 80 /* Footnotes on ScmCompiledCodeRec 81 * 82 * *1) This may be NULL if this compiled code is "partially compiled"--- 83 * that is, the compiler only runs pass1 and put the intermediate 84 * form in intermediateForm field. 85 * *2) For the C-dumped code, the code vector is located in a static data 86 * area, subject to GC scanning. In that case, the constants pointer 87 * is NULL. 88 * *3) ((<offset> <info> ...) ...) 89 * <offset> is either an instruction offset or 'definition (for the 90 * entire closure). 91 * At this moment, only used <info> is (source-info . <source>). 92 * *4) (<signature> <info> ...) 93 * <signature> is (<procedure-name> <formal> ...) 94 * <procedure-name> may be just a symbol, or a list (in case of internal 95 * function). There's no precise definition for the format yet---it's 96 * for debug information. See Scm_CompiledCodeFullName(). 97 * <formal> ... is the formal argument list, as appears in the original 98 * lambda form, including :key, :optional etc. 99 * At this moment we don't use <info> ... yet; the plan is to put 100 * metainfo about closure interface, e.g. types. 101 * *5) This IForm is a direct result of Pass1, i.e. non-optimized form. 102 * Pass2 scans it when IForm is inlined into the caller site. 103 */ 104 105 SCM_CLASS_DECL(Scm_CompiledCodeClass); 106 #define SCM_CLASS_COMPILED_CODE (&Scm_CompiledCodeClass) 107 108 #define SCM_COMPILED_CODE(obj) ((ScmCompiledCode*)(obj)) 109 #define SCM_COMPILED_CODE_P(obj) SCM_XTYPEP(obj, SCM_CLASS_COMPILED_CODE) 110 #define SCM_COMPILED_CODE_ARG_INFO(obj) (SCM_COMPILED_CODE(obj)->argInfo) 111 #define SCM_COMPILED_CODE_REQUIRED_ARGS(obj) \ 112 (SCM_COMPILED_CODE(obj)->requiredArgs) 113 #define SCM_COMPILED_CODE_OPTIONAL_ARGS(obj) \ 114 (SCM_COMPILED_CODE(obj)->optionalArgs) 115 116 #define SCM_COMPILED_CODE_CONST_INITIALIZER(code, codesize, maxstack, reqargs, optargs, name, debuginfo, signatureinfo, parent, iform) \ 117 { { SCM_CLASS_STATIC_TAG(Scm_CompiledCodeClass) }, \ 118 (code), NULL, (codesize), 0, (maxstack), \ 119 (reqargs), (optargs), (name), (debuginfo), (signatureinfo), \ 120 (parent), (iform), NULL /*builder*/ } 121 122 SCM_EXTERN void Scm_CompiledCodeCopyX(ScmCompiledCode *dest, 123 const ScmCompiledCode *src); 124 SCM_EXTERN void Scm_CompiledCodeDump(ScmCompiledCode *cc); 125 SCM_EXTERN ScmObj Scm_CompiledCodeToList(ScmCompiledCode *cc); 126 SCM_EXTERN ScmObj Scm_CompiledCodeFullName(ScmCompiledCode *cc); 127 SCM_EXTERN void Scm_VMExecuteToplevels(ScmCompiledCode *cv[]); 128 129 /* 130 * VM instructions 131 */ 132 #define SCM_VM_INSN_ARG_MAX ((1L<<(32-13))-1) 133 #define SCM_VM_INSN_ARG_MIN (-SCM_VM_INSN_ARG_MAX) 134 #define SCM_VM_INSN_ARG_FITS(k) \ 135 (((k)<=SCM_VM_INSN_ARG_MAX)&&((k)>=SCM_VM_INSN_ARG_MIN)) 136 137 /* Macros for transition to the packed code vector of NVM. 138 In the packed code vector, VM insns are stored untagged. 139 It eliminates the shift in the dispatcher. */ 140 #define SCM_VM_INSN_CODE(obj) ((u_int)(SCM_WORD(obj)&0x0fff)) 141 #define SCM_VM_INSN_ARG(obj) ((signed long)SCM_WORD(obj) >> 12) 142 #define SCM_VM_INSN_ARG0(obj) ((int)((SCM_WORD(obj) >> 12) & 0x03ff)) 143 #define SCM_VM_INSN_ARG1(obj) ((int)((SCM_WORD(obj) >> 22) & 0x03ff)) 144 145 #define SCM_VM_INSN(code) SCM_WORD(code) 146 #define SCM_VM_INSN1(code, arg) SCM_WORD((long)((arg)<<12) | (code)) 147 #define SCM_VM_INSN2(code, arg0, arg1) \ 148 SCM_WORD((long)((arg1) << 22) | ((arg0) << 12) | (code)) 149 150 /* insn flags. see vminsn.scm for details. */ 151 enum ScmVMInsnFlag { 152 SCM_VM_INSN_OBSOLETED = (1L<<0), 153 SCM_VM_INSN_FOLD_LREF = (1L<<1) 154 }; 155 156 /* Operand type */ 157 enum { 158 SCM_VM_OPERAND_NONE, /* take no operand */ 159 SCM_VM_OPERAND_OBJ, /* take ScmObj */ 160 SCM_VM_OPERAND_CODE, /* take ScmCompiledCode */ 161 SCM_VM_OPERAND_CODES, /* take a list of ScmCompiledCodes */ 162 SCM_VM_OPERAND_ADDR, /* take address of next code */ 163 SCM_VM_OPERAND_OBJ_ADDR /* take an object and address of next code */ 164 }; 165 166 SCM_EXTERN const char *Scm_VMInsnName(u_int code); 167 SCM_EXTERN int Scm_VMInsnNumParams(u_int code); 168 SCM_EXTERN int Scm_VMInsnOperandType(u_int code); 169 SCM_EXTERN int Scm_VMInsnNameToCode(ScmObj name); 170 SCM_EXTERN ScmWord Scm_VMInsnBuild(ScmObj insn); 171 172 SCM_DECL_END 173 174 #endif /* GAUCHE_CODE_H */ 175