c-vector.scm 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Timo Harter
  3. ; (make-vector size init)
  4. (define-c-generator make-vector #t
  5. (lambda (call port indent)
  6. (let ((type (node-type call)))
  7. (write-c-coercion type port)
  8. (format port "malloc(sizeof(")
  9. (display-c-type (pointer-type-to type) #f port)
  10. (format port ") * ")
  11. (c-value (call-arg call 0) port)
  12. (format port ")"))))
  13. (define-c-generator vector-ref #t
  14. (lambda (call port indent)
  15. (generate-c-vector-ref (call-arg call 0) (call-arg call 1) port)))
  16. (define (generate-c-vector-ref vector index port)
  17. (display "*(" port)
  18. (c-value vector port)
  19. (display " + " port)
  20. (c-value index port)
  21. (writec port #\)))
  22. (define-c-generator vector-set! #t
  23. (lambda (call port indent)
  24. (generate-c-vector-set (call-arg call 1)
  25. (call-arg call 2)
  26. (call-arg call 3)
  27. port indent)))
  28. (define (generate-c-vector-set vector index value port indent)
  29. (indent-to port indent)
  30. (generate-c-vector-ref vector index port)
  31. (display " = " port)
  32. (c-value value port)
  33. (writec port #\;))
  34. (define-c-generator make-string #t
  35. (lambda (call port indent)
  36. ; calloc is used as a hack to get a zero at the end
  37. (format port "(char *)calloc( 1, 1 + ")
  38. (c-value (call-arg call 0) port)
  39. (format port ")")))
  40. (define-c-generator string-length #t
  41. (lambda (call port indent)
  42. (format port "strlen((char *) ")
  43. (c-value (call-arg call 0) port)
  44. (format port ")")))
  45. (define-c-generator string-ref #t
  46. (lambda (call port indent)
  47. (generate-c-vector-ref (call-arg call 0) (call-arg call 1) port)))
  48. (define-c-generator string-set! #f
  49. (lambda (call port indent)
  50. (generate-c-vector-set (call-arg call 1)
  51. (call-arg call 2)
  52. (call-arg call 3)
  53. port indent)))
  54. (define-c-generator make-record #f
  55. (lambda (call port indent)
  56. (let ((type (get-record-type (literal-value (call-arg call 0)))))
  57. (write-c-coercion (make-pointer-type type) port)
  58. (format port "malloc(sizeof(struct ")
  59. (write-c-identifier (record-type-name type) port)
  60. (format port "))"))))
  61. (define-c-generator record-ref #t
  62. (lambda (call port indent)
  63. (generate-c-record-ref (call-arg call 0)
  64. (call-arg call 1)
  65. (call-arg call 2)
  66. port)))
  67. (define (generate-c-record-ref record type field port)
  68. (let ((field (get-record-type-field (literal-value type)
  69. (literal-value field))))
  70. (c-value record port)
  71. (display "->" port)
  72. (write-c-identifier (record-field-name field) port)))
  73. (define-c-generator record-set! #t
  74. (lambda (call port indent)
  75. (generate-c-record-set (call-arg call 1)
  76. (call-arg call 2)
  77. (call-arg call 3)
  78. (call-arg call 4)
  79. port indent)))
  80. (define (generate-c-record-set record value type field port indent)
  81. (indent-to port indent)
  82. (generate-c-record-ref record type field port)
  83. (display " = " port)
  84. (c-value value port)
  85. (writec port #\;))
  86. (define-c-generator allocate-memory #t
  87. (lambda (call port indent)
  88. (write-c-coercion type/address port)
  89. (format port "malloc(")
  90. (c-value (call-arg call 0) port)
  91. (format port ")")))
  92. (define-c-generator deallocate #t
  93. (lambda (call port indent)
  94. (format port "free(")
  95. (c-value (call-arg call 0) port)
  96. (format port ")")))
  97. (define-c-generator deallocate-memory #t
  98. (lambda (call port indent)
  99. (format port "free(")
  100. (c-value (call-arg call 0) port)
  101. (format port ")")))
  102. (define-c-generator address+ #t
  103. (lambda (call port indent)
  104. (simple-c-primop "+" call port)))
  105. (define-c-generator address-difference #t
  106. (lambda (call port indent)
  107. (simple-c-primop "-" call port)))
  108. (define-c-generator address= #t
  109. (lambda (call port indent)
  110. (simple-c-primop "==" call port)))
  111. (define-c-generator address< #t
  112. (lambda (call port indent)
  113. (simple-c-primop "<" call port)))
  114. (define-c-generator address->integer #t
  115. (lambda (call port indent)
  116. (format port "((long) ")
  117. (c-value (call-arg call 0) port)
  118. (format port ")")))
  119. (define-c-generator integer->address #t
  120. (lambda (call port indent)
  121. (format port "((char *) ")
  122. (c-value (call-arg call 0) port)
  123. (format port ")")))
  124. (define-c-generator copy-memory! #t
  125. (lambda (call port indent)
  126. (format port "memmove((void *)")
  127. (c-value (call-arg call 1) port)
  128. (format port ", (void *)")
  129. (c-value (call-arg call 0) port)
  130. (format port ",")
  131. (c-value (call-arg call 2) port)
  132. (format port ")")))
  133. (define-c-generator memory-equal? #t
  134. (lambda (call port indent)
  135. (format port "(!memcmp((void *)")
  136. (c-value (call-arg call 1) port)
  137. (format port ", (void *)")
  138. (c-value (call-arg call 0) port)
  139. (format port ",")
  140. (c-value (call-arg call 2) port)
  141. (format port "))")))
  142. (define-c-generator byte-ref #t
  143. (lambda (call port indent)
  144. (generate-c-memory-ref "unsigned char" (call-arg call 0) port)))
  145. (define-c-generator word-ref #t
  146. (lambda (call port indent)
  147. (generate-c-memory-ref "long" (call-arg call 0) port)))
  148. (define-c-generator flonum-ref #t
  149. (lambda (call port indent)
  150. (generate-c-memory-ref "double" (call-arg call 0) port)))
  151. (define (generate-c-memory-ref type pointer port)
  152. (format port "*((~A *) " type)
  153. (c-value pointer port)
  154. (writec port #\)))
  155. (define-c-generator byte-set! #t
  156. (lambda (call port indent)
  157. (generate-c-memory-set! "unsigned char"
  158. (call-arg call 1)
  159. (call-arg call 2)
  160. port
  161. indent)))
  162. (define-c-generator word-set! #t
  163. (lambda (call port indent)
  164. (generate-c-memory-set! "long"
  165. (call-arg call 1)
  166. (call-arg call 2)
  167. port
  168. indent)))
  169. (define-c-generator flonum-set! #t
  170. (lambda (call port indent)
  171. (generate-c-memory-set! "double"
  172. (call-arg call 1)
  173. (call-arg call 2)
  174. port
  175. indent)))
  176. (define (generate-c-memory-set! type pointer value port indent)
  177. (indent-to port indent)
  178. (generate-c-memory-ref type pointer port)
  179. (display " = " port)
  180. (format port "(~A) (" type)
  181. (c-value value port)
  182. (writec port #\))
  183. (writec port #\;))
  184. (define-c-generator char-pointer->string #t
  185. (lambda (call port indent)
  186. (format port "((char *)")
  187. (c-value (call-arg call 0) port)
  188. (format port ")")))
  189. (define-c-generator char-pointer->nul-terminated-string #t
  190. (lambda (call port indent)
  191. (format port "((char *)")
  192. (c-value (call-arg call 0) port)
  193. (format port ")")))
  194. (define-c-generator computed-goto #f
  195. (lambda (call port indent)
  196. (generate-c-switch call port indent)))
  197. (define (generate-c-switch call port indent)
  198. (let ((size (call-exits call))
  199. (parent-id (lambda-id (node-parent call))))
  200. (display "\n#ifdef USE_DIRECT_THREADING\n" port)
  201. (write-goto-jump-table call port indent)
  202. (indent-to port indent)
  203. (format port "goto *Jtable~D[" parent-id)
  204. (c-value (call-arg call (+ size 1)) port)
  205. (display "];\n#else\n" port)
  206. (indent-to port indent)
  207. (display "switch (" port)
  208. (c-value (call-arg call (+ size 1)) port)
  209. (display ") {\n#endif\n" port)
  210. (let ((indent (+ indent 2)))
  211. (do ((i 0 (+ i 1))
  212. (labels (literal-value (call-arg call size)) (cdr labels)))
  213. ((>= i size))
  214. (display "\n#ifdef USE_DIRECT_THREADING" port)
  215. (for-each (lambda (l)
  216. (format port "\nJlabel~D_~D:" parent-id l))
  217. (car labels))
  218. (display "\n#else\n" port)
  219. (for-each (lambda (l)
  220. (indent-to port indent)
  221. (format port "case ~D : " l))
  222. (car labels))
  223. (display "\n#endif\n" port)
  224. (write-c-switch-case (call-arg call i) port indent)))
  225. (display "\n#ifndef USE_DIRECT_THREADING\n" port)
  226. (indent-to port indent)
  227. (display "}" port)
  228. (display "\n#endif\n" port)))
  229. (define (write-c-switch-case node port indent)
  230. (indent-to port (+ indent 2))
  231. (writec port #\{)
  232. (write-c-block (lambda-body node) port (+ indent 2))
  233. (display "\n#ifndef USE_DIRECT_THREADING\n" port)
  234. (indent-to port (+ indent 2))
  235. (display "break;\n#endif\n" port))
  236. (define (write-goto-jump-table call port indent)
  237. (let ((size (call-exits call))
  238. (parent-id (lambda-id (node-parent call))) ; use the id of the parent lambda to identify this computed-goto
  239. (max-value 0)) ; find the highest case value in the computed goto
  240. (for-each
  241. (lambda (labels)
  242. (for-each
  243. (lambda (l) (if (> l max-value) (set! max-value l)))
  244. labels))
  245. (literal-value (call-arg call size)))
  246. (indent-to port indent)
  247. (format port "static void *Jtable~D[] = { " parent-id)
  248. (do ((i 0 (+ i 1))) ((>= i max-value))
  249. (format port "&&Jlabel~D_~D, " parent-id i)
  250. (if (equal? 0 (modulo i 6)) ; make the output more readable
  251. (indent-to port (+ indent 2))))
  252. (format port "&&Jlabel~D_~D };" parent-id max-value)))