;;; Guile bytecode assembler

;;; Copyright (C) 2001, 2009, 2010, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
;;;
;;; This library is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU Lesser General Public
;;; License as published by the Free Software Foundation; either
;;; version 3 of the License, or (at your option) any later version.
;;;
;;; This library is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;; Lesser General Public License for more details.
;;;
;;; You should have received a copy of the GNU Lesser General Public
;;; License along with this library; if not, write to the Free Software
;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

;;; Commentary:
;;;
;;; This module implements an assembler that creates an ELF image from
;;; bytecode assembly and macro-assembly.  The input can be given in
;;; s-expression form, like ((OP ARG ...) ...).  Internally there is a
;;; procedural interface, the emit-OP procedures, but that is not
;;; currently exported.
;;;
;;; "Primitive instructions" correspond to VM operations.  Assemblers
;;; for primitive instructions are generated programmatically from
;;; (instruction-list), which itself is derived from the VM sources.
;;; There are also "macro-instructions" like "label" or "load-constant"
;;; that expand to 0 or more primitive instructions.
;;;
;;; The assembler also handles some higher-level tasks, like creating
;;; the symbol table, other metadata sections, creating a constant table
;;; for the whole compilation unit, and writing the dynamic section of
;;; the ELF file along with the appropriate initialization routines.
;;;
;;; Most compilers will want to use the trio of make-assembler,
;;; emit-text, and link-assembly.  That will result in the creation of
;;; an ELF image as a bytevector, which can then be loaded using
;;; load-thunk-from-memory, or written to disk as a .go file.
;;;
;;; Code:

(define-module (system vm assembler)
  #:use-module (system base target)
  #:use-module (system vm dwarf)
  #:use-module (system vm elf)
  #:use-module (system vm linker)
  #:use-module (system syntax internal)
  #:use-module (language bytecode)
  #:use-module (rnrs bytevectors)
  #:use-module (ice-9 binary-ports)
  #:use-module (ice-9 vlist)
  #:use-module (ice-9 match)
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-4)
  #:use-module (srfi srfi-9)
  #:use-module (srfi srfi-11)
  #:export (make-assembler

            (emit-receive* . emit-receive)
            (emit-mov* . emit-mov)
            (emit-fmov* . emit-fmov)

            emit-call
            emit-call-label
            emit-tail-call
            emit-tail-call-label
            emit-receive-values
            emit-return
            emit-return-values
            emit-call/cc
            emit-abort
            emit-builtin-ref
            emit-br-if-nargs-ne
            emit-br-if-nargs-lt
            emit-br-if-nargs-gt
            emit-assert-nargs-ee
            emit-assert-nargs-ge
            emit-assert-nargs-le
            emit-alloc-frame
            emit-reset-frame
            emit-assert-nargs-ee/locals
            emit-br-if-npos-gt
            emit-bind-kwargs
            emit-bind-rest
            emit-br
            emit-br-if-true
            emit-br-if-null
            emit-br-if-nil
            emit-br-if-pair
            emit-br-if-struct
            emit-br-if-char
            emit-br-if-tc7
            emit-br-if-eq
            emit-br-if-eqv
            emit-br-if-=
            emit-br-if-<
            emit-br-if-<=
            emit-br-if-logtest
            emit-br-if-u64-=
            emit-br-if-u64-<
            emit-br-if-u64-<=
            emit-br-if-u64-<-scm
            emit-br-if-u64-<=-scm
            emit-br-if-u64-=-scm
            emit-br-if-u64->=-scm
            emit-br-if-u64->-scm
            emit-br-if-f64-=
            emit-br-if-f64-<
            emit-br-if-f64-<=
            emit-br-if-f64->
            emit-br-if-f64->=
            emit-box
            emit-box-ref
            emit-box-set!
            emit-make-closure
            emit-free-ref
            emit-free-set!
            emit-current-module
            emit-resolve
            emit-define!
            emit-toplevel-box
            emit-module-box
            emit-prompt
            emit-wind
            emit-unwind
            emit-push-fluid
            emit-pop-fluid
            emit-push-dynamic-state
            emit-pop-dynamic-state
            emit-current-thread
            emit-fluid-ref
            emit-fluid-set!
            emit-string-length
            emit-string-ref
            emit-string-set!
            emit-string->number
            emit-string->symbol
            emit-symbol->keyword
            emit-cons
            emit-car
            emit-cdr
            emit-set-car!
            emit-set-cdr!
            emit-add
            emit-add/immediate
            emit-sub
            emit-sub/immediate
            emit-mul
            emit-div
            emit-quo
            emit-rem
            emit-mod
            emit-ash
            emit-fadd
            emit-fsub
            emit-fmul
            emit-fdiv
            emit-uadd
            emit-usub
            emit-umul
            emit-uadd/immediate
            emit-usub/immediate
            emit-umul/immediate
            emit-logand
            emit-logior
            emit-logxor
            emit-logsub
            emit-ulogand
            emit-ulogior
            emit-ulogxor
            emit-ulogsub
            emit-ursh
            emit-ulsh
            emit-ursh/immediate
            emit-ulsh/immediate
            emit-char->integer
            emit-integer->char
            emit-make-vector
            emit-make-vector/immediate
            emit-vector-length
            emit-vector-ref
            emit-vector-ref/immediate
            emit-vector-set!
            emit-vector-set!/immediate
            emit-struct-vtable
            emit-allocate-struct/immediate
            emit-struct-ref/immediate
            emit-struct-set!/immediate
            emit-allocate-struct
            emit-struct-ref
            emit-struct-set!
            emit-class-of
            emit-make-array
            emit-scm->f64
            emit-load-f64
            emit-f64->scm
            emit-scm->u64
            emit-scm->u64/truncate
            emit-load-u64
            emit-u64->scm
            emit-scm->s64
            emit-load-s64
            emit-s64->scm
            emit-bv-length
            emit-bv-u8-ref
            emit-bv-s8-ref
            emit-bv-u16-ref
            emit-bv-s16-ref
            emit-bv-u32-ref
            emit-bv-s32-ref
            emit-bv-u64-ref
            emit-bv-s64-ref
            emit-bv-f32-ref
            emit-bv-f64-ref
            emit-bv-u8-set!
            emit-bv-s8-set!
            emit-bv-u16-set!
            emit-bv-s16-set!
            emit-bv-u32-set!
            emit-bv-s32-set!
            emit-bv-u64-set!
            emit-bv-s64-set!
            emit-bv-f32-set!
            emit-bv-f64-set!
            emit-make-atomic-box
            emit-atomic-box-ref
            emit-atomic-box-set!
            emit-atomic-box-swap!
            emit-atomic-box-compare-and-swap!
            emit-handle-interrupts

            emit-text
            link-assembly))


