This commit is contained in:
NikolajDanger
2022-05-25 16:01:54 +02:00
parent 5f7c450809
commit 3cce70432d
6 changed files with 1048 additions and 754 deletions

View File

@ -613,8 +613,59 @@ let rec compileExp (e : TypedExp)
If `n` is less than `0` then remember to terminate the program with
an error -- see implementation of `iota`.
*)
| Replicate (_, _, _, _) ->
failwith "Unimplemented code generation of replicate"
| Replicate (n_exp, a_exp, a_type, (line, _)) ->
let a_size = getElemSize a_type
let size_reg = newReg "size_reg"
let n_code = compileExp n_exp vtable size_reg
(* size_reg is now the integer n. *)
let a_reg = newReg "a_reg"
let a_code = compileExp a_exp vtable a_reg
(* Check that array size N >= 0:
if N >= 0 then jumpto safe_lab
jumpto "_IllegalArrSizeError_"
safe_lab: ...
*)
let safe_lab = newLab "safe_lab"
let checksize = [ Mips.BGEZ (size_reg, safe_lab)
; Mips.LI (RN5, line)
; Mips.LA (RN6, "_Msg_IllegalArraySize_")
; Mips.J "_RuntimeError_"
; Mips.LABEL (safe_lab)
]
let addr_reg = newReg "addr_reg"
let i_reg = newReg "i_reg"
let init_regs = [ Mips.ADDI (addr_reg, place, 4)
; Mips.MOVE (i_reg, RZ) ]
(* addr_reg is now the position of the first array element. *)
(* Run a loop. Keep jumping back to loop_beg until it is not the
case that i_reg < size_reg, and then jump to loop_end. *)
let loop_beg = newLab "loop_beg"
let loop_end = newLab "loop_end"
let tmp_reg = newReg "tmp_reg"
let loop_header = [ Mips.LABEL (loop_beg)
; Mips.SUB (tmp_reg, i_reg, size_reg)
; Mips.BGEZ (tmp_reg, loop_end)
]
(* 'arr[i] = a' *)
let loop_replicate = [ mipsStore a_size (a_reg, addr_reg, 0) ]
let loop_footer = [ Mips.ADDI (addr_reg, addr_reg, 4)
; Mips.ADDI (i_reg, i_reg, 1)
; Mips.J loop_beg
; Mips.LABEL loop_end
]
n_code
@ a_code
@ checksize
@ dynalloc (size_reg, place, Int)
@ init_regs
@ loop_header
@ loop_replicate
@ loop_footer
(* TODO project task 2: see also the comment to replicate.
(a) `filter(f, arr)`: has some similarity with the implementation of map.
@ -631,8 +682,59 @@ let rec compileExp (e : TypedExp)
counter computed in step (c). You do this of course with a
`Mips.SW(counter_reg, place, 0)` instruction.
*)
| Filter (_, _, _, _) ->
failwith "Unimplemented code generation of filter"
| Filter (farg, arr_exp, a_type, pos) ->
let size_reg = newReg "size_reg" (* size of input/output array *)
let arr_reg = newReg "arr_reg" (* address of array *)
let elem_reg = newReg "elem_reg" (* address of single element *)
let res_reg = newReg "res_reg"
let bool_reg = newReg "bool_reg"
let arr_code = compileExp arr_exp vtable arr_reg
let get_size = [ Mips.LW (size_reg, arr_reg, 0) ]
let addr_reg = newReg "addr_reg" (* address of element in new array *)
let i_reg = newReg "i_reg"
let j_reg = newReg "j_reg"
let init_regs = [ Mips.ADDI (addr_reg, place, 4)
; Mips.MOVE (i_reg, RZ)
; Mips.MOVE (j_reg, RZ)
; Mips.ADDI (elem_reg, arr_reg, 4)
]
let loop_beg = newLab "loop_beg"
let loop_end = newLab "loop_end"
let not_true = newLab "not_true"
let tmp_reg = newReg "tmp_reg"
let loop_header = [ Mips.LABEL (loop_beg)
; Mips.SUB (tmp_reg, i_reg, size_reg)
; Mips.BGEZ (tmp_reg, loop_end) ]
(* map is 'arr[i] = f(old_arr[i])'. *)
let a_size = getElemSize a_type
let loop_map =
[ mipsLoad a_size (res_reg, elem_reg, 0)
; Mips.ADDI(elem_reg, elem_reg, elemSizeToInt a_size)
]
@ applyFunArg(farg, [res_reg], vtable, bool_reg, pos)
@
[ Mips.BEQ (bool_reg, RZ, not_true)
; mipsStore a_size (res_reg, addr_reg, 0)
; Mips.ADDI (j_reg, j_reg, 1)
; Mips.ADDI (addr_reg, addr_reg, elemSizeToInt a_size)
]
let loop_footer =
[ Mips.LABEL not_true
; Mips.ADDI (i_reg, i_reg, 1)
; Mips.J loop_beg
; Mips.LABEL loop_end
; Mips.SW (j_reg,place,0)
]
arr_code
@ get_size
@ dynalloc (size_reg, place, a_type)
@ init_regs
@ loop_header
@ loop_map
@ loop_footer
(* TODO project task 2: see also the comment to replicate.
`scan(f, ne, arr)`: you can inspire yourself from the implementation of
@ -641,8 +743,56 @@ let rec compileExp (e : TypedExp)
the current location of the result iterator at every iteration of
the loop.
*)
| Scan (_, _, _, _, _) ->
failwith "Unimplemented code generation of scan"
| Scan (farg, e_exp, arr_exp, a_type, pos) ->
let size_reg = newReg "size_reg" (* size of input/output array *)
let arr_reg = newReg "arr_reg" (* address of array *)
let elem_reg = newReg "elem_reg" (* address of single element *)
let res_reg = newReg "res_reg"
let nelem_reg = newReg "nelem_reg"
let arr_code = compileExp arr_exp vtable arr_reg
let e_code = compileExp e_exp vtable nelem_reg
let get_size = [ Mips.LW (size_reg, arr_reg, 0) ]
let addr_reg = newReg "addr_reg" (* address of element in new array *)
let i_reg = newReg "i_reg"
let init_regs = [ Mips.ADDI (addr_reg, place, 4)
; Mips.MOVE (i_reg, RZ)
; Mips.ADDI (elem_reg, arr_reg, 4)
]
let loop_beg = newLab "loop_beg"
let loop_end = newLab "loop_end"
let tmp_reg = newReg "tmp_reg"
let loop_header = [ Mips.LABEL (loop_beg)
; Mips.SUB (tmp_reg, i_reg, size_reg)
; Mips.BGEZ (tmp_reg, loop_end) ]
(* map is 'arr[i] = f(old_arr[i])'. *)
let a_size = getElemSize a_type
let loop_map =
[ mipsLoad a_size (res_reg, elem_reg, 0)
; Mips.ADDI(elem_reg, elem_reg, elemSizeToInt a_size)
]
@ applyFunArg(farg, [nelem_reg ; res_reg], vtable, nelem_reg, pos)
@
[ mipsStore a_size (nelem_reg, addr_reg, 0)
; Mips.ADDI (addr_reg, addr_reg, elemSizeToInt a_size)
]
let loop_footer =
[ Mips.ADDI (i_reg, i_reg, 1)
; Mips.J loop_beg
; Mips.LABEL loop_end
]
arr_code
@ e_code
@ get_size
@ dynalloc (size_reg, place, a_type)
@ init_regs
@ loop_header
@ loop_map
@ loop_footer
and applyFunArg ( ff : TypedFunArg
, args : Mips.reg list