c-vector.scm 9.3 KB

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