assembler.scm 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. (define (scan-1 code place lbls)
  2. ;; scan-1 is the first pass of the assembler
  3. ;;
  4. ;; it flattens the list of lists (instructions are short lists)
  5. ;; into one long list.
  6. ;;
  7. ;; it also looks for labels, erasing them from the output but
  8. ;; noting their positions
  9. ;;
  10. ;; (label <lbl>)
  11. ;;
  12. (if (null? code)
  13. #t
  14. (let ((inst (car code))
  15. (rest (cdr code)))
  16. (if (label? inst)
  17. (begin
  18. (stack-push! lbls (cons (label-get-name inst) place))
  19. (scan-1 rest
  20. place
  21. lbls))
  22. (scan-1 rest
  23. (+ place (length inst))
  24. lbls)))))
  25. (define (resolve-label place lbl lbls)
  26. (cond ((assoc lbl (stack-get lbls)) =>
  27. (lambda (entry)
  28. (- (cdr entry) place)))
  29. (else (error 'resolve-label "couldn't find label" 0))))
  30. (define (mad-helper inst place lbls)
  31. (cond ((branch? inst)
  32. `(branch ,(resolve-label place (branch-get-label inst) lbls)))
  33. ((jump? inst)
  34. `(jump ,(resolve-label place (jump-get-label inst) lbls)))
  35. ((stackframe? inst)
  36. `(stackframe ,(resolve-label place (stackframe-get-label inst) lbls)))
  37. ((allocate-closure? inst)
  38. `(allocate-closure
  39. ,(allocate-closure-get-size inst)
  40. ,(resolve-label place (allocate-closure-get-label inst) lbls)))
  41. ((information? inst)
  42. `(information ,(resolve-label place (information-get-label inst) lbls)
  43. ,(information-get-info inst)))
  44. (else inst)))
  45. (define (scan-2 code place lbls)
  46. ;; scan-2 is the second pass
  47. ;;
  48. ;; it looks for certain special forms that reference
  49. ;; labels, and replaces the label reference with a
  50. ;; relative offset
  51. ;;
  52. ;; (branch <lbl>)
  53. ;; (jump <lbl>)
  54. ;; (stackframe <lbl>)
  55. ;; (allocate-closure <size> <lbl>)
  56. ;;
  57. (if (null? code)
  58. '()
  59. (let ((inst (car code))
  60. (rest (cdr code)))
  61. (if (label? inst)
  62. (scan-2 rest place lbls)
  63. (let ((place (+ place (length inst))))
  64. (append (mad-helper inst place lbls)
  65. (scan-2 rest
  66. place
  67. lbls)))))))
  68. (define (assemble code)
  69. ;; lbls is an assoc list about label definitions
  70. ;; the entries are:
  71. ;; (<label-name> . <label-position>)
  72. ;;
  73. ;; lbl-refs is a queue about label uses
  74. ;; the entries are:
  75. ;; (<label-name> . <position>)
  76. ;;
  77. (let* ((lbls (empty-stack)))
  78. (scan-1 code 0 lbls)
  79. (scan-2 code 0 lbls)))