instructions.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
  2. *
  3. * This library is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU Lesser General Public License
  5. * as published by the Free Software Foundation; either version 3 of
  6. * the License, or (at your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public
  14. * License along with this library; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. * 02110-1301 USA
  17. */
  18. #if HAVE_CONFIG_H
  19. # include <config.h>
  20. #endif
  21. #include <string.h>
  22. #include "_scm.h"
  23. #include "vm-bootstrap.h"
  24. #include "instructions.h"
  25. struct scm_instruction {
  26. enum scm_opcode opcode; /* opcode */
  27. const char *name; /* instruction name */
  28. signed char len; /* Instruction length. This may be -1 for
  29. the loader (see the `VM_LOADER'
  30. macro). */
  31. signed char npop; /* The number of values popped. This may be
  32. -1 for insns like `call' which can take
  33. any number of arguments. */
  34. char npush; /* the number of values pushed */
  35. SCM symname; /* filled in later */
  36. };
  37. #define SCM_VALIDATE_LOOKUP_INSTRUCTION(pos, var, cvar) \
  38. do { \
  39. cvar = scm_lookup_instruction_by_name (var); \
  40. SCM_ASSERT_TYPE (cvar, var, pos, FUNC_NAME, "INSTRUCTION_P"); \
  41. } while (0)
  42. static struct scm_instruction*
  43. fetch_instruction_table ()
  44. {
  45. static struct scm_instruction *table = NULL;
  46. if (SCM_UNLIKELY (!table))
  47. {
  48. size_t bytes = SCM_VM_NUM_INSTRUCTIONS * sizeof(struct scm_instruction);
  49. int i;
  50. table = malloc (bytes);
  51. memset (table, 0, bytes);
  52. #define VM_INSTRUCTION_TO_TABLE 1
  53. #include <libguile/vm-expand.h>
  54. #include <libguile/vm-i-system.i>
  55. #include <libguile/vm-i-scheme.i>
  56. #include <libguile/vm-i-loader.i>
  57. #undef VM_INSTRUCTION_TO_TABLE
  58. for (i = 0; i < SCM_VM_NUM_INSTRUCTIONS; i++)
  59. {
  60. table[i].opcode = i;
  61. if (table[i].name)
  62. table[i].symname =
  63. scm_permanent_object (scm_from_locale_symbol (table[i].name));
  64. else
  65. table[i].symname = SCM_BOOL_F;
  66. }
  67. }
  68. return table;
  69. }
  70. static struct scm_instruction *
  71. scm_lookup_instruction_by_name (SCM name)
  72. {
  73. static SCM instructions_by_name = SCM_BOOL_F;
  74. struct scm_instruction *table = fetch_instruction_table ();
  75. SCM op;
  76. if (SCM_UNLIKELY (SCM_FALSEP (instructions_by_name)))
  77. {
  78. int i;
  79. instructions_by_name = scm_permanent_object
  80. (scm_make_hash_table (SCM_I_MAKINUM (SCM_VM_NUM_INSTRUCTIONS)));
  81. for (i = 0; i < SCM_VM_NUM_INSTRUCTIONS; i++)
  82. if (scm_is_true (table[i].symname))
  83. scm_hashq_set_x (instructions_by_name, table[i].symname,
  84. SCM_I_MAKINUM (i));
  85. }
  86. op = scm_hashq_ref (instructions_by_name, name, SCM_UNDEFINED);
  87. if (SCM_I_INUMP (op))
  88. return &table[SCM_I_INUM (op)];
  89. return NULL;
  90. }
  91. /* Scheme interface */
  92. SCM_DEFINE (scm_instruction_list, "instruction-list", 0, 0, 0,
  93. (void),
  94. "")
  95. #define FUNC_NAME s_scm_instruction_list
  96. {
  97. SCM list = SCM_EOL;
  98. int i;
  99. struct scm_instruction *ip = fetch_instruction_table ();
  100. for (i = 0; i < SCM_VM_NUM_INSTRUCTIONS; i++)
  101. if (ip[i].name)
  102. list = scm_cons (ip[i].symname, list);
  103. return scm_reverse_x (list, SCM_EOL);
  104. }
  105. #undef FUNC_NAME
  106. SCM_DEFINE (scm_instruction_p, "instruction?", 1, 0, 0,
  107. (SCM obj),
  108. "")
  109. #define FUNC_NAME s_scm_instruction_p
  110. {
  111. return SCM_BOOL (scm_lookup_instruction_by_name (obj));
  112. }
  113. #undef FUNC_NAME
  114. SCM_DEFINE (scm_instruction_length, "instruction-length", 1, 0, 0,
  115. (SCM inst),
  116. "")
  117. #define FUNC_NAME s_scm_instruction_length
  118. {
  119. struct scm_instruction *ip;
  120. SCM_VALIDATE_LOOKUP_INSTRUCTION (1, inst, ip);
  121. return SCM_I_MAKINUM (ip->len);
  122. }
  123. #undef FUNC_NAME
  124. SCM_DEFINE (scm_instruction_pops, "instruction-pops", 1, 0, 0,
  125. (SCM inst),
  126. "")
  127. #define FUNC_NAME s_scm_instruction_pops
  128. {
  129. struct scm_instruction *ip;
  130. SCM_VALIDATE_LOOKUP_INSTRUCTION (1, inst, ip);
  131. return SCM_I_MAKINUM (ip->npop);
  132. }
  133. #undef FUNC_NAME
  134. SCM_DEFINE (scm_instruction_pushes, "instruction-pushes", 1, 0, 0,
  135. (SCM inst),
  136. "")
  137. #define FUNC_NAME s_scm_instruction_pushes
  138. {
  139. struct scm_instruction *ip;
  140. SCM_VALIDATE_LOOKUP_INSTRUCTION (1, inst, ip);
  141. return SCM_I_MAKINUM (ip->npush);
  142. }
  143. #undef FUNC_NAME
  144. SCM_DEFINE (scm_instruction_to_opcode, "instruction->opcode", 1, 0, 0,
  145. (SCM inst),
  146. "")
  147. #define FUNC_NAME s_scm_instruction_to_opcode
  148. {
  149. struct scm_instruction *ip;
  150. SCM_VALIDATE_LOOKUP_INSTRUCTION (1, inst, ip);
  151. return SCM_I_MAKINUM (ip->opcode);
  152. }
  153. #undef FUNC_NAME
  154. SCM_DEFINE (scm_opcode_to_instruction, "opcode->instruction", 1, 0, 0,
  155. (SCM op),
  156. "")
  157. #define FUNC_NAME s_scm_opcode_to_instruction
  158. {
  159. int opcode;
  160. SCM ret = SCM_BOOL_F;
  161. SCM_MAKE_VALIDATE (1, op, I_INUMP);
  162. opcode = SCM_I_INUM (op);
  163. if (opcode >= 0 && opcode < SCM_VM_NUM_INSTRUCTIONS)
  164. ret = fetch_instruction_table ()[opcode].symname;
  165. if (scm_is_false (ret))
  166. scm_wrong_type_arg_msg (FUNC_NAME, 1, op, "INSTRUCTION_P");
  167. return ret;
  168. }
  169. #undef FUNC_NAME
  170. void
  171. scm_bootstrap_instructions (void)
  172. {
  173. scm_c_register_extension ("libguile", "scm_init_instructions",
  174. (scm_t_extension_init_func)scm_init_instructions,
  175. NULL);
  176. }
  177. void
  178. scm_init_instructions (void)
  179. {
  180. scm_bootstrap_vm ();
  181. #ifndef SCM_MAGIC_SNARFER
  182. #include "libguile/instructions.x"
  183. #endif
  184. }
  185. /*
  186. Local Variables:
  187. c-file-style: "gnu"
  188. End:
  189. */