2013-05-23 14:52:29 +02:00
|
|
|
/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
|
2001-04-01 05:03:41 +00:00
|
|
|
*
|
2009-05-26 22:23:44 +02:00
|
|
|
* This library is free software; you can redistribute it and/or
|
2009-06-17 00:22:09 +01:00
|
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 3 of
|
|
|
|
|
* the License, or (at your option) any later version.
|
2001-04-01 05:03:41 +00:00
|
|
|
*
|
2009-06-17 00:22:09 +01:00
|
|
|
* This library is distributed in the hope that it will be useful, but
|
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
2009-05-26 22:23:44 +02:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
2001-04-01 05:03:41 +00:00
|
|
|
*
|
2009-05-26 22:23:44 +02:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2009-06-17 00:22:09 +01:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
|
|
* 02110-1301 USA
|
2009-05-26 22:23:44 +02:00
|
|
|
*/
|
2001-04-01 05:03:41 +00:00
|
|
|
|
2008-05-20 11:46:52 +02:00
|
|
|
#if HAVE_CONFIG_H
|
|
|
|
|
# include <config.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-04-01 05:03:41 +00:00
|
|
|
#include <string.h>
|
2009-05-26 22:23:44 +02:00
|
|
|
|
|
|
|
|
#include "_scm.h"
|
2011-02-10 21:11:47 +01:00
|
|
|
#include "threads.h"
|
2001-04-01 05:03:41 +00:00
|
|
|
#include "instructions.h"
|
|
|
|
|
|
2011-02-10 21:11:47 +01:00
|
|
|
|
2013-07-19 09:55:20 +02:00
|
|
|
SCM_SYMBOL (sym_left_arrow, "<-");
|
|
|
|
|
SCM_SYMBOL (sym_bang, "!");
|
|
|
|
|
|
|
|
|
|
|
2013-05-23 14:52:29 +02:00
|
|
|
#define OP_HAS_ARITY (1U << 0)
|
|
|
|
|
|
|
|
|
|
#define FOR_EACH_INSTRUCTION_WORD_TYPE(M) \
|
|
|
|
|
M(X32) \
|
|
|
|
|
M(U8_X24) \
|
|
|
|
|
M(U8_U24) \
|
|
|
|
|
M(U8_L24) \
|
|
|
|
|
M(U8_U8_I16) \
|
|
|
|
|
M(U8_U8_U8_U8) \
|
|
|
|
|
M(U8_U12_U12) \
|
|
|
|
|
M(U32) /* Unsigned. */ \
|
|
|
|
|
M(I32) /* Immediate. */ \
|
|
|
|
|
M(A32) /* Immediate, high bits. */ \
|
|
|
|
|
M(B32) /* Immediate, low bits. */ \
|
|
|
|
|
M(N32) /* Non-immediate. */ \
|
|
|
|
|
M(S32) /* Scheme value (indirected). */ \
|
|
|
|
|
M(L32) /* Label. */ \
|
|
|
|
|
M(LO32) /* Label with offset. */ \
|
|
|
|
|
M(X8_U24) \
|
|
|
|
|
M(X8_U12_U12) \
|
|
|
|
|
M(X8_L24) \
|
|
|
|
|
M(B1_X7_L24) \
|
Various RTL VM and calling convention tweaks
* libguile/instructions.c (FOR_EACH_INSTRUCTION_WORD_TYPE): Allow for
five-word instructions, and for new instruction word types.
* libguile/vm-engine.c (RETURN_ONE_VALUE): Instead of returning the
value in the fixed part of the call frame, return it in the same place
multiple-value returns go: from slot 1.
(BR_ARITHMETIC): Allow arithmetic tests to be negated.
(rtl_vm_engine): Change calling convention to use the same location
for single and multiple-value returns. Renumber all instructions.
(halt, halt/values): Fold into a single instruction (halt).
(call): Take the location of the procedure instead of the location of
the call frame. Also take the number of args, and reset the sp before
jumping to the procedure, so as to indicate the number of arguments.
(call/values): Remove, as the new calling convention has RA == MVRA.
(tail-call): Require the procedure to be shuffled down already, and
take "nlocals" as an arg instead of "nargs".
(receive, receive-values): New instructions, for receiving returned
values from calls.
(return-values): Rename from return/values. Remove "values".
(alloc-frame): Rename from reserve-locals.
(reset-frame): New instruction.
(drop-locals): Remove.
(br-if-=, br-if-<, br-if-<=): Allow these instructions to be
negatable.
(br-if->, br-if->=): Remove. Probably a bad idea, given NaN.
(box-ref): Don't bother trying to do a reverse lookup -- the
toplevel-box, module-box, and resolve instructions should handle
that.
(resolve): Add arg to check that the variable is bound.
(toplevel-box, module-box): New instructions, replacing toplevel-ref,
toplevel-set, module-ref, and module-set.
* libguile/vm.c (rtl_boot_continuation_code, rtl_values_code): Adapt to
instruction set changes.
* module/Makefile.am: Make the assembler and disassembler dependent on
vm-operations.h.
* module/system/vm/assembler.scm:
* module/system/vm/disassembler.scm: Adapt to instruction changes and
new instruction word kinds.
* test-suite/tests/rtl.test: Adapt to instruction set changes.
2013-08-11 16:42:06 +02:00
|
|
|
M(B1_U7_L24) \
|
|
|
|
|
M(B1_X7_U24) \
|
|
|
|
|
M(B1_X31)
|
2013-05-23 14:52:29 +02:00
|
|
|
|
|
|
|
|
#define TYPE_WIDTH 5
|
|
|
|
|
|
|
|
|
|
enum word_type
|
|
|
|
|
{
|
|
|
|
|
#define ENUM(type) type,
|
|
|
|
|
FOR_EACH_INSTRUCTION_WORD_TYPE (ENUM)
|
|
|
|
|
#undef ENUM
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static SCM word_type_symbols[] =
|
|
|
|
|
{
|
|
|
|
|
#define FALSE(type) SCM_BOOL_F,
|
|
|
|
|
FOR_EACH_INSTRUCTION_WORD_TYPE (FALSE)
|
|
|
|
|
#undef FALSE
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define OP(n,type) ((type) << (n*TYPE_WIDTH))
|
|
|
|
|
|
|
|
|
|
/* The VM_DEFINE_OP macro uses a CPP-based DSL to describe what kinds of
|
|
|
|
|
arguments each RTL instruction takes. This piece of code is the only
|
|
|
|
|
bit that actually interprets that language. These macro definitions
|
|
|
|
|
encode the operand types into bits in a 32-bit integer.
|
|
|
|
|
|
|
|
|
|
(rtl-instruction-list) parses those encoded values into lists of
|
|
|
|
|
symbols, one for each 32-bit word that the operator takes. (system
|
|
|
|
|
vm rtl) uses those word types to generate assemblers and
|
|
|
|
|
disassemblers for the instructions. */
|
|
|
|
|
|
|
|
|
|
#define OP1(type0) \
|
|
|
|
|
(OP (0, type0))
|
|
|
|
|
#define OP2(type0, type1) \
|
|
|
|
|
(OP (0, type0) | OP (1, type1))
|
|
|
|
|
#define OP3(type0, type1, type2) \
|
|
|
|
|
(OP (0, type0) | OP (1, type1) | OP (2, type2))
|
|
|
|
|
#define OP4(type0, type1, type2, type3) \
|
|
|
|
|
(OP (0, type0) | OP (1, type1) | OP (2, type2) | OP (3, type3))
|
Various RTL VM and calling convention tweaks
* libguile/instructions.c (FOR_EACH_INSTRUCTION_WORD_TYPE): Allow for
five-word instructions, and for new instruction word types.
* libguile/vm-engine.c (RETURN_ONE_VALUE): Instead of returning the
value in the fixed part of the call frame, return it in the same place
multiple-value returns go: from slot 1.
(BR_ARITHMETIC): Allow arithmetic tests to be negated.
(rtl_vm_engine): Change calling convention to use the same location
for single and multiple-value returns. Renumber all instructions.
(halt, halt/values): Fold into a single instruction (halt).
(call): Take the location of the procedure instead of the location of
the call frame. Also take the number of args, and reset the sp before
jumping to the procedure, so as to indicate the number of arguments.
(call/values): Remove, as the new calling convention has RA == MVRA.
(tail-call): Require the procedure to be shuffled down already, and
take "nlocals" as an arg instead of "nargs".
(receive, receive-values): New instructions, for receiving returned
values from calls.
(return-values): Rename from return/values. Remove "values".
(alloc-frame): Rename from reserve-locals.
(reset-frame): New instruction.
(drop-locals): Remove.
(br-if-=, br-if-<, br-if-<=): Allow these instructions to be
negatable.
(br-if->, br-if->=): Remove. Probably a bad idea, given NaN.
(box-ref): Don't bother trying to do a reverse lookup -- the
toplevel-box, module-box, and resolve instructions should handle
that.
(resolve): Add arg to check that the variable is bound.
(toplevel-box, module-box): New instructions, replacing toplevel-ref,
toplevel-set, module-ref, and module-set.
* libguile/vm.c (rtl_boot_continuation_code, rtl_values_code): Adapt to
instruction set changes.
* module/Makefile.am: Make the assembler and disassembler dependent on
vm-operations.h.
* module/system/vm/assembler.scm:
* module/system/vm/disassembler.scm: Adapt to instruction changes and
new instruction word kinds.
* test-suite/tests/rtl.test: Adapt to instruction set changes.
2013-08-11 16:42:06 +02:00
|
|
|
#define OP5(type0, type1, type2, type3, type4) \
|
|
|
|
|
(OP (0, type0) | OP (1, type1) | OP (2, type2) | OP (3, type3) | OP (4, type4))
|
2013-05-23 14:52:29 +02:00
|
|
|
|
|
|
|
|
#define OP_DST (1 << (TYPE_WIDTH * 5))
|
|
|
|
|
|
|
|
|
|
#define WORD_TYPE(n, word) \
|
|
|
|
|
(((word) >> ((n) * TYPE_WIDTH)) & ((1 << TYPE_WIDTH) - 1))
|
|
|
|
|
|
|
|
|
|
struct scm_rtl_instruction {
|
|
|
|
|
enum scm_rtl_opcode opcode; /* opcode */
|
|
|
|
|
const char *name; /* instruction name */
|
|
|
|
|
scm_t_uint32 meta;
|
|
|
|
|
SCM symname; /* filled in later */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
static opcodes; refactor program/objcode division; use new assembly pipeline
* gdbinit: Untested attempts to get the stack fondling macros to deal
with the new program representation.
* libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source)
(scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is
a struct scm_objcode*.
* libguile/instructions.h:
* libguile/instructions.c: Hide the instruction table and the struct
scm_instruction structure; all access to instructions now goes through
procedures. This is because instructions are no longer in a packed
array indexed by opcode. Also, declare a mask that all instructions
should fit in.
* libguile/objcodes.h:
* libguile/objcodes.c: Rewrite so that object code directly maps its
arity and length from its bytecode. This makes it unnecessary to keep
this information in programs, allowing programs to be simple conses
between the code (objcodes) and data (the object table and the closure
variables).
* libguile/programs.c (scm_make_program): Rework so that make-program
takes objcode, an object table, and externals as arguments. It's much
clearer this way, and we avoid malloc().
* libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode
changes.
* libguile/vm-engine.c (vm_run): Initialize the jump table on the first
run, with the opcodes declared in the instruction sources, and with bad
instructions raising an error instead of wandering off into the
Unknown.
* libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3
bytes. The old code was too error-prone.
(NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK.
(NEW_FRAME): Update for program/objcode changes.
* libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION)
(VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so
that we have a stable bytecode API.
* libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare
opcodes.
(load-integer): Use an int instead of a long as the accumulator; still
need to revisit this code at some point, I think.
(load-program): Simplify, thankfully!! Just creates the objcode slice
and rolls with it.
* libguile/vm-i-scheme.c: Number the opcodes explicitly.
* libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare
opcodes.
(make-closure): Update for new program API.
* libguile/vm.c (vm_make_boot_program): Update for new program/objcode
API. Still a bit ugly.
(scm_load_compiled_with_vm): Update for new program/objcode API.
* module/language/assembly.scm (byte-length): Fix byte-length calculation
for loaders, and load-program.
(code-pack, code-unpack): Start to move things from (system vm conv)
here.
(object->code, code->object): More things from conv.scm.
* module/language/glil.scm (<glil-program>): Add a new field,
closure-level.
(make-glil-program, compute-closure-level): Calculate the "closure
level" when making a glil program. This is the maximum depth of
external binding refs in this closure.
(unparse-glil): Fix label serialization.
* module/language/glil/compile-assembly.scm (make-meta): Prepend #f for
the meta's object table, though maybe in the future we can avoid
creating assembly in the first place.
(assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the
different sets of arguments to assoc and assoc-ref!
(glil->assembly): Attempt to make the <glil-program> case more
readable, and fix the bugs. Sorry I don't know how to comment this
change any more than this.
(glil->assembly): For <glil-module> serialize the whole key, not just
the name.
(dump-object): subprogram-code is already a list. Serialize integers as
strings, not u8vectors. Fix the order of lists and vectors.
* module/language/glil/spec.scm (glil): Switch orders, so we prefer glil
-> assembly -> objcode. Actually glil->objcode doesn't work any more,
needs to be removed I think.
* module/language/objcode/spec.scm (objcode->value):
s/objcode->program/make-program/.
* module/language/scheme/inline.scm: Add acons inline.
* module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes,
they are header. Handle subprograms properly. Still needs help though.
(decode-length): Lengths are always 3 bytes now.
* module/system/vm/disasm.scm: Superficial changes to keep things
working. I'd like to fix this better in the future.
* module/system/vm/frame.scm (bootstrap-frame?): Fixes for
program-bytecode.
* module/system/vm/program.scm: Export make-program. It's program-objcode
now, no more program-bytecode.
* module/system/vm/vm.scm (vm-load): Use make-program.
* test-suite/tests/asm-to-bytecode.test: New test, very minimal.
* module/system/vm/objcode.scm: Export word-size, byte-order, and
write-objcode.
2009-01-29 21:09:04 +01:00
|
|
|
#define SCM_VALIDATE_LOOKUP_INSTRUCTION(pos, var, cvar) \
|
|
|
|
|
do { \
|
|
|
|
|
cvar = scm_lookup_instruction_by_name (var); \
|
|
|
|
|
SCM_ASSERT_TYPE (cvar, var, pos, FUNC_NAME, "INSTRUCTION_P"); \
|
|
|
|
|
} while (0)
|
2001-04-01 05:03:41 +00:00
|
|
|
|
static opcodes; refactor program/objcode division; use new assembly pipeline
* gdbinit: Untested attempts to get the stack fondling macros to deal
with the new program representation.
* libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source)
(scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is
a struct scm_objcode*.
* libguile/instructions.h:
* libguile/instructions.c: Hide the instruction table and the struct
scm_instruction structure; all access to instructions now goes through
procedures. This is because instructions are no longer in a packed
array indexed by opcode. Also, declare a mask that all instructions
should fit in.
* libguile/objcodes.h:
* libguile/objcodes.c: Rewrite so that object code directly maps its
arity and length from its bytecode. This makes it unnecessary to keep
this information in programs, allowing programs to be simple conses
between the code (objcodes) and data (the object table and the closure
variables).
* libguile/programs.c (scm_make_program): Rework so that make-program
takes objcode, an object table, and externals as arguments. It's much
clearer this way, and we avoid malloc().
* libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode
changes.
* libguile/vm-engine.c (vm_run): Initialize the jump table on the first
run, with the opcodes declared in the instruction sources, and with bad
instructions raising an error instead of wandering off into the
Unknown.
* libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3
bytes. The old code was too error-prone.
(NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK.
(NEW_FRAME): Update for program/objcode changes.
* libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION)
(VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so
that we have a stable bytecode API.
* libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare
opcodes.
(load-integer): Use an int instead of a long as the accumulator; still
need to revisit this code at some point, I think.
(load-program): Simplify, thankfully!! Just creates the objcode slice
and rolls with it.
* libguile/vm-i-scheme.c: Number the opcodes explicitly.
* libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare
opcodes.
(make-closure): Update for new program API.
* libguile/vm.c (vm_make_boot_program): Update for new program/objcode
API. Still a bit ugly.
(scm_load_compiled_with_vm): Update for new program/objcode API.
* module/language/assembly.scm (byte-length): Fix byte-length calculation
for loaders, and load-program.
(code-pack, code-unpack): Start to move things from (system vm conv)
here.
(object->code, code->object): More things from conv.scm.
* module/language/glil.scm (<glil-program>): Add a new field,
closure-level.
(make-glil-program, compute-closure-level): Calculate the "closure
level" when making a glil program. This is the maximum depth of
external binding refs in this closure.
(unparse-glil): Fix label serialization.
* module/language/glil/compile-assembly.scm (make-meta): Prepend #f for
the meta's object table, though maybe in the future we can avoid
creating assembly in the first place.
(assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the
different sets of arguments to assoc and assoc-ref!
(glil->assembly): Attempt to make the <glil-program> case more
readable, and fix the bugs. Sorry I don't know how to comment this
change any more than this.
(glil->assembly): For <glil-module> serialize the whole key, not just
the name.
(dump-object): subprogram-code is already a list. Serialize integers as
strings, not u8vectors. Fix the order of lists and vectors.
* module/language/glil/spec.scm (glil): Switch orders, so we prefer glil
-> assembly -> objcode. Actually glil->objcode doesn't work any more,
needs to be removed I think.
* module/language/objcode/spec.scm (objcode->value):
s/objcode->program/make-program/.
* module/language/scheme/inline.scm: Add acons inline.
* module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes,
they are header. Handle subprograms properly. Still needs help though.
(decode-length): Lengths are always 3 bytes now.
* module/system/vm/disasm.scm: Superficial changes to keep things
working. I'd like to fix this better in the future.
* module/system/vm/frame.scm (bootstrap-frame?): Fixes for
program-bytecode.
* module/system/vm/program.scm: Export make-program. It's program-objcode
now, no more program-bytecode.
* module/system/vm/vm.scm (vm-load): Use make-program.
* test-suite/tests/asm-to-bytecode.test: New test, very minimal.
* module/system/vm/objcode.scm: Export word-size, byte-order, and
write-objcode.
2009-01-29 21:09:04 +01:00
|
|
|
|
2011-02-10 21:11:47 +01:00
|
|
|
static scm_i_pthread_mutex_t itable_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
|
|
|
|
|
|
2013-06-08 14:58:10 +02:00
|
|
|
static const struct scm_rtl_instruction*
|
2013-05-23 14:52:29 +02:00
|
|
|
fetch_rtl_instruction_table ()
|
|
|
|
|
{
|
|
|
|
|
static struct scm_rtl_instruction *table = NULL;
|
|
|
|
|
|
|
|
|
|
scm_i_pthread_mutex_lock (&itable_lock);
|
|
|
|
|
if (SCM_UNLIKELY (!table))
|
|
|
|
|
{
|
|
|
|
|
size_t bytes = SCM_VM_NUM_INSTRUCTIONS * sizeof(struct scm_rtl_instruction);
|
|
|
|
|
int i;
|
|
|
|
|
table = malloc (bytes);
|
|
|
|
|
memset (table, 0, bytes);
|
|
|
|
|
|
|
|
|
|
#define INIT(opcode, tag, name_, meta_) table[opcode].name = name_; table[opcode].meta = meta_;
|
|
|
|
|
FOR_EACH_VM_OPERATION (INIT);
|
|
|
|
|
#undef INIT
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < SCM_VM_NUM_INSTRUCTIONS; i++)
|
|
|
|
|
{
|
|
|
|
|
table[i].opcode = i;
|
|
|
|
|
if (table[i].name)
|
|
|
|
|
table[i].symname = scm_from_utf8_symbol (table[i].name);
|
|
|
|
|
else
|
|
|
|
|
table[i].symname = SCM_BOOL_F;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
scm_i_pthread_mutex_unlock (&itable_lock);
|
|
|
|
|
|
|
|
|
|
return table;
|
|
|
|
|
}
|
|
|
|
|
|
static opcodes; refactor program/objcode division; use new assembly pipeline
* gdbinit: Untested attempts to get the stack fondling macros to deal
with the new program representation.
* libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source)
(scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is
a struct scm_objcode*.
* libguile/instructions.h:
* libguile/instructions.c: Hide the instruction table and the struct
scm_instruction structure; all access to instructions now goes through
procedures. This is because instructions are no longer in a packed
array indexed by opcode. Also, declare a mask that all instructions
should fit in.
* libguile/objcodes.h:
* libguile/objcodes.c: Rewrite so that object code directly maps its
arity and length from its bytecode. This makes it unnecessary to keep
this information in programs, allowing programs to be simple conses
between the code (objcodes) and data (the object table and the closure
variables).
* libguile/programs.c (scm_make_program): Rework so that make-program
takes objcode, an object table, and externals as arguments. It's much
clearer this way, and we avoid malloc().
* libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode
changes.
* libguile/vm-engine.c (vm_run): Initialize the jump table on the first
run, with the opcodes declared in the instruction sources, and with bad
instructions raising an error instead of wandering off into the
Unknown.
* libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3
bytes. The old code was too error-prone.
(NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK.
(NEW_FRAME): Update for program/objcode changes.
* libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION)
(VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so
that we have a stable bytecode API.
* libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare
opcodes.
(load-integer): Use an int instead of a long as the accumulator; still
need to revisit this code at some point, I think.
(load-program): Simplify, thankfully!! Just creates the objcode slice
and rolls with it.
* libguile/vm-i-scheme.c: Number the opcodes explicitly.
* libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare
opcodes.
(make-closure): Update for new program API.
* libguile/vm.c (vm_make_boot_program): Update for new program/objcode
API. Still a bit ugly.
(scm_load_compiled_with_vm): Update for new program/objcode API.
* module/language/assembly.scm (byte-length): Fix byte-length calculation
for loaders, and load-program.
(code-pack, code-unpack): Start to move things from (system vm conv)
here.
(object->code, code->object): More things from conv.scm.
* module/language/glil.scm (<glil-program>): Add a new field,
closure-level.
(make-glil-program, compute-closure-level): Calculate the "closure
level" when making a glil program. This is the maximum depth of
external binding refs in this closure.
(unparse-glil): Fix label serialization.
* module/language/glil/compile-assembly.scm (make-meta): Prepend #f for
the meta's object table, though maybe in the future we can avoid
creating assembly in the first place.
(assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the
different sets of arguments to assoc and assoc-ref!
(glil->assembly): Attempt to make the <glil-program> case more
readable, and fix the bugs. Sorry I don't know how to comment this
change any more than this.
(glil->assembly): For <glil-module> serialize the whole key, not just
the name.
(dump-object): subprogram-code is already a list. Serialize integers as
strings, not u8vectors. Fix the order of lists and vectors.
* module/language/glil/spec.scm (glil): Switch orders, so we prefer glil
-> assembly -> objcode. Actually glil->objcode doesn't work any more,
needs to be removed I think.
* module/language/objcode/spec.scm (objcode->value):
s/objcode->program/make-program/.
* module/language/scheme/inline.scm: Add acons inline.
* module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes,
they are header. Handle subprograms properly. Still needs help though.
(decode-length): Lengths are always 3 bytes now.
* module/system/vm/disasm.scm: Superficial changes to keep things
working. I'd like to fix this better in the future.
* module/system/vm/frame.scm (bootstrap-frame?): Fixes for
program-bytecode.
* module/system/vm/program.scm: Export make-program. It's program-objcode
now, no more program-bytecode.
* module/system/vm/vm.scm (vm-load): Use make-program.
* test-suite/tests/asm-to-bytecode.test: New test, very minimal.
* module/system/vm/objcode.scm: Export word-size, byte-order, and
write-objcode.
2009-01-29 21:09:04 +01:00
|
|
|
|
2001-04-01 05:03:41 +00:00
|
|
|
/* Scheme interface */
|
|
|
|
|
|
2013-05-23 14:52:29 +02:00
|
|
|
SCM_DEFINE (scm_rtl_instruction_list, "rtl-instruction-list", 0, 0, 0,
|
|
|
|
|
(void),
|
|
|
|
|
"")
|
|
|
|
|
#define FUNC_NAME s_scm_rtl_instruction_list
|
|
|
|
|
{
|
|
|
|
|
SCM list = SCM_EOL;
|
|
|
|
|
int i;
|
2013-06-08 14:58:10 +02:00
|
|
|
const struct scm_rtl_instruction *ip = fetch_rtl_instruction_table ();
|
2013-05-23 14:52:29 +02:00
|
|
|
for (i = 0; i < SCM_VM_NUM_INSTRUCTIONS; i++)
|
|
|
|
|
if (ip[i].name)
|
|
|
|
|
{
|
|
|
|
|
scm_t_uint32 meta = ip[i].meta;
|
|
|
|
|
SCM tail = SCM_EOL;
|
|
|
|
|
int len;
|
|
|
|
|
|
2013-06-08 14:58:10 +02:00
|
|
|
/* Format: (name opcode word0 word1 ...) */
|
2013-05-23 14:52:29 +02:00
|
|
|
|
Various RTL VM and calling convention tweaks
* libguile/instructions.c (FOR_EACH_INSTRUCTION_WORD_TYPE): Allow for
five-word instructions, and for new instruction word types.
* libguile/vm-engine.c (RETURN_ONE_VALUE): Instead of returning the
value in the fixed part of the call frame, return it in the same place
multiple-value returns go: from slot 1.
(BR_ARITHMETIC): Allow arithmetic tests to be negated.
(rtl_vm_engine): Change calling convention to use the same location
for single and multiple-value returns. Renumber all instructions.
(halt, halt/values): Fold into a single instruction (halt).
(call): Take the location of the procedure instead of the location of
the call frame. Also take the number of args, and reset the sp before
jumping to the procedure, so as to indicate the number of arguments.
(call/values): Remove, as the new calling convention has RA == MVRA.
(tail-call): Require the procedure to be shuffled down already, and
take "nlocals" as an arg instead of "nargs".
(receive, receive-values): New instructions, for receiving returned
values from calls.
(return-values): Rename from return/values. Remove "values".
(alloc-frame): Rename from reserve-locals.
(reset-frame): New instruction.
(drop-locals): Remove.
(br-if-=, br-if-<, br-if-<=): Allow these instructions to be
negatable.
(br-if->, br-if->=): Remove. Probably a bad idea, given NaN.
(box-ref): Don't bother trying to do a reverse lookup -- the
toplevel-box, module-box, and resolve instructions should handle
that.
(resolve): Add arg to check that the variable is bound.
(toplevel-box, module-box): New instructions, replacing toplevel-ref,
toplevel-set, module-ref, and module-set.
* libguile/vm.c (rtl_boot_continuation_code, rtl_values_code): Adapt to
instruction set changes.
* module/Makefile.am: Make the assembler and disassembler dependent on
vm-operations.h.
* module/system/vm/assembler.scm:
* module/system/vm/disassembler.scm: Adapt to instruction changes and
new instruction word kinds.
* test-suite/tests/rtl.test: Adapt to instruction set changes.
2013-08-11 16:42:06 +02:00
|
|
|
if (WORD_TYPE (4, meta))
|
|
|
|
|
len = 5;
|
|
|
|
|
else if (WORD_TYPE (3, meta))
|
2013-05-23 14:52:29 +02:00
|
|
|
len = 4;
|
|
|
|
|
else if (WORD_TYPE (2, meta))
|
|
|
|
|
len = 3;
|
|
|
|
|
else if (WORD_TYPE (1, meta))
|
|
|
|
|
len = 2;
|
|
|
|
|
else if (WORD_TYPE (0, meta))
|
|
|
|
|
len = 1;
|
|
|
|
|
else
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
switch (len)
|
|
|
|
|
{
|
Various RTL VM and calling convention tweaks
* libguile/instructions.c (FOR_EACH_INSTRUCTION_WORD_TYPE): Allow for
five-word instructions, and for new instruction word types.
* libguile/vm-engine.c (RETURN_ONE_VALUE): Instead of returning the
value in the fixed part of the call frame, return it in the same place
multiple-value returns go: from slot 1.
(BR_ARITHMETIC): Allow arithmetic tests to be negated.
(rtl_vm_engine): Change calling convention to use the same location
for single and multiple-value returns. Renumber all instructions.
(halt, halt/values): Fold into a single instruction (halt).
(call): Take the location of the procedure instead of the location of
the call frame. Also take the number of args, and reset the sp before
jumping to the procedure, so as to indicate the number of arguments.
(call/values): Remove, as the new calling convention has RA == MVRA.
(tail-call): Require the procedure to be shuffled down already, and
take "nlocals" as an arg instead of "nargs".
(receive, receive-values): New instructions, for receiving returned
values from calls.
(return-values): Rename from return/values. Remove "values".
(alloc-frame): Rename from reserve-locals.
(reset-frame): New instruction.
(drop-locals): Remove.
(br-if-=, br-if-<, br-if-<=): Allow these instructions to be
negatable.
(br-if->, br-if->=): Remove. Probably a bad idea, given NaN.
(box-ref): Don't bother trying to do a reverse lookup -- the
toplevel-box, module-box, and resolve instructions should handle
that.
(resolve): Add arg to check that the variable is bound.
(toplevel-box, module-box): New instructions, replacing toplevel-ref,
toplevel-set, module-ref, and module-set.
* libguile/vm.c (rtl_boot_continuation_code, rtl_values_code): Adapt to
instruction set changes.
* module/Makefile.am: Make the assembler and disassembler dependent on
vm-operations.h.
* module/system/vm/assembler.scm:
* module/system/vm/disassembler.scm: Adapt to instruction changes and
new instruction word kinds.
* test-suite/tests/rtl.test: Adapt to instruction set changes.
2013-08-11 16:42:06 +02:00
|
|
|
case 5:
|
|
|
|
|
tail = scm_cons (word_type_symbols[WORD_TYPE (4, meta)], tail);
|
2013-05-23 14:52:29 +02:00
|
|
|
case 4:
|
|
|
|
|
tail = scm_cons (word_type_symbols[WORD_TYPE (3, meta)], tail);
|
|
|
|
|
case 3:
|
|
|
|
|
tail = scm_cons (word_type_symbols[WORD_TYPE (2, meta)], tail);
|
|
|
|
|
case 2:
|
|
|
|
|
tail = scm_cons (word_type_symbols[WORD_TYPE (1, meta)], tail);
|
|
|
|
|
case 1:
|
|
|
|
|
tail = scm_cons (word_type_symbols[WORD_TYPE (0, meta)], tail);
|
|
|
|
|
default:
|
2013-07-19 09:55:20 +02:00
|
|
|
tail = scm_cons ((meta & OP_DST) ? sym_left_arrow : sym_bang, tail);
|
2013-05-23 14:52:29 +02:00
|
|
|
tail = scm_cons (scm_from_int (ip[i].opcode), tail);
|
|
|
|
|
tail = scm_cons (ip[i].symname, tail);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list = scm_cons (tail, list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return scm_reverse_x (list, SCM_EOL);
|
|
|
|
|
}
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
big reorg of scheme modules -- e.g. programs.c -> (system vm program)
This reorganization kills the ugly module-export-all hacks in
bootstrap.scm and core.scm. In fact, it gets rid of core.scm entirely,
breaking out its functionality into separate files.
* module/system/vm/trace.scm:
* module/system/vm/profile.scm:
* module/system/vm/disasm.scm:
* module/system/vm/debug.scm:
* module/system/vm/conv.scm:
* module/system/vm/assemble.scm:
* module/system/repl/repl.scm:
* module/system/repl/common.scm:
* module/system/base/compile.scm:
* module/system/repl/command.scm: Update for changes, and fix a bug in
procedure-documentation.
* module/system/vm/bootstrap.scm: Just call scm_bootstrap_vm, which
handles setting load-compiled for us.
* module/system/vm/core.scm: Removed, functionality folded into other
modules.
* module/system/vm/frame.scm: Export the C frame procedures here; also
move scheme functions from core.scm here.
* module/system/vm/instruction.scm: New file, exports procedures from
instructions.c.
* module/system/vm/objcode.scm: New file, exports procedures from
objcodes.c.
* module/system/vm/program.scm: New file, exports procedures from
programs.c, and some scheme functions originally from core.scm.
* module/system/vm/vm.scm: New file, from vm.c and core.scm.
* src/Makefile.am (libguile_vm_la_SOURCES): Add bootstrap.h.
* src/bootstrap.h: New file, prototypes scm_bootstrap_vm (), which the
scm_init_* functions call.
* src/frames.h:
* src/frames.c (scm_init_frames):
* src/frames.c (scm_bootstrap_frames):
* src/vm.h:
* src/instructions.h:
* src/instructions.c (scm_init_instructions):
* src/instructions.c (scm_bootstrap_instructions):
* src/objcodes.h:
* src/objcodes.c (scm_bootstrap_objcodes):
* src/objcodes.c (scm_init_objcodes):
* src/programs.h:
* src/programs.c (scm_bootstrap_programs):
* src/programs.c (scm_init_programs):
* src/vm.c (scm_bootstrap_vm):
* src/vm.c (scm_init_vm): Call scm_bootstrap_vm() before doing anything
in an init function. Bootstrap_vm will call bootstrap_instructions(),
etc to initialize types, then set load-compiled to point to
load-compiled/vm.
* src/vm.c (scm_load_compiled_with_vm): Code to load .go files, if
they're present.
2008-08-07 13:11:27 +02:00
|
|
|
void
|
|
|
|
|
scm_bootstrap_instructions (void)
|
|
|
|
|
{
|
2010-03-16 21:18:12 +01:00
|
|
|
scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
|
|
|
|
|
"scm_init_instructions",
|
2009-03-27 18:40:15 -07:00
|
|
|
(scm_t_extension_init_func)scm_init_instructions,
|
|
|
|
|
NULL);
|
2013-05-23 14:52:29 +02:00
|
|
|
|
|
|
|
|
#define INIT(type) \
|
|
|
|
|
word_type_symbols[type] = scm_from_utf8_symbol (#type);
|
|
|
|
|
FOR_EACH_INSTRUCTION_WORD_TYPE (INIT)
|
|
|
|
|
#undef INIT
|
big reorg of scheme modules -- e.g. programs.c -> (system vm program)
This reorganization kills the ugly module-export-all hacks in
bootstrap.scm and core.scm. In fact, it gets rid of core.scm entirely,
breaking out its functionality into separate files.
* module/system/vm/trace.scm:
* module/system/vm/profile.scm:
* module/system/vm/disasm.scm:
* module/system/vm/debug.scm:
* module/system/vm/conv.scm:
* module/system/vm/assemble.scm:
* module/system/repl/repl.scm:
* module/system/repl/common.scm:
* module/system/base/compile.scm:
* module/system/repl/command.scm: Update for changes, and fix a bug in
procedure-documentation.
* module/system/vm/bootstrap.scm: Just call scm_bootstrap_vm, which
handles setting load-compiled for us.
* module/system/vm/core.scm: Removed, functionality folded into other
modules.
* module/system/vm/frame.scm: Export the C frame procedures here; also
move scheme functions from core.scm here.
* module/system/vm/instruction.scm: New file, exports procedures from
instructions.c.
* module/system/vm/objcode.scm: New file, exports procedures from
objcodes.c.
* module/system/vm/program.scm: New file, exports procedures from
programs.c, and some scheme functions originally from core.scm.
* module/system/vm/vm.scm: New file, from vm.c and core.scm.
* src/Makefile.am (libguile_vm_la_SOURCES): Add bootstrap.h.
* src/bootstrap.h: New file, prototypes scm_bootstrap_vm (), which the
scm_init_* functions call.
* src/frames.h:
* src/frames.c (scm_init_frames):
* src/frames.c (scm_bootstrap_frames):
* src/vm.h:
* src/instructions.h:
* src/instructions.c (scm_init_instructions):
* src/instructions.c (scm_bootstrap_instructions):
* src/objcodes.h:
* src/objcodes.c (scm_bootstrap_objcodes):
* src/objcodes.c (scm_init_objcodes):
* src/programs.h:
* src/programs.c (scm_bootstrap_programs):
* src/programs.c (scm_init_programs):
* src/vm.c (scm_bootstrap_vm):
* src/vm.c (scm_init_vm): Call scm_bootstrap_vm() before doing anything
in an init function. Bootstrap_vm will call bootstrap_instructions(),
etc to initialize types, then set load-compiled to point to
load-compiled/vm.
* src/vm.c (scm_load_compiled_with_vm): Code to load .go files, if
they're present.
2008-08-07 13:11:27 +02:00
|
|
|
}
|
|
|
|
|
|
2001-04-01 05:03:41 +00:00
|
|
|
void
|
|
|
|
|
scm_init_instructions (void)
|
|
|
|
|
{
|
|
|
|
|
#ifndef SCM_MAGIC_SNARFER
|
2009-03-16 23:39:29 +01:00
|
|
|
#include "libguile/instructions.x"
|
2001-04-01 05:03:41 +00:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Local Variables:
|
|
|
|
|
c-file-style: "gnu"
|
|
|
|
|
End:
|
|
|
|
|
*/
|