mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
add new rtl vm
* libguile/vm-engine.c (rtl_vm_engine): Add new VM. (vm_engine): Add support for calling RTL programs. * libguile/tags.h (scm_tc7_rtl_program): New type for procedures that run on the new VM. * libguile/evalext.c (scm_self_evaluating_p): * libguile/goops.c (scm_class_of): * libguile/print.c (iprin1): * libguile/procprop.c (scm_i_procedure_arity): * libguile/procs.c (scm_procedure_p): Add hooks for the new tc7. * libguile/programs.h: * libguile/programs.c (scm_make_rtl_program, scm_i_rtl_program_print) (scm_rtl_program_p, scm_rtl_program_code): * module/system/vm/program.scm: Add constructors and accessors for the new "RTL programs". * libguile/vm.c (rtl_boot_continuation): Define a boot program. (rtl_apply, rtl_values): New static RTL programs. * libguile/frames.c (scm_frame_num_locals): Adapt for frames of RTL programs. * libguile/frames.h: Add description of RTL frames. * libguile/Makefile.am: Add rules to generate vm-operations.h. * .gitignore: Ignore vm-operations.h. * module/system/vm/instruction.scm: * libguile/instructions.c: * libguile/instructions.h: Use vm-operations.h to define enumerated values for the new RTL opcodes. Define some helper macros to pack and unpack 32-bit instruction words. (rtl-instruction-list): New function, exported by (system vm instruction). * libguile/objcodes.c: Wire up the bits needed to detect the new RTL bytecode and load it, as appropriate.
This commit is contained in:
parent
1701a68920
commit
510ca12687
19 changed files with 3626 additions and 29 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -156,3 +156,4 @@ INSTALL
|
||||||
/test-suite/standalone/test-smob-mark
|
/test-suite/standalone/test-smob-mark
|
||||||
/test-suite/standalone/test-scm-values
|
/test-suite/standalone/test-scm-values
|
||||||
/test-suite/standalone/test-scm-to-latin1-string
|
/test-suite/standalone/test-scm-to-latin1-string
|
||||||
|
/libguile/vm-operations.h
|
||||||
|
|
|
@ -433,9 +433,18 @@ DOT_I_FILES = vm-i-system.i vm-i-scheme.i vm-i-loader.i
|
||||||
.c.i:
|
.c.i:
|
||||||
$(AM_V_GEN)$(GREP) '^VM_DEFINE' $< > $@
|
$(AM_V_GEN)$(GREP) '^VM_DEFINE' $< > $@
|
||||||
|
|
||||||
|
vm-operations.h: vm-engine.c
|
||||||
|
@echo '/* This file was generated automatically from $<; do not' > $@
|
||||||
|
@echo ' edit. See the source file for copyright information. */' >> $@
|
||||||
|
@echo '' >> $@
|
||||||
|
@echo "#define FOR_EACH_VM_OPERATION(M) \\" >> $@
|
||||||
|
$(AM_V_GEN)$(GREP) '^ *VM_DEFINE_OP' $< \
|
||||||
|
| sed -e 's,VM_DEFINE_OP (\(.*\)).*, M (\1) \\,' >> $@
|
||||||
|
@echo '' >> $@
|
||||||
|
|
||||||
BUILT_SOURCES = cpp-E.c cpp-SIG.c libpath.h \
|
BUILT_SOURCES = cpp-E.c cpp-SIG.c libpath.h \
|
||||||
scmconfig.h \
|
scmconfig.h \
|
||||||
$(DOT_I_FILES) $(DOT_X_FILES) $(EXTRA_DOT_X_FILES)
|
$(DOT_I_FILES) vm-operations.h $(DOT_X_FILES) $(EXTRA_DOT_X_FILES)
|
||||||
|
|
||||||
# Force the generation of `guile-procedures.texi' because the top-level
|
# Force the generation of `guile-procedures.texi' because the top-level
|
||||||
# Makefile expects it to be built.
|
# Makefile expects it to be built.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 1998,1999,2000,2001,2002,2003, 2006, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
/* Copyright (C) 1998,1999,2000,2001,2002,2003, 2006, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -87,6 +87,7 @@ SCM_DEFINE (scm_self_evaluating_p, "self-evaluating?", 1, 0, 0,
|
||||||
case scm_tc7_number:
|
case scm_tc7_number:
|
||||||
case scm_tc7_string:
|
case scm_tc7_string:
|
||||||
case scm_tc7_smob:
|
case scm_tc7_smob:
|
||||||
|
case scm_tc7_rtl_program:
|
||||||
case scm_tc7_program:
|
case scm_tc7_program:
|
||||||
case scm_tc7_bytevector:
|
case scm_tc7_bytevector:
|
||||||
case scm_tc7_array:
|
case scm_tc7_array:
|
||||||
|
|
|
@ -129,11 +129,21 @@ SCM_DEFINE (scm_frame_num_locals, "frame-num-locals", 1, 0, 0,
|
||||||
"")
|
"")
|
||||||
#define FUNC_NAME s_scm_frame_num_locals
|
#define FUNC_NAME s_scm_frame_num_locals
|
||||||
{
|
{
|
||||||
SCM *sp, *p;
|
SCM *fp, *sp, *p;
|
||||||
unsigned int n = 0;
|
unsigned int n = 0;
|
||||||
|
|
||||||
SCM_VALIDATE_VM_FRAME (1, frame);
|
SCM_VALIDATE_VM_FRAME (1, frame);
|
||||||
|
|
||||||
|
fp = SCM_VM_FRAME_FP (frame);
|
||||||
|
sp = SCM_VM_FRAME_SP (frame);
|
||||||
|
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
|
||||||
|
|
||||||
|
if (SCM_RTL_PROGRAM_P (fp[-1]))
|
||||||
|
/* The frame size of an RTL program is fixed, except in the case of
|
||||||
|
passing a wrong number of arguments to the program. So we do
|
||||||
|
need to use an SP for determining the number of locals. */
|
||||||
|
return scm_from_uint32 (sp + 1 - p);
|
||||||
|
|
||||||
sp = SCM_VM_FRAME_SP (frame);
|
sp = SCM_VM_FRAME_SP (frame);
|
||||||
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
|
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
|
||||||
while (p <= sp)
|
while (p <= sp)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001, 2009, 2010, 2011 Free Software Foundation, Inc.
|
/* Copyright (C) 2001, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
|
||||||
* *
|
* *
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -98,6 +98,37 @@ struct scm_vm_frame
|
||||||
#define SCM_FRAME_PROGRAM(fp) \
|
#define SCM_FRAME_PROGRAM(fp) \
|
||||||
(SCM_FRAME_STRUCT (fp)->program)
|
(SCM_FRAME_STRUCT (fp)->program)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RTL frames
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The frame format for the new RTL programs is almost like that for the
|
||||||
|
stack-vm programs. They differ in their handling of MV returns,
|
||||||
|
however. For RTL, every call is an MV call: every call has an MVRA.
|
||||||
|
Unlike the stack-vm programs, the MVRA for RTL programs is computable
|
||||||
|
from the RA -- it's always one word (4 bytes) before the RA.
|
||||||
|
|
||||||
|
Until we completely migrate to the RTL VM, we will also write the
|
||||||
|
MVRA to the stack.
|
||||||
|
|
||||||
|
When an RTL program returns multiple values, it will shuffle them
|
||||||
|
down to start contiguously from slot 0, as for a tail call. This
|
||||||
|
means that when the caller goes to access them, there are 2 or 3
|
||||||
|
empty words between the top of the caller stack and the bottom of the
|
||||||
|
values, corresponding to the frame that was just popped.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SCM_FRAME_RTL_RETURN_ADDRESS(fp) \
|
||||||
|
((scm_t_uint32 *) SCM_FRAME_RETURN_ADDRESS (fp))
|
||||||
|
#define SCM_FRAME_SET_RTL_RETURN_ADDRESS(fp, ip) \
|
||||||
|
SCM_FRAME_SET_RETURN_ADDRESS (fp, (scm_t_uint8 *) (ip))
|
||||||
|
|
||||||
|
#define SCM_FRAME_RTL_MV_RETURN_ADDRESS(fp) \
|
||||||
|
((scm_t_uint32 *) SCM_FRAME_MV_RETURN_ADDRESS (fp))
|
||||||
|
#define SCM_FRAME_SET_RTL_MV_RETURN_ADDRESS(fp, ip) \
|
||||||
|
SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, (scm_t_uint8 *) (ip))
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Heap frames
|
* Heap frames
|
||||||
|
|
|
@ -301,6 +301,9 @@ SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
|
||||||
else
|
else
|
||||||
return scm_class_procedure;
|
return scm_class_procedure;
|
||||||
|
|
||||||
|
case scm_tc7_rtl_program:
|
||||||
|
return scm_class_procedure;
|
||||||
|
|
||||||
case scm_tc7_smob:
|
case scm_tc7_smob:
|
||||||
{
|
{
|
||||||
scm_t_bits type = SCM_TYP16 (x);
|
scm_t_bits type = SCM_TYP16 (x);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001, 2009, 2010, 2011 Free Software Foundation, Inc.
|
/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -40,6 +40,83 @@ struct scm_instruction {
|
||||||
SCM symname; /* filled in later */
|
SCM symname; /* filled in later */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#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_R24) \
|
||||||
|
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_R24) \
|
||||||
|
M(X8_L24) \
|
||||||
|
M(B1_X7_L24) \
|
||||||
|
M(B1_U7_L24)
|
||||||
|
|
||||||
|
#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))
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define SCM_VALIDATE_LOOKUP_INSTRUCTION(pos, var, cvar) \
|
#define SCM_VALIDATE_LOOKUP_INSTRUCTION(pos, var, cvar) \
|
||||||
do { \
|
do { \
|
||||||
cvar = scm_lookup_instruction_by_name (var); \
|
cvar = scm_lookup_instruction_by_name (var); \
|
||||||
|
@ -82,6 +159,37 @@ fetch_instruction_table ()
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct scm_rtl_instruction*
|
||||||
|
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 struct scm_instruction *
|
static struct scm_instruction *
|
||||||
scm_lookup_instruction_by_name (SCM name)
|
scm_lookup_instruction_by_name (SCM name)
|
||||||
{
|
{
|
||||||
|
@ -127,6 +235,57 @@ SCM_DEFINE (scm_instruction_list, "instruction-list", 0, 0, 0,
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
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;
|
||||||
|
struct scm_rtl_instruction *ip = fetch_rtl_instruction_table ();
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* Format: (name opcode len rest? out br in) */
|
||||||
|
|
||||||
|
if (WORD_TYPE (3, meta))
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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:
|
||||||
|
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
|
||||||
|
|
||||||
SCM_DEFINE (scm_instruction_p, "instruction?", 1, 0, 0,
|
SCM_DEFINE (scm_instruction_p, "instruction?", 1, 0, 0,
|
||||||
(SCM obj),
|
(SCM obj),
|
||||||
"")
|
"")
|
||||||
|
@ -208,6 +367,11 @@ scm_bootstrap_instructions (void)
|
||||||
"scm_init_instructions",
|
"scm_init_instructions",
|
||||||
(scm_t_extension_init_func)scm_init_instructions,
|
(scm_t_extension_init_func)scm_init_instructions,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
#define INIT(type) \
|
||||||
|
word_type_symbols[type] = scm_from_utf8_symbol (#type);
|
||||||
|
FOR_EACH_INSTRUCTION_WORD_TYPE (INIT)
|
||||||
|
#undef INIT
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
|
/* Copyright (C) 2001, 2009, 2012 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -20,6 +20,59 @@
|
||||||
#define _SCM_INSTRUCTIONS_H_
|
#define _SCM_INSTRUCTIONS_H_
|
||||||
|
|
||||||
#include <libguile.h>
|
#include <libguile.h>
|
||||||
|
#include <libguile/vm-operations.h>
|
||||||
|
|
||||||
|
enum scm_rtl_opcode
|
||||||
|
{
|
||||||
|
#define ENUM(opcode, tag, name, meta) scm_rtl_op_##tag = opcode,
|
||||||
|
FOR_EACH_VM_OPERATION(ENUM)
|
||||||
|
#undef ENUM
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SCM_PACK_RTL_8_8_8(op,a,b,c) ((op) | ((a) << 8) | ((b) << 16) | ((d) << 24))
|
||||||
|
#define SCM_PACK_RTL_8_16(op,a,b) ((op) | ((a) << 8) | ((b) << 16))
|
||||||
|
#define SCM_PACK_RTL_16_8(op,a,b) ((op) | ((a) << 16) | ((b) << 24))
|
||||||
|
#define SCM_PACK_RTL_24(op,a) ((op) | ((a) << 8))
|
||||||
|
|
||||||
|
#define SCM_UNPACK_RTL_8_8_8(op,a,b,c) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
a = (op >> 8) & 0xff; \
|
||||||
|
b = (op >> 16) & 0xff; \
|
||||||
|
c = op >> 24; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define SCM_UNPACK_RTL_8_16(op,a,b) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
a = (op >> 8) & 0xff; \
|
||||||
|
b = op >> 16; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define SCM_UNPACK_RTL_16_8(op,a,b) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
a = (op >> 8) & 0xffff; \
|
||||||
|
b = op >> 24; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define SCM_UNPACK_RTL_12_12(op,a,b) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
a = (op >> 8) & 0xfff; \
|
||||||
|
b = op >> 20; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define SCM_UNPACK_RTL_24(op,a) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
a = op >> 8; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
#define SCM_VM_NUM_INSTRUCTIONS (1<<8)
|
#define SCM_VM_NUM_INSTRUCTIONS (1<<8)
|
||||||
#define SCM_VM_INSTRUCTION_MASK (SCM_VM_NUM_INSTRUCTIONS-1)
|
#define SCM_VM_INSTRUCTION_MASK (SCM_VM_NUM_INSTRUCTIONS-1)
|
||||||
|
@ -33,6 +86,8 @@ enum scm_opcode {
|
||||||
#undef VM_INSTRUCTION_TO_OPCODE
|
#undef VM_INSTRUCTION_TO_OPCODE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SCM_INTERNAL SCM scm_rtl_instruction_list (void);
|
||||||
|
|
||||||
SCM_API SCM scm_instruction_list (void);
|
SCM_API SCM scm_instruction_list (void);
|
||||||
SCM_API SCM scm_instruction_p (SCM obj);
|
SCM_API SCM scm_instruction_p (SCM obj);
|
||||||
SCM_API SCM scm_instruction_length (SCM inst);
|
SCM_API SCM scm_instruction_length (SCM inst);
|
||||||
|
|
|
@ -94,7 +94,8 @@ static void register_elf (char *data, size_t len);
|
||||||
enum bytecode_kind
|
enum bytecode_kind
|
||||||
{
|
{
|
||||||
BYTECODE_KIND_NONE,
|
BYTECODE_KIND_NONE,
|
||||||
BYTECODE_KIND_GUILE_2_0
|
BYTECODE_KIND_GUILE_2_0,
|
||||||
|
BYTECODE_KIND_GUILE_2_2
|
||||||
};
|
};
|
||||||
|
|
||||||
static SCM
|
static SCM
|
||||||
|
@ -110,6 +111,10 @@ pointer_to_procedure (enum bytecode_kind bytecode_kind, char *ptr)
|
||||||
objcode = scm_double_cell (tag, (scm_t_bits) ptr, SCM_BOOL_F_BITS, 0);
|
objcode = scm_double_cell (tag, (scm_t_bits) ptr, SCM_BOOL_F_BITS, 0);
|
||||||
return scm_make_program (objcode, SCM_BOOL_F, SCM_UNDEFINED);
|
return scm_make_program (objcode, SCM_BOOL_F, SCM_UNDEFINED);
|
||||||
}
|
}
|
||||||
|
case BYTECODE_KIND_GUILE_2_2:
|
||||||
|
{
|
||||||
|
return scm_i_make_rtl_program ((scm_t_uint32 *) ptr);
|
||||||
|
}
|
||||||
case BYTECODE_KIND_NONE:
|
case BYTECODE_KIND_NONE:
|
||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
|
@ -302,29 +307,52 @@ process_dynamic_segment (char *base, Elf_Phdr *dyn_phdr,
|
||||||
{
|
{
|
||||||
scm_t_uint16 major = dyn[i].d_un.d_val >> 16;
|
scm_t_uint16 major = dyn[i].d_un.d_val >> 16;
|
||||||
scm_t_uint16 minor = dyn[i].d_un.d_val & 0xffff;
|
scm_t_uint16 minor = dyn[i].d_un.d_val & 0xffff;
|
||||||
if (major != 0x0200)
|
switch (major)
|
||||||
return "incompatible bytecode kind";
|
{
|
||||||
if (minor > SCM_OBJCODE_MINOR_VERSION)
|
case 0x0200:
|
||||||
return "incompatible bytecode version";
|
bytecode_kind = BYTECODE_KIND_GUILE_2_0;
|
||||||
bytecode_kind = BYTECODE_KIND_GUILE_2_0;
|
if (minor > SCM_OBJCODE_MINOR_VERSION)
|
||||||
|
return "incompatible bytecode version";
|
||||||
|
break;
|
||||||
|
case 0x0202:
|
||||||
|
bytecode_kind = BYTECODE_KIND_GUILE_2_2;
|
||||||
|
if (minor)
|
||||||
|
return "incompatible bytecode version";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return "incompatible bytecode kind";
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytecode_kind != BYTECODE_KIND_GUILE_2_0)
|
|
||||||
return "missing DT_GUILE_RTL_VERSION";
|
|
||||||
if (init)
|
|
||||||
return "unexpected DT_INIT";
|
|
||||||
if ((scm_t_uintptr) entry % 8)
|
|
||||||
return "unaligned DT_GUILE_ENTRY";
|
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return "missing DT_GUILE_ENTRY";
|
return "missing DT_GUILE_ENTRY";
|
||||||
|
|
||||||
|
switch (bytecode_kind)
|
||||||
|
{
|
||||||
|
case BYTECODE_KIND_GUILE_2_0:
|
||||||
|
if (init)
|
||||||
|
return "unexpected DT_INIT";
|
||||||
|
if ((scm_t_uintptr) entry % 8)
|
||||||
|
return "unaligned DT_GUILE_ENTRY";
|
||||||
|
break;
|
||||||
|
case BYTECODE_KIND_GUILE_2_2:
|
||||||
|
if ((scm_t_uintptr) init % 4)
|
||||||
|
return "unaligned DT_INIT";
|
||||||
|
if ((scm_t_uintptr) entry % 4)
|
||||||
|
return "unaligned DT_GUILE_ENTRY";
|
||||||
|
break;
|
||||||
|
case BYTECODE_KIND_NONE:
|
||||||
|
default:
|
||||||
|
return "missing DT_GUILE_RTL_VERSION";
|
||||||
|
}
|
||||||
|
|
||||||
if (gc_root)
|
if (gc_root)
|
||||||
GC_add_roots (gc_root, gc_root + gc_root_size);
|
GC_add_roots (gc_root, gc_root + gc_root_size);
|
||||||
|
|
||||||
*init_out = SCM_BOOL_F;
|
*init_out = init ? pointer_to_procedure (bytecode_kind, init) : SCM_BOOL_F;
|
||||||
*entry_out = pointer_to_procedure (bytecode_kind, entry);
|
*entry_out = pointer_to_procedure (bytecode_kind, entry);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -656,6 +656,9 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate)
|
||||||
case scm_tc7_variable:
|
case scm_tc7_variable:
|
||||||
scm_i_variable_print (exp, port, pstate);
|
scm_i_variable_print (exp, port, pstate);
|
||||||
break;
|
break;
|
||||||
|
case scm_tc7_rtl_program:
|
||||||
|
scm_i_rtl_program_print (exp, port, pstate);
|
||||||
|
break;
|
||||||
case scm_tc7_program:
|
case scm_tc7_program:
|
||||||
scm_i_program_print (exp, port, pstate);
|
scm_i_program_print (exp, port, pstate);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -80,6 +80,14 @@ scm_i_procedure_arity (SCM proc, int *req, int *opt, int *rest)
|
||||||
see. */
|
see. */
|
||||||
*req -= 1;
|
*req -= 1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (SCM_RTL_PROGRAM_P (proc))
|
||||||
|
{
|
||||||
|
*req = 0;
|
||||||
|
*opt = 0;
|
||||||
|
*rest = 1;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Copyright (C) 1995, 1996, 1997, 1999, 2000, 2001, 2006, 2008, 2009,
|
/* Copyright (C) 1995, 1996, 1997, 1999, 2000, 2001, 2006, 2008, 2009,
|
||||||
* 2010, 2011, 2012 Free Software Foundation, Inc.
|
* 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -48,6 +48,7 @@ SCM_DEFINE (scm_procedure_p, "procedure?", 1, 0, 0,
|
||||||
#define FUNC_NAME s_scm_procedure_p
|
#define FUNC_NAME s_scm_procedure_p
|
||||||
{
|
{
|
||||||
return scm_from_bool (SCM_PROGRAM_P (obj)
|
return scm_from_bool (SCM_PROGRAM_P (obj)
|
||||||
|
|| SCM_RTL_PROGRAM_P (obj)
|
||||||
|| (SCM_STRUCTP (obj) && SCM_STRUCT_APPLICABLE_P (obj))
|
|| (SCM_STRUCTP (obj) && SCM_STRUCT_APPLICABLE_P (obj))
|
||||||
|| (SCM_HAS_TYP7 (obj, scm_tc7_smob)
|
|| (SCM_HAS_TYP7 (obj, scm_tc7_smob)
|
||||||
&& SCM_SMOB_APPLICABLE_P (obj)));
|
&& SCM_SMOB_APPLICABLE_P (obj)));
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001, 2009, 2010, 2011 Free Software Foundation, Inc.
|
/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -69,6 +69,58 @@ SCM_DEFINE (scm_make_program, "make-program", 1, 2, 0,
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
SCM_DEFINE (scm_make_rtl_program, "make-rtl-program", 1, 2, 0,
|
||||||
|
(SCM bytevector, SCM byte_offset, SCM free_variables),
|
||||||
|
"")
|
||||||
|
#define FUNC_NAME s_scm_make_rtl_program
|
||||||
|
{
|
||||||
|
scm_t_uint8 *code;
|
||||||
|
scm_t_uint32 offset;
|
||||||
|
|
||||||
|
if (!scm_is_bytevector (bytevector))
|
||||||
|
scm_wrong_type_arg (FUNC_NAME, 1, bytevector);
|
||||||
|
if (SCM_UNBNDP (byte_offset))
|
||||||
|
offset = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset = scm_to_uint32 (byte_offset);
|
||||||
|
if (offset > SCM_BYTEVECTOR_LENGTH (bytevector))
|
||||||
|
SCM_OUT_OF_RANGE (2, byte_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
code = (scm_t_uint8*) SCM_BYTEVECTOR_CONTENTS (bytevector) + offset;
|
||||||
|
if (((scm_t_uintptr) code) % 4)
|
||||||
|
SCM_OUT_OF_RANGE (2, byte_offset);
|
||||||
|
|
||||||
|
if (SCM_UNBNDP (free_variables) || scm_is_false (free_variables))
|
||||||
|
return scm_cell (scm_tc7_rtl_program, (scm_t_bits) code);
|
||||||
|
else
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
SCM_DEFINE (scm_rtl_program_code, "rtl-program-code", 1, 0, 0,
|
||||||
|
(SCM program),
|
||||||
|
"")
|
||||||
|
#define FUNC_NAME s_scm_rtl_program_code
|
||||||
|
{
|
||||||
|
SCM_VALIDATE_RTL_PROGRAM (1, program);
|
||||||
|
|
||||||
|
/* FIXME: we need scm_from_uintptr (). */
|
||||||
|
return scm_from_size_t ((size_t) SCM_RTL_PROGRAM_CODE (program));
|
||||||
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
void
|
||||||
|
scm_i_rtl_program_print (SCM program, SCM port, scm_print_state *pstate)
|
||||||
|
{
|
||||||
|
scm_puts_unlocked ("#<rtl-program ", port);
|
||||||
|
scm_uintprint (SCM_UNPACK (program), 16, port);
|
||||||
|
scm_putc_unlocked (' ', port);
|
||||||
|
scm_uintprint ((scm_t_uintptr) SCM_RTL_PROGRAM_CODE (program), 16, port);
|
||||||
|
scm_putc_unlocked ('>', port);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
scm_i_program_print (SCM program, SCM port, scm_print_state *pstate)
|
scm_i_program_print (SCM program, SCM port, scm_print_state *pstate)
|
||||||
{
|
{
|
||||||
|
@ -121,6 +173,15 @@ SCM_DEFINE (scm_program_p, "program?", 1, 0, 0,
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
SCM_DEFINE (scm_rtl_program_p, "rtl-program?", 1, 0, 0,
|
||||||
|
(SCM obj),
|
||||||
|
"")
|
||||||
|
#define FUNC_NAME s_scm_rtl_program_p
|
||||||
|
{
|
||||||
|
return scm_from_bool (SCM_RTL_PROGRAM_P (obj));
|
||||||
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
SCM_DEFINE (scm_program_base, "program-base", 1, 0, 0,
|
SCM_DEFINE (scm_program_base, "program-base", 1, 0, 0,
|
||||||
(SCM program),
|
(SCM program),
|
||||||
"")
|
"")
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2001, 2009, 2010, 2011 Free Software Foundation, Inc.
|
/* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public License
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
@ -22,6 +22,31 @@
|
||||||
#include <libguile.h>
|
#include <libguile.h>
|
||||||
#include <libguile/objcodes.h>
|
#include <libguile/objcodes.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The new RTL programs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SCM_RTL_PROGRAM_P(x) (SCM_HAS_TYP7 (x, scm_tc7_rtl_program))
|
||||||
|
#define SCM_RTL_PROGRAM_CODE(x) ((scm_t_uint32 *) SCM_CELL_WORD_1 (x))
|
||||||
|
#define SCM_RTL_PROGRAM_FREE_VARIABLES(x) (SCM_CELL_OBJECT_LOC (x, 2))
|
||||||
|
#define SCM_RTL_PROGRAM_FREE_VARIABLE_REF(x,i) (SCM_RTL_PROGRAM_FREE_VARIABLES (x)[i])
|
||||||
|
#define SCM_RTL_PROGRAM_FREE_VARIABLE_SET(x,i,v) (SCM_RTL_PROGRAM_FREE_VARIABLES (x)[i]=(v))
|
||||||
|
#define SCM_RTL_PROGRAM_NUM_FREE_VARIABLES(x) (SCM_CELL_WORD_0 (x) >> 16)
|
||||||
|
#define SCM_VALIDATE_RTL_PROGRAM(p,x) SCM_MAKE_VALIDATE (p, x, RTL_PROGRAM_P)
|
||||||
|
|
||||||
|
static inline SCM
|
||||||
|
scm_i_make_rtl_program (const scm_t_uint32 *code)
|
||||||
|
{
|
||||||
|
return scm_cell (scm_tc7_rtl_program, (scm_t_bits)code);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCM_INTERNAL SCM scm_make_rtl_program (SCM bytevector, SCM byte_offset, SCM free_variables);
|
||||||
|
SCM_INTERNAL SCM scm_rtl_program_p (SCM obj);
|
||||||
|
SCM_INTERNAL SCM scm_rtl_program_code (SCM program);
|
||||||
|
|
||||||
|
SCM_INTERNAL void scm_i_rtl_program_print (SCM program, SCM port,
|
||||||
|
scm_print_state *pstate);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Programs
|
* Programs
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -425,7 +425,7 @@ typedef union SCM { struct { scm_t_bits n; } n; } SCM;
|
||||||
|
|
||||||
#define scm_tc7_unused_17 61
|
#define scm_tc7_unused_17 61
|
||||||
#define scm_tc7_unused_21 63
|
#define scm_tc7_unused_21 63
|
||||||
#define scm_tc7_unused_19 69
|
#define scm_tc7_rtl_program 69
|
||||||
#define scm_tc7_program 79
|
#define scm_tc7_program 79
|
||||||
#define scm_tc7_weak_set 85
|
#define scm_tc7_weak_set 85
|
||||||
#define scm_tc7_weak_table 87
|
#define scm_tc7_weak_table 87
|
||||||
|
|
3170
libguile/vm-engine.c
3170
libguile/vm-engine.c
File diff suppressed because it is too large
Load diff
|
@ -594,6 +594,30 @@ vm_error_bad_wide_string_length (size_t len)
|
||||||
|
|
||||||
static SCM boot_continuation;
|
static SCM boot_continuation;
|
||||||
|
|
||||||
|
static SCM rtl_boot_continuation;
|
||||||
|
static SCM rtl_apply;
|
||||||
|
static SCM rtl_values;
|
||||||
|
|
||||||
|
static const scm_t_uint32 rtl_boot_continuation_code[] = {
|
||||||
|
SCM_PACK_RTL_24 (scm_rtl_op_halt_values, 0), /* empty stack frame in r0-r2, results from r3 */
|
||||||
|
SCM_PACK_RTL_24 (scm_rtl_op_halt, 0) /* result in r0 */
|
||||||
|
};
|
||||||
|
|
||||||
|
static scm_t_uint32* rtl_boot_multiple_value_continuation_code =
|
||||||
|
(scm_t_uint32 *) rtl_boot_continuation_code;
|
||||||
|
|
||||||
|
static scm_t_uint32* rtl_boot_single_value_continuation_code =
|
||||||
|
(scm_t_uint32 *) rtl_boot_continuation_code + 1;
|
||||||
|
|
||||||
|
static const scm_t_uint32 rtl_apply_code[] = {
|
||||||
|
SCM_PACK_RTL_24 (scm_rtl_op_apply, 0) /* proc in r0, args from r1, nargs set */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const scm_t_uint32 rtl_values_code[] = {
|
||||||
|
SCM_PACK_RTL_24 (scm_rtl_op_values, 0) /* vals from r0 */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* VM
|
* VM
|
||||||
|
@ -637,18 +661,22 @@ initialize_default_stack_size (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VM_NAME vm_regular_engine
|
#define VM_NAME vm_regular_engine
|
||||||
|
#define RTL_VM_NAME rtl_vm_regular_engine
|
||||||
#define FUNC_NAME "vm-regular-engine"
|
#define FUNC_NAME "vm-regular-engine"
|
||||||
#define VM_ENGINE SCM_VM_REGULAR_ENGINE
|
#define VM_ENGINE SCM_VM_REGULAR_ENGINE
|
||||||
#include "vm-engine.c"
|
#include "vm-engine.c"
|
||||||
#undef VM_NAME
|
#undef VM_NAME
|
||||||
|
#undef RTL_VM_NAME
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
#undef VM_ENGINE
|
#undef VM_ENGINE
|
||||||
|
|
||||||
#define VM_NAME vm_debug_engine
|
#define VM_NAME vm_debug_engine
|
||||||
|
#define RTL_VM_NAME rtl_vm_debug_engine
|
||||||
#define FUNC_NAME "vm-debug-engine"
|
#define FUNC_NAME "vm-debug-engine"
|
||||||
#define VM_ENGINE SCM_VM_DEBUG_ENGINE
|
#define VM_ENGINE SCM_VM_DEBUG_ENGINE
|
||||||
#include "vm-engine.c"
|
#include "vm-engine.c"
|
||||||
#undef VM_NAME
|
#undef VM_NAME
|
||||||
|
#undef RTL_VM_NAME
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
#undef VM_ENGINE
|
#undef VM_ENGINE
|
||||||
|
|
||||||
|
@ -1110,6 +1138,10 @@ scm_init_vm (void)
|
||||||
#ifndef SCM_MAGIC_SNARFER
|
#ifndef SCM_MAGIC_SNARFER
|
||||||
#include "libguile/vm.x"
|
#include "libguile/vm.x"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
rtl_boot_continuation = scm_i_make_rtl_program (rtl_boot_continuation_code);
|
||||||
|
rtl_apply = scm_i_make_rtl_program (rtl_apply_code);
|
||||||
|
rtl_values = scm_i_make_rtl_program (rtl_values_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
;;; Guile VM instructions
|
;;; Guile VM instructions
|
||||||
|
|
||||||
;; Copyright (C) 2001, 2010 Free Software Foundation, Inc.
|
;; Copyright (C) 2001, 2010, 2012 Free Software Foundation, Inc.
|
||||||
|
|
||||||
;;; This library is free software; you can redistribute it and/or
|
;;; This library is free software; you can redistribute it and/or
|
||||||
;;; modify it under the terms of the GNU Lesser General Public
|
;;; modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -19,7 +19,8 @@
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
(define-module (system vm instruction)
|
(define-module (system vm instruction)
|
||||||
#:export (instruction-list
|
#:export (rtl-instruction-list
|
||||||
|
instruction-list
|
||||||
instruction? instruction-length
|
instruction? instruction-length
|
||||||
instruction-pops instruction-pushes
|
instruction-pops instruction-pushes
|
||||||
instruction->opcode opcode->instruction))
|
instruction->opcode opcode->instruction))
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
#:use-module (srfi srfi-26)
|
#:use-module (srfi srfi-26)
|
||||||
#:export (make-program
|
#:export (make-program
|
||||||
|
make-rtl-program
|
||||||
|
|
||||||
make-binding binding:name binding:boxed? binding:index
|
make-binding binding:name binding:boxed? binding:index
|
||||||
binding:start binding:end
|
binding:start binding:end
|
||||||
|
@ -43,6 +44,7 @@
|
||||||
|
|
||||||
program-meta
|
program-meta
|
||||||
program-objcode program? program-objects
|
program-objcode program? program-objects
|
||||||
|
rtl-program? rtl-program-code
|
||||||
program-module program-base
|
program-module program-base
|
||||||
program-free-variables
|
program-free-variables
|
||||||
program-num-free-variables
|
program-num-free-variables
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue