mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-10 05:50:26 +02:00
Assembler works on byte offsets, not u32 offsets
* module/system/vm/assembler.scm (u32-ref, u32-set!, s32-ref, s32-set!): Remove these helpers. * module/system/vm/assembler.scm (<asm>): Track offsets in bytes, not u32 units. (emit, assembler, process-relocs, process-labels, link-text-object) (link-frame-maps, link-symtab, write-arities, link-docstrs) (link-procprops, link-debug): Adapt. * module/system/vm/linker.scm (process-reloc): Add addend before dividing by 4 for rel32/4 symbols.
This commit is contained in:
parent
3c271457f1
commit
9e1c07bda6
2 changed files with 48 additions and 56 deletions
|
@ -291,20 +291,6 @@
|
||||||
((pack-flags f1 f2) (logior (if f1 (ash 1 0) 0)
|
((pack-flags f1 f2) (logior (if f1 (ash 1 0) 0)
|
||||||
(if f2 (ash 1 1) 0))))))
|
(if f2 (ash 1 1) 0))))))
|
||||||
|
|
||||||
;;; Helpers to read and write 32-bit units in a buffer.
|
|
||||||
|
|
||||||
(define-inline (u32-ref buf n)
|
|
||||||
(bytevector-u32-native-ref buf (* n 4)))
|
|
||||||
|
|
||||||
(define-inline (u32-set! buf n val)
|
|
||||||
(bytevector-u32-native-set! buf (* n 4) val))
|
|
||||||
|
|
||||||
(define-inline (s32-ref buf n)
|
|
||||||
(bytevector-s32-native-ref buf (* n 4)))
|
|
||||||
|
|
||||||
(define-inline (s32-set! buf n val)
|
|
||||||
(bytevector-s32-native-set! buf (* n 4) val))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -366,20 +352,19 @@
|
||||||
slot-maps)
|
slot-maps)
|
||||||
asm?
|
asm?
|
||||||
|
|
||||||
;; We write bytecode into what is logically a growable vector,
|
;; We write bytecode into a bytevector, growing the bytevector as
|
||||||
;; implemented as a list of blocks. asm-cur is the current block, and
|
;; needed. asm-cur is that bytevector, and asm-pos is the byte offset
|
||||||
;; asm-pos is the current index into that block, in 32-bit units.
|
;; into the vector at which the next word should be written.
|
||||||
;;
|
;;
|
||||||
(buf asm-buf set-asm-buf!)
|
(buf asm-buf set-asm-buf!)
|
||||||
(pos asm-pos set-asm-pos!)
|
(pos asm-pos set-asm-pos!)
|
||||||
|
|
||||||
;; asm-start is an absolute position, indicating the offset of the
|
;; asm-start is an absolute position, indicating the byte offset of
|
||||||
;; beginning of an instruction (in u32 units). It is updated after
|
;; the beginning of an instruction. It is updated after writing all
|
||||||
;; writing all the words for one primitive instruction. It models the
|
;; the words for one primitive instruction. It models the position of
|
||||||
;; position of the instruction pointer during execution, given that
|
;; the instruction pointer during execution, given that the VM updates
|
||||||
;; the VM updates the IP only at the end of executing the instruction,
|
;; the IP only at the end of executing the instruction, and is thus
|
||||||
;; and is thus useful for computing offsets between two points in a
|
;; useful for computing offsets between two points in a program.
|
||||||
;; program.
|
|
||||||
;;
|
;;
|
||||||
(start asm-start set-asm-start!)
|
(start asm-start set-asm-start!)
|
||||||
|
|
||||||
|
@ -466,8 +451,8 @@ target."
|
||||||
(define-inline (emit asm u32)
|
(define-inline (emit asm u32)
|
||||||
"Emit one 32-bit word into the instruction stream. Assumes that there
|
"Emit one 32-bit word into the instruction stream. Assumes that there
|
||||||
is space for the word."
|
is space for the word."
|
||||||
(u32-set! (asm-buf asm) (asm-pos asm) u32)
|
(bytevector-u32-native-set! (asm-buf asm) (asm-pos asm) u32)
|
||||||
(set-asm-pos! asm (1+ (asm-pos asm))))
|
(set-asm-pos! asm (+ (asm-pos asm) 4)))
|
||||||
|
|
||||||
(define-inline (make-reloc type label base word)
|
(define-inline (make-reloc type label base word)
|
||||||
"Make an internal relocation of type @var{type} referencing symbol
|
"Make an internal relocation of type @var{type} referencing symbol
|
||||||
|
@ -596,7 +581,7 @@ later by the linker."
|
||||||
(emit asm 0))
|
(emit asm 0))
|
||||||
((LO32 label offset)
|
((LO32 label offset)
|
||||||
(record-far-label-reference asm label
|
(record-far-label-reference asm label
|
||||||
(* offset (/ (asm-word-size asm) 4)))
|
(* offset (asm-word-size asm)))
|
||||||
(emit asm 0))
|
(emit asm 0))
|
||||||
((C8_C24 a b)
|
((C8_C24 a b)
|
||||||
(emit asm (pack-u8-u24 a b)))
|
(emit asm (pack-u8-u24 a b)))
|
||||||
|
@ -638,7 +623,7 @@ later by the linker."
|
||||||
#'(lambda (asm formal0 ... formal* ... ...)
|
#'(lambda (asm formal0 ... formal* ... ...)
|
||||||
(let lp ()
|
(let lp ()
|
||||||
(let ((words (length '(word0 word* ...))))
|
(let ((words (length '(word0 word* ...))))
|
||||||
(unless (<= (* 4 (+ (asm-pos asm) words))
|
(unless (<= (+ (asm-pos asm) (* 4 words))
|
||||||
(bytevector-length (asm-buf asm)))
|
(bytevector-length (asm-buf asm)))
|
||||||
(grow-buffer! asm)
|
(grow-buffer! asm)
|
||||||
(lp))))
|
(lp))))
|
||||||
|
@ -1201,7 +1186,7 @@ returned instead."
|
||||||
(define-macro-assembler (definition asm name slot representation)
|
(define-macro-assembler (definition asm name slot representation)
|
||||||
(let* ((arity (car (meta-arities (car (asm-meta asm)))))
|
(let* ((arity (car (meta-arities (car (asm-meta asm)))))
|
||||||
(def (vector name slot representation
|
(def (vector name slot representation
|
||||||
(* (- (asm-start asm) (arity-low-pc arity)) 4))))
|
(- (asm-start asm) (arity-low-pc arity)))))
|
||||||
(set-arity-definitions! arity (cons def (arity-definitions arity)))))
|
(set-arity-definitions! arity (cons def (arity-definitions arity)))))
|
||||||
|
|
||||||
(define-macro-assembler (cache-current-module! asm module scope)
|
(define-macro-assembler (cache-current-module! asm module scope)
|
||||||
|
@ -1550,23 +1535,29 @@ relocations for references to symbols defined outside the text section."
|
||||||
(fold
|
(fold
|
||||||
(lambda (reloc tail)
|
(lambda (reloc tail)
|
||||||
(match reloc
|
(match reloc
|
||||||
((type label base word)
|
((type label base offset)
|
||||||
(let ((abs (hashq-ref labels label))
|
(let ((abs (hashq-ref labels label))
|
||||||
(dst (+ base word)))
|
(dst (+ base offset)))
|
||||||
(case type
|
(case type
|
||||||
((s32)
|
((s32)
|
||||||
(if abs
|
(if abs
|
||||||
(let ((rel (- abs base)))
|
(let ((rel (- abs base)))
|
||||||
(s32-set! buf dst rel)
|
(unless (zero? (logand rel #x3))
|
||||||
|
(error "reloc not in 32-bit units!"))
|
||||||
|
(bytevector-s32-native-set! buf dst (ash rel -2))
|
||||||
tail)
|
tail)
|
||||||
(cons (make-linker-reloc 'rel32/4 (* dst 4) word label)
|
(cons (make-linker-reloc 'rel32/4 dst offset label)
|
||||||
tail)))
|
tail)))
|
||||||
((x8-s24)
|
((x8-s24)
|
||||||
(unless abs
|
(unless abs
|
||||||
(error "unbound near relocation" reloc))
|
(error "unbound near relocation" reloc))
|
||||||
(let ((rel (- abs base))
|
(let ((rel (- abs base))
|
||||||
(u32 (u32-ref buf dst)))
|
(u32 (bytevector-u32-native-ref buf dst)))
|
||||||
(u32-set! buf dst (pack-u8-s24 (logand u32 #xff) rel))
|
(unless (zero? (logand rel #x3))
|
||||||
|
(error "reloc not in 32-bit units!"))
|
||||||
|
(bytevector-u32-native-set! buf dst
|
||||||
|
(pack-u8-s24 (logand u32 #xff)
|
||||||
|
(ash rel -2)))
|
||||||
tail))
|
tail))
|
||||||
(else (error "bad relocation kind" reloc)))))))
|
(else (error "bad relocation kind" reloc)))))))
|
||||||
'()
|
'()
|
||||||
|
@ -1576,7 +1567,7 @@ relocations for references to symbols defined outside the text section."
|
||||||
"Define linker symbols for the label-offset map in @var{labels}.
|
"Define linker symbols for the label-offset map in @var{labels}.
|
||||||
The offsets are expected to be expressed in words."
|
The offsets are expected to be expressed in words."
|
||||||
(hash-map->list (lambda (label loc)
|
(hash-map->list (lambda (label loc)
|
||||||
(make-linker-symbol label (* loc 4)))
|
(make-linker-symbol label loc))
|
||||||
labels))
|
labels))
|
||||||
|
|
||||||
(define (swap-bytes! buf)
|
(define (swap-bytes! buf)
|
||||||
|
@ -1596,7 +1587,7 @@ The offsets are expected to be expressed in words."
|
||||||
(define (link-text-object asm)
|
(define (link-text-object asm)
|
||||||
"Link the .rtl-text section, swapping the endianness of the bytes if
|
"Link the .rtl-text section, swapping the endianness of the bytes if
|
||||||
needed."
|
needed."
|
||||||
(let ((buf (make-u32vector (asm-pos asm))))
|
(let ((buf (make-bytevector (asm-pos asm))))
|
||||||
(bytevector-copy! (asm-buf asm) 0 buf 0 (bytevector-length buf))
|
(bytevector-copy! (asm-buf asm) 0 buf 0 (bytevector-length buf))
|
||||||
(unless (eq? (asm-endianness asm) (native-endianness))
|
(unless (eq? (asm-endianness asm) (native-endianness))
|
||||||
(swap-bytes! buf))
|
(swap-bytes! buf))
|
||||||
|
@ -1646,7 +1637,7 @@ needed."
|
||||||
(list (make-linker-reloc 'abs32/1 0 0 '.rtl-text))
|
(list (make-linker-reloc 'abs32/1 0 0 '.rtl-text))
|
||||||
'() #:type SHT_PROGBITS #:flags SHF_ALLOC))
|
'() #:type SHT_PROGBITS #:flags SHF_ALLOC))
|
||||||
(((pos proc-slot . map) . maps)
|
(((pos proc-slot . map) . maps)
|
||||||
(bytevector-u32-set! bv header-pos (* pos 4) endianness)
|
(bytevector-u32-set! bv header-pos pos endianness)
|
||||||
(bytevector-u32-set! bv (+ header-pos 4) map-pos endianness)
|
(bytevector-u32-set! bv (+ header-pos 4) map-pos endianness)
|
||||||
(let write-bytes ((map-pos map-pos)
|
(let write-bytes ((map-pos map-pos)
|
||||||
(map map)
|
(map map)
|
||||||
|
@ -1753,9 +1744,9 @@ procedure with label @var{rw-init}. @var{rw-init} may be false. If
|
||||||
#:name name
|
#:name name
|
||||||
;; Symbol value and size are measured in
|
;; Symbol value and size are measured in
|
||||||
;; bytes, not u32s.
|
;; bytes, not u32s.
|
||||||
#:value (* 4 (meta-low-pc meta))
|
#:value (meta-low-pc meta)
|
||||||
#:size (* 4 (- (meta-high-pc meta)
|
#:size (- (meta-high-pc meta)
|
||||||
(meta-low-pc meta)))
|
(meta-low-pc meta))
|
||||||
#:type STT_FUNC
|
#:type STT_FUNC
|
||||||
#:visibility STV_HIDDEN
|
#:visibility STV_HIDDEN
|
||||||
#:shndx (elf-section-index text-section)))))
|
#:shndx (elf-section-index text-section)))))
|
||||||
|
@ -1870,8 +1861,8 @@ procedure with label @var{rw-init}. @var{rw-init} may be false. If
|
||||||
(define (write-header pos low-pc high-pc offset flags nreq nopt nlocals)
|
(define (write-header pos low-pc high-pc offset flags nreq nopt nlocals)
|
||||||
(unless (<= (+ nreq nopt) nlocals)
|
(unless (<= (+ nreq nopt) nlocals)
|
||||||
(error "forgot to emit definition instructions?"))
|
(error "forgot to emit definition instructions?"))
|
||||||
(bytevector-u32-set! headers pos (* low-pc 4) (asm-endianness asm))
|
(bytevector-u32-set! headers pos low-pc (asm-endianness asm))
|
||||||
(bytevector-u32-set! headers (+ pos 4) (* high-pc 4) (asm-endianness asm))
|
(bytevector-u32-set! headers (+ pos 4) high-pc (asm-endianness asm))
|
||||||
(bytevector-u32-set! headers (+ pos 8) offset (asm-endianness asm))
|
(bytevector-u32-set! headers (+ pos 8) offset (asm-endianness asm))
|
||||||
(bytevector-u32-set! headers (+ pos 12) flags (asm-endianness asm))
|
(bytevector-u32-set! headers (+ pos 12) flags (asm-endianness asm))
|
||||||
(bytevector-u32-set! headers (+ pos 16) nreq (asm-endianness asm))
|
(bytevector-u32-set! headers (+ pos 16) nreq (asm-endianness asm))
|
||||||
|
@ -2018,7 +2009,7 @@ procedure with label @var{rw-init}. @var{rw-init} may be false. If
|
||||||
(and tail
|
(and tail
|
||||||
(not (find-tail is-documentation? (cdr tail)))
|
(not (find-tail is-documentation? (cdr tail)))
|
||||||
(string? (cdar tail))
|
(string? (cdar tail))
|
||||||
(cons (* 4 (meta-low-pc meta)) (cdar tail)))))
|
(cons (meta-low-pc meta) (cdar tail)))))
|
||||||
(reverse (asm-meta asm))))
|
(reverse (asm-meta asm))))
|
||||||
(let* ((endianness (asm-endianness asm))
|
(let* ((endianness (asm-endianness asm))
|
||||||
(docstrings (find-docstrings))
|
(docstrings (find-docstrings))
|
||||||
|
@ -2084,7 +2075,7 @@ procedure with label @var{rw-init}. @var{rw-init} may be false. If
|
||||||
(filter-map (lambda (meta)
|
(filter-map (lambda (meta)
|
||||||
(let ((props (props-without-name-or-docstring meta)))
|
(let ((props (props-without-name-or-docstring meta)))
|
||||||
(and (pair? props)
|
(and (pair? props)
|
||||||
(cons (* 4 (meta-low-pc meta)) props))))
|
(cons (meta-low-pc meta) props))))
|
||||||
(reverse (asm-meta asm))))
|
(reverse (asm-meta asm))))
|
||||||
(let* ((endianness (asm-endianness asm))
|
(let* ((endianness (asm-endianness asm))
|
||||||
(procprops (find-procprops))
|
(procprops (find-procprops))
|
||||||
|
@ -2145,14 +2136,14 @@ procedure with label @var{rw-init}. @var{rw-init} may be false. If
|
||||||
(else
|
(else
|
||||||
'()))
|
'()))
|
||||||
(low-pc ,(meta-label meta))
|
(low-pc ,(meta-label meta))
|
||||||
(high-pc ,(* 4 (- (meta-high-pc meta) (meta-low-pc meta)))))))
|
(high-pc ,(- (meta-high-pc meta) (meta-low-pc meta))))))
|
||||||
|
|
||||||
(define (make-compile-unit-die asm)
|
(define (make-compile-unit-die asm)
|
||||||
`(compile-unit
|
`(compile-unit
|
||||||
(@ (producer ,(string-append "Guile " (version)))
|
(@ (producer ,(string-append "Guile " (version)))
|
||||||
(language ,(asm-language asm))
|
(language ,(asm-language asm))
|
||||||
(low-pc .rtl-text)
|
(low-pc .rtl-text)
|
||||||
(high-pc ,(* 4 (asm-pos asm)))
|
(high-pc ,(asm-pos asm))
|
||||||
(stmt-list 0))
|
(stmt-list 0))
|
||||||
,@(map meta->subprogram-die (reverse (asm-meta asm)))))
|
,@(map meta->subprogram-die (reverse (asm-meta asm)))))
|
||||||
|
|
||||||
|
@ -2200,6 +2191,7 @@ procedure with label @var{rw-init}. @var{rw-init} may be false. If
|
||||||
;; from 10 to 255, so 246 values.
|
;; from 10 to 255, so 246 values.
|
||||||
(define base -4)
|
(define base -4)
|
||||||
(define range 15)
|
(define range 15)
|
||||||
|
(define min-inc 4) ; Minimum PC increment.
|
||||||
|
|
||||||
(let lp ((sources (asm-sources asm)) (out '()))
|
(let lp ((sources (asm-sources asm)) (out '()))
|
||||||
(match sources
|
(match sources
|
||||||
|
@ -2225,7 +2217,7 @@ procedure with label @var{rw-init}. @var{rw-init} may be false. If
|
||||||
(put-u32 line-port 0) ; Length; will patch later.
|
(put-u32 line-port 0) ; Length; will patch later.
|
||||||
(put-u16 line-port 2) ; DWARF 2 format.
|
(put-u16 line-port 2) ; DWARF 2 format.
|
||||||
(put-u32 line-port 0) ; Prologue length; will patch later.
|
(put-u32 line-port 0) ; Prologue length; will patch later.
|
||||||
(put-u8 line-port 4) ; Minimum instruction length: 4 bytes.
|
(put-u8 line-port min-inc) ; Minimum instruction length: 4 bytes.
|
||||||
(put-u8 line-port 1) ; Default is-stmt: true.
|
(put-u8 line-port 1) ; Default is-stmt: true.
|
||||||
|
|
||||||
(put-s8 line-port base) ; Line base. See the DWARF standard.
|
(put-s8 line-port base) ; Line base. See the DWARF standard.
|
||||||
|
@ -2297,12 +2289,14 @@ procedure with label @var{rw-init}. @var{rw-init} may be false. If
|
||||||
(add-reloc! 'abs64/1)
|
(add-reloc! 'abs64/1)
|
||||||
(put-u64 line-port 0))))
|
(put-u64 line-port 0))))
|
||||||
(define (end-sequence pc)
|
(define (end-sequence pc)
|
||||||
(let ((pc-inc (- (asm-pos asm) pc)))
|
(let ((pc-inc (/ (- (asm-pos asm) pc) min-inc)))
|
||||||
(put-u8 line-port 2) ; advance-pc
|
(put-u8 line-port 2) ; advance-pc
|
||||||
(put-uleb128 line-port pc-inc))
|
(put-uleb128 line-port pc-inc))
|
||||||
(extended-op 1 0))
|
(extended-op 1 0))
|
||||||
(define (advance-pc pc-inc line-inc)
|
(define (advance-pc pc-inc line-inc)
|
||||||
(let ((spec (+ (- line-inc base) (* pc-inc range) 10)))
|
(let ((spec (+ (- line-inc base)
|
||||||
|
(* (/ pc-inc min-inc) range)
|
||||||
|
10)))
|
||||||
(cond
|
(cond
|
||||||
((or (< line-inc base) (>= line-inc (+ base range)))
|
((or (< line-inc base) (>= line-inc (+ base range)))
|
||||||
(advance-line line-inc)
|
(advance-line line-inc)
|
||||||
|
@ -2311,11 +2305,11 @@ procedure with label @var{rw-init}. @var{rw-init} may be false. If
|
||||||
(put-u8 line-port spec))
|
(put-u8 line-port spec))
|
||||||
((< spec 500)
|
((< spec 500)
|
||||||
(put-u8 line-port 8) ; const-advance-pc
|
(put-u8 line-port 8) ; const-advance-pc
|
||||||
(advance-pc (- pc-inc (floor/ (- 255 10) range))
|
(advance-pc (- pc-inc (* (floor/ (- 255 10) range) min-inc))
|
||||||
line-inc))
|
line-inc))
|
||||||
(else
|
(else
|
||||||
(put-u8 line-port 2) ; advance-pc
|
(put-u8 line-port 2) ; advance-pc
|
||||||
(put-uleb128 line-port pc-inc)
|
(put-uleb128 line-port (/ pc-inc min-inc))
|
||||||
(advance-pc 0 line-inc)))))
|
(advance-pc 0 line-inc)))))
|
||||||
(define (advance-line inc)
|
(define (advance-line inc)
|
||||||
(put-u8 line-port 3)
|
(put-u8 line-port 3)
|
||||||
|
|
|
@ -394,12 +394,10 @@ symbol, as present in @var{symtab}."
|
||||||
(target (linker-symbol-address symbol)))
|
(target (linker-symbol-address symbol)))
|
||||||
(case (linker-reloc-type reloc)
|
(case (linker-reloc-type reloc)
|
||||||
((rel32/4)
|
((rel32/4)
|
||||||
(let ((diff (- target offset)))
|
(let ((diff (+ (- target offset) (linker-reloc-addend reloc))))
|
||||||
(unless (zero? (modulo diff 4))
|
(unless (zero? (modulo diff 4))
|
||||||
(error "Bad offset" reloc symbol offset))
|
(error "Bad offset" reloc symbol offset))
|
||||||
(bytevector-s32-set! bv offset
|
(bytevector-s32-set! bv offset (/ diff 4) endianness)))
|
||||||
(+ (/ diff 4) (linker-reloc-addend reloc))
|
|
||||||
endianness)))
|
|
||||||
((rel32/1)
|
((rel32/1)
|
||||||
(let ((diff (- target offset)))
|
(let ((diff (- target offset)))
|
||||||
(bytevector-s32-set! bv offset
|
(bytevector-s32-set! bv offset
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue