factor/basis/compiler/cfg/instructions/instructions.factor

883 lines
16 KiB
Factor

! Copyright (C) 2008, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: assocs accessors arrays kernel sequences namespaces words
math math.order layouts classes.union compiler.units alien
byte-arrays combinators compiler.cfg.registers
compiler.cfg.instructions.syntax ;
IN: compiler.cfg.instructions
<<
SYMBOL: insn-classes
V{ } clone insn-classes set-global
>>
: new-insn ( ... class -- insn ) f swap boa ; inline
! Virtual CPU instructions, used by CFG IR
TUPLE: insn ;
! Instructions which use vregs
TUPLE: vreg-insn < insn ;
! Instructions which do not have side effects; used for
! dead code elimination
TUPLE: flushable-insn < vreg-insn ;
! Instructions which are referentially transparent; used for
! value numbering
TUPLE: foldable-insn < flushable-insn ;
! Constants
FOLDABLE-INSN: ##load-integer
def: dst/int-rep
literal: val ;
FOLDABLE-INSN: ##load-reference
def: dst/tagged-rep
literal: obj ;
! These four are inserted by representation selection
FLUSHABLE-INSN: ##load-tagged
def: dst/tagged-rep
literal: val ;
FLUSHABLE-INSN: ##load-float
def: dst/float-rep
literal: val ;
FLUSHABLE-INSN: ##load-double
def: dst/double-rep
literal: val ;
FLUSHABLE-INSN: ##load-vector
def: dst
literal: val rep ;
! Stack operations
FLUSHABLE-INSN: ##peek
def: dst/tagged-rep
literal: loc ;
VREG-INSN: ##replace
use: src/tagged-rep
literal: loc ;
INSN: ##replace-imm
literal: src loc ;
INSN: ##inc-d
literal: n ;
INSN: ##inc-r
literal: n ;
! Subroutine calls
INSN: ##call
literal: word ;
INSN: ##jump
literal: word ;
INSN: ##prologue ;
INSN: ##epilogue ;
INSN: ##return ;
! Dummy instruction that simply inhibits TCO
INSN: ##no-tco ;
! Jump tables
VREG-INSN: ##dispatch
use: src/int-rep
temp: temp/int-rep ;
! Slot access
FLUSHABLE-INSN: ##slot
def: dst/tagged-rep
use: obj/tagged-rep slot/int-rep
literal: scale tag ;
FLUSHABLE-INSN: ##slot-imm
def: dst/tagged-rep
use: obj/tagged-rep
literal: slot tag ;
VREG-INSN: ##set-slot
use: src/tagged-rep obj/tagged-rep slot/int-rep
literal: scale tag ;
VREG-INSN: ##set-slot-imm
use: src/tagged-rep obj/tagged-rep
literal: slot tag ;
! Register transfers
FOLDABLE-INSN: ##copy
def: dst
use: src
literal: rep ;
FOLDABLE-INSN: ##tagged>integer
def: dst/int-rep
use: src/tagged-rep ;
! Integer arithmetic
FOLDABLE-INSN: ##add
def: dst/int-rep
use: src1/int-rep src2/int-rep ;
FOLDABLE-INSN: ##add-imm
def: dst/int-rep
use: src1/int-rep
literal: src2 ;
FOLDABLE-INSN: ##sub
def: dst/int-rep
use: src1/int-rep src2/int-rep ;
FOLDABLE-INSN: ##sub-imm
def: dst/int-rep
use: src1/int-rep
literal: src2 ;
FOLDABLE-INSN: ##mul
def: dst/int-rep
use: src1/int-rep src2/int-rep ;
FOLDABLE-INSN: ##mul-imm
def: dst/int-rep
use: src1/int-rep
literal: src2 ;
FOLDABLE-INSN: ##and
def: dst/int-rep
use: src1/int-rep src2/int-rep ;
FOLDABLE-INSN: ##and-imm
def: dst/int-rep
use: src1/int-rep
literal: src2 ;
FOLDABLE-INSN: ##or
def: dst/int-rep
use: src1/int-rep src2/int-rep ;
FOLDABLE-INSN: ##or-imm
def: dst/int-rep
use: src1/int-rep
literal: src2 ;
FOLDABLE-INSN: ##xor
def: dst/int-rep
use: src1/int-rep src2/int-rep ;
FOLDABLE-INSN: ##xor-imm
def: dst/int-rep
use: src1/int-rep
literal: src2 ;
FOLDABLE-INSN: ##shl
def: dst/int-rep
use: src1/int-rep src2/int-rep ;
FOLDABLE-INSN: ##shl-imm
def: dst/int-rep
use: src1/int-rep
literal: src2 ;
FOLDABLE-INSN: ##shr
def: dst/int-rep
use: src1/int-rep src2/int-rep ;
FOLDABLE-INSN: ##shr-imm
def: dst/int-rep
use: src1/int-rep
literal: src2 ;
FOLDABLE-INSN: ##sar
def: dst/int-rep
use: src1/int-rep src2/int-rep ;
FOLDABLE-INSN: ##sar-imm
def: dst/int-rep
use: src1/int-rep
literal: src2 ;
FOLDABLE-INSN: ##min
def: dst/int-rep
use: src1/int-rep src2/int-rep ;
FOLDABLE-INSN: ##max
def: dst/int-rep
use: src1/int-rep src2/int-rep ;
FOLDABLE-INSN: ##not
def: dst/int-rep
use: src/int-rep ;
FOLDABLE-INSN: ##neg
def: dst/int-rep
use: src/int-rep ;
FOLDABLE-INSN: ##log2
def: dst/int-rep
use: src/int-rep ;
FOLDABLE-INSN: ##bit-count
def: dst/int-rep
use: src/int-rep ;
! Float arithmetic
FOLDABLE-INSN: ##add-float
def: dst/double-rep
use: src1/double-rep src2/double-rep ;
FOLDABLE-INSN: ##sub-float
def: dst/double-rep
use: src1/double-rep src2/double-rep ;
FOLDABLE-INSN: ##mul-float
def: dst/double-rep
use: src1/double-rep src2/double-rep ;
FOLDABLE-INSN: ##div-float
def: dst/double-rep
use: src1/double-rep src2/double-rep ;
FOLDABLE-INSN: ##min-float
def: dst/double-rep
use: src1/double-rep src2/double-rep ;
FOLDABLE-INSN: ##max-float
def: dst/double-rep
use: src1/double-rep src2/double-rep ;
FOLDABLE-INSN: ##sqrt
def: dst/double-rep
use: src/double-rep ;
! Single/double float conversion
FOLDABLE-INSN: ##single>double-float
def: dst/double-rep
use: src/float-rep ;
FOLDABLE-INSN: ##double>single-float
def: dst/float-rep
use: src/double-rep ;
! Float/integer conversion
FOLDABLE-INSN: ##float>integer
def: dst/int-rep
use: src/double-rep ;
FOLDABLE-INSN: ##integer>float
def: dst/double-rep
use: src/int-rep ;
! SIMD operations
FOLDABLE-INSN: ##zero-vector
def: dst
literal: rep ;
FOLDABLE-INSN: ##fill-vector
def: dst
literal: rep ;
FOLDABLE-INSN: ##gather-vector-2
def: dst
use: src1/scalar-rep src2/scalar-rep
literal: rep ;
FOLDABLE-INSN: ##gather-int-vector-2
def: dst
use: src1/int-rep src2/int-rep
literal: rep ;
FOLDABLE-INSN: ##gather-vector-4
def: dst
use: src1/scalar-rep src2/scalar-rep src3/scalar-rep src4/scalar-rep
literal: rep ;
FOLDABLE-INSN: ##gather-int-vector-4
def: dst
use: src1/int-rep src2/int-rep src3/int-rep src4/int-rep
literal: rep ;
FOLDABLE-INSN: ##select-vector
def: dst/int-rep
use: src
literal: n rep ;
FOLDABLE-INSN: ##shuffle-vector
def: dst
use: src shuffle
literal: rep ;
FOLDABLE-INSN: ##shuffle-vector-halves-imm
def: dst
use: src1 src2
literal: shuffle rep ;
FOLDABLE-INSN: ##shuffle-vector-imm
def: dst
use: src
literal: shuffle rep ;
FOLDABLE-INSN: ##tail>head-vector
def: dst
use: src
literal: rep ;
FOLDABLE-INSN: ##merge-vector-head
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##merge-vector-tail
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##float-pack-vector
def: dst
use: src
literal: rep ;
FOLDABLE-INSN: ##signed-pack-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##unsigned-pack-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##unpack-vector-head
def: dst
use: src
literal: rep ;
FOLDABLE-INSN: ##unpack-vector-tail
def: dst
use: src
literal: rep ;
FOLDABLE-INSN: ##integer>float-vector
def: dst
use: src
literal: rep ;
FOLDABLE-INSN: ##float>integer-vector
def: dst
use: src
literal: rep ;
FOLDABLE-INSN: ##compare-vector
def: dst
use: src1 src2
literal: rep cc ;
FOLDABLE-INSN: ##test-vector
def: dst/tagged-rep
use: src1
temp: temp/int-rep
literal: rep vcc ;
VREG-INSN: ##test-vector-branch
use: src1
temp: temp/int-rep
literal: rep vcc ;
FOLDABLE-INSN: ##add-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##saturated-add-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##add-sub-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##sub-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##saturated-sub-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##mul-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##mul-high-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##mul-horizontal-add-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##saturated-mul-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##div-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##min-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##max-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##avg-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##dot-vector
def: dst/scalar-rep
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##sad-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##horizontal-add-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##horizontal-sub-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##horizontal-shl-vector-imm
def: dst
use: src1
literal: src2 rep ;
FOLDABLE-INSN: ##horizontal-shr-vector-imm
def: dst
use: src1
literal: src2 rep ;
FOLDABLE-INSN: ##abs-vector
def: dst
use: src
literal: rep ;
FOLDABLE-INSN: ##sqrt-vector
def: dst
use: src
literal: rep ;
FOLDABLE-INSN: ##and-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##andn-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##or-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##xor-vector
def: dst
use: src1 src2
literal: rep ;
FOLDABLE-INSN: ##not-vector
def: dst
use: src
literal: rep ;
FOLDABLE-INSN: ##shl-vector-imm
def: dst
use: src1
literal: src2 rep ;
FOLDABLE-INSN: ##shr-vector-imm
def: dst
use: src1
literal: src2 rep ;
FOLDABLE-INSN: ##shl-vector
def: dst
use: src1 src2/int-scalar-rep
literal: rep ;
FOLDABLE-INSN: ##shr-vector
def: dst
use: src1 src2/int-scalar-rep
literal: rep ;
! Scalar/vector conversion
FOLDABLE-INSN: ##scalar>integer
def: dst/int-rep
use: src
literal: rep ;
FOLDABLE-INSN: ##integer>scalar
def: dst
use: src/int-rep
literal: rep ;
FOLDABLE-INSN: ##vector>scalar
def: dst/scalar-rep
use: src
literal: rep ;
FOLDABLE-INSN: ##scalar>vector
def: dst
use: src/scalar-rep
literal: rep ;
! Boxing and unboxing aliens
FOLDABLE-INSN: ##box-alien
def: dst/tagged-rep
use: src/int-rep
temp: temp/int-rep ;
FOLDABLE-INSN: ##box-displaced-alien
def: dst/tagged-rep
use: displacement/int-rep base/tagged-rep
temp: temp/int-rep
literal: base-class ;
FOLDABLE-INSN: ##unbox-any-c-ptr
def: dst/int-rep
use: src/tagged-rep ;
FOLDABLE-INSN: ##unbox-alien
def: dst/int-rep
use: src/tagged-rep ;
! Zero-extending and sign-extending integers
FOLDABLE-INSN: ##convert-integer
def: dst/int-rep
use: src/int-rep
literal: c-type ;
! Raw memory accessors
FLUSHABLE-INSN: ##load-memory
def: dst
use: base/int-rep displacement/int-rep
literal: scale offset rep c-type ;
FLUSHABLE-INSN: ##load-memory-imm
def: dst
use: base/int-rep
literal: offset rep c-type ;
VREG-INSN: ##store-memory
use: src base/int-rep displacement/int-rep
literal: scale offset rep c-type ;
VREG-INSN: ##store-memory-imm
use: src base/int-rep
literal: offset rep c-type ;
! Memory allocation
FLUSHABLE-INSN: ##allot
def: dst/tagged-rep
literal: size class
temp: temp/int-rep ;
VREG-INSN: ##write-barrier
use: src/tagged-rep slot/int-rep
literal: scale tag
temp: temp1/int-rep temp2/int-rep ;
VREG-INSN: ##write-barrier-imm
use: src/tagged-rep
literal: slot tag
temp: temp1/int-rep temp2/int-rep ;
FLUSHABLE-INSN: ##alien-global
def: dst/int-rep
literal: symbol library ;
FLUSHABLE-INSN: ##vm-field
def: dst/tagged-rep
literal: offset ;
VREG-INSN: ##set-vm-field
use: src/tagged-rep
literal: offset ;
! FFI
FOLDABLE-INSN: ##unbox
def: dst
use: src/tagged-rep
literal: unboxer rep ;
FOLDABLE-INSN: ##unbox-long-long
def: dst1/int-rep dst2/int-rep
use: src/tagged-rep
literal: unboxer ;
FLUSHABLE-INSN: ##local-allot
def: dst/int-rep
literal: size align offset ;
FOLDABLE-INSN: ##box
def: dst/tagged-rep
use: src
literal: boxer rep gc-map ;
FOLDABLE-INSN: ##box-long-long
def: dst/tagged-rep
use: src1/int-rep src2/int-rep
literal: boxer gc-map ;
! Alien call inputs and outputs are arrays of triples with shape
! { vreg rep stack#/reg }
VREG-INSN: ##alien-invoke
literal: reg-inputs stack-inputs reg-outputs dead-outputs cleanup stack-size symbols dll gc-map ;
VREG-INSN: ##alien-indirect
use: src/int-rep
literal: reg-inputs stack-inputs reg-outputs dead-outputs cleanup stack-size gc-map ;
VREG-INSN: ##alien-assembly
literal: reg-inputs stack-inputs reg-outputs dead-outputs cleanup stack-size quot gc-map ;
VREG-INSN: ##callback-inputs
literal: reg-outputs stack-outputs ;
VREG-INSN: ##callback-outputs
literal: reg-inputs ;
! Control flow
FLUSHABLE-INSN: ##phi
def: dst
literal: inputs ;
INSN: ##branch ;
! Tagged conditionals
VREG-INSN: ##compare-branch
use: src1/tagged-rep src2/tagged-rep
literal: cc ;
VREG-INSN: ##compare-imm-branch
use: src1/tagged-rep
literal: src2 cc ;
FOLDABLE-INSN: ##compare
def: dst/tagged-rep
use: src1/tagged-rep src2/tagged-rep
literal: cc
temp: temp/int-rep ;
FOLDABLE-INSN: ##compare-imm
def: dst/tagged-rep
use: src1/tagged-rep
literal: src2 cc
temp: temp/int-rep ;
! Integer conditionals
VREG-INSN: ##compare-integer-branch
use: src1/int-rep src2/int-rep
literal: cc ;
VREG-INSN: ##compare-integer-imm-branch
use: src1/int-rep
literal: src2 cc ;
VREG-INSN: ##test-branch
use: src1/int-rep src2/int-rep
literal: cc ;
VREG-INSN: ##test-imm-branch
use: src1/int-rep
literal: src2 cc ;
FOLDABLE-INSN: ##compare-integer
def: dst/tagged-rep
use: src1/int-rep src2/int-rep
literal: cc
temp: temp/int-rep ;
FOLDABLE-INSN: ##compare-integer-imm
def: dst/tagged-rep
use: src1/int-rep
literal: src2 cc
temp: temp/int-rep ;
FOLDABLE-INSN: ##test
def: dst/tagged-rep
use: src1/int-rep src2/int-rep
literal: cc
temp: temp/int-rep ;
FOLDABLE-INSN: ##test-imm
def: dst/tagged-rep
use: src1/int-rep
literal: src2 cc
temp: temp/int-rep ;
! Float conditionals
VREG-INSN: ##compare-float-ordered-branch
use: src1/double-rep src2/double-rep
literal: cc ;
VREG-INSN: ##compare-float-unordered-branch
use: src1/double-rep src2/double-rep
literal: cc ;
FOLDABLE-INSN: ##compare-float-ordered
def: dst/tagged-rep
use: src1/double-rep src2/double-rep
literal: cc
temp: temp/int-rep ;
FOLDABLE-INSN: ##compare-float-unordered
def: dst/tagged-rep
use: src1/double-rep src2/double-rep
literal: cc
temp: temp/int-rep ;
! Overflowing arithmetic
VREG-INSN: ##fixnum-add
def: dst/tagged-rep
use: src1/tagged-rep src2/tagged-rep
literal: cc ;
VREG-INSN: ##fixnum-sub
def: dst/tagged-rep
use: src1/tagged-rep src2/tagged-rep
literal: cc ;
VREG-INSN: ##fixnum-mul
def: dst/tagged-rep
use: src1/tagged-rep src2/int-rep
literal: cc ;
VREG-INSN: ##save-context
temp: temp1/int-rep temp2/int-rep ;
! GC checks
VREG-INSN: ##check-nursery-branch
literal: size cc
temp: temp1/int-rep temp2/int-rep ;
INSN: ##call-gc
literal: gc-map ;
! Spills and reloads, inserted by register allocator
TUPLE: spill-slot { n integer } ;
C: <spill-slot> spill-slot
VREG-INSN: ##spill
use: src
literal: rep dst ;
VREG-INSN: ##reload
def: dst
literal: rep src ;
UNION: ##allocation
##allot
##box-alien
##box-displaced-alien ;
UNION: conditional-branch-insn
##compare-branch
##compare-imm-branch
##compare-integer-branch
##compare-integer-imm-branch
##test-branch
##test-imm-branch
##compare-float-ordered-branch
##compare-float-unordered-branch
##test-vector-branch
##check-nursery-branch
##fixnum-add
##fixnum-sub
##fixnum-mul ;
! For alias analysis
UNION: ##read ##slot ##slot-imm ##vm-field ##alien-global ;
UNION: ##write ##set-slot ##set-slot-imm ##set-vm-field ;
UNION: alien-call-insn
##alien-invoke
##alien-indirect
##alien-assembly ;
! Instructions that contain subroutine calls to functions which
! can callback arbitrary Factor code
UNION: factor-call-insn
alien-call-insn ;
! Instructions that contain subroutine calls to functions which
! allocate memory
UNION: gc-map-insn
##call-gc
##box
##box-long-long
factor-call-insn ;
M: gc-map-insn clone call-next-method [ clone ] change-gc-map ;
! Each one has a gc-map slot
TUPLE: gc-map scrub-d scrub-r gc-roots derived-roots ;
: <gc-map> ( -- gc-map ) gc-map new ;
! Instructions that clobber registers. They receive inputs and
! produce outputs in spill slots.
UNION: hairy-clobber-insn
##call-gc
alien-call-insn
##callback-inputs
##callback-outputs
##unbox-long-long ;
! Instructions that clobber registers but are allowed to produce
! outputs in registers. Inputs are in spill slots, except for
! inputs coalesced with the output, in which case that input
! will be in a register.
UNION: clobber-insn
hairy-clobber-insn
##unbox
##box
##box-long-long ;
! Instructions that have complex expansions and require that the
! output registers are not equal to any of the input registers
UNION: def-is-use-insn
##box-alien
##box-displaced-alien
##unbox-any-c-ptr ;