rd-size endianness constants inits shstrtab next-section-number meta sources slot-maps) asm? ;; We write bytecode into a bytevector, growing the bytevector as ;; needed. asm-cur is that bytevector, and asm-pos is the byte offset ;; into the vector at which the next word should be written. ;; (buf asm-buf set-asm-buf!) (pos asm-pos set-asm-pos!) ;; asm-start is an absolute position, indicating the byte offset of ;; the beginning of an instruction. It is updated after writing all ;; the words for one primitive instruction. It models the position of ;; the instruction pointer during execution, given that the VM updates ;; the IP only at the end of executing the instruction, and is thus ;; useful for computing offsets between two points in a program. ;; (start asm-start set-asm-start!) ;; An alist of symbol -> position pairs, indicating the labels defined ;; in this compilation unit. ;; (labels asm-labels set-asm-labels!) ;; A list of relocations needed by the program text. We use an ;; internal representation for relocations, and handle textualn ;; relative relocations in the assembler. Other kinds of relocations ;; are later reified as linker relocations and resolved by the linker. ;; (relocs asm-relocs set-asm-relocs!) ;; Target information. ;; (word-size asm-word-size) (endianness asm-endianness) ;; The constant table, as a vhash of object -> label. All constants ;; get de-duplicated and written into separate sections -- either the ;; .rodata section, for read-only data, or .data, for constants that ;; need initialization at load-time (like symbols). Constants can ;; depend on other constants (e.g. a symbol depending on a stringbuf), ;; so order in this table is important. ;; (constants asm-constants set-asm-constants!) ;; A list of instructions needed to initialize the constants. Will ;; run in a thunk with 2 local variables. ;; (inits asm-inits set-asm-inits!) ;; The shstrtab, for section names. ;; (shstrtab asm-shstrtab set-asm-shstrtab!) ;; The section number for the next section to be written. ;; (next-section-number asm-next-section-number set-asm-next-section-number!) ;; A list of , corresponding to procedure metadata. ;; (meta asm-meta set-asm-meta!) ;; A list of (pos . source) pairs, indicating source information. POS ;; is relative to the beginning of the text section, and SOURCE is in ;; the same format that source-properties returns. ;; (sources asm-sources set-asm-sources!) ;; A list of (pos . slot-map) pairs, indicating slot maps. POS is ;; relative to the beginning of the text section. SLOT-MAP is a ;; bitfield describing the stack at call sites, as an integer. ;; (slot-maps asm-slot-maps set-asm-slot-maps!)) (define* (make-assembler #:key (word-size (target-word-size)) (endianness (target-endianness))) "Create an assembler for a given target @var{word-size} and @var{endianness}, falling back to appropriate values for the configured target." (make-asm (make-u32vector 1000) 0 0 (make-hash-table) '() word-size endianness vlist-null '() (make-string-table) 1 '() '() '())) (define (intern-section-name! asm string) "Add a string to the section name table (shstrtab)." (string-table-intern! (asm-shstrtab asm) string)) (define (grow-buffer! asm) "Grow the code buffer of the asm." (let* ((buf (asm-buf asm)) (len (bytevector-length buf)) (new (make-u32vector (ash len -1) 0))) (bytevector-copy! buf 0 new 0 len) (set-asm-buf! asm new) #f)) (define-inline (emit asm u32) "Emit one 32-bit word into the instruction stream. Assumes that there is space for the word." (bytevector-u32-native-set! (asm-buf asm) (asm-pos asm) u32) (set-asm-pos! asm (+ (asm-pos asm) 4))) (define-inline (make-reloc type label base word) "Make an internal relocation of type @var{type} referencing symbol @var{label}, @var{word} words after position @var{start}. @var{type} may be x8-s24, indicating a 24-bit relative label reference that can be fixed up by the assembler, or s32, indicating a 32-bit relative reference that needs to be fixed up by the linker." (list type label base word)) (define-inline (reset-asm-start! asm) "Reset the asm-start after writing the words for one instruction." (set-asm-start! asm (asm-pos asm))) (define (record-label-reference asm label) "Record an x8-s24 local label reference. This value will get patched up later by the assembler." (let* ((start (asm-start asm)) (pos (asm-pos asm)) (reloc (make-reloc 'x8-s24 label start (- pos start)))) (set-asm-relocs! asm (cons reloc (asm-relocs asm))))) (define* (record-far-label-reference asm label #:optional (offset 0)) "Record an s32 far label reference. This value will get patched up later by the linker." (let* ((start (- (asm-start asm) offset)) (pos (asm-pos asm)) (reloc (make-reloc 's32 label start (- pos start)))) (set-asm-relocs! asm (cons reloc (asm-relocs asm)))))