-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcompiler.ml
More file actions
123 lines (101 loc) · 4.51 KB
/
compiler.ml
File metadata and controls
123 lines (101 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
(*
* TODO:
* delete all the unwanted labels
*)
#use "code-gen.ml";;
(* Open the scheme file and read from it *)
let file_to_string f =
let ic = open_in f in
let s = really_input_string ic (in_channel_length ic) in
close_in ic;
s;;
(* Transform the scheme code (comes as a string) to expr' using reader, tag parser and semantic analyser
The result is a list of expr'
*)
let string_to_asts s = List.map Semantics.run_semantics
(Tag_Parser.tag_parse_expressions
(Reader.read_sexprs s));;
let primitive_names_to_labels =
["boolean?", "is_boolean"; "float?", "is_float"; "integer?", "is_integer"; "pair?", "is_pair";
"null?", "is_null"; "char?", "is_char"; "vector?", "is_vector"; "string?", "is_string";
"procedure?", "is_procedure"; "symbol?", "is_symbol"; "string-length", "string_length";
"string-ref", "string_ref"; "string-set!", "string_set"; "make-string", "make_string";
"vector-length", "vector_length"; "vector-ref", "vector_ref"; "vector-set!", "vector_set";
"make-vector", "make_vector"; "symbol->string", "symbol_to_string";
"char->integer", "char_to_integer"; "integer->char", "integer_to_char"; "eq?", "is_eq";
"+", "bin_add"; "*", "bin_mul"; "-", "bin_sub"; "/", "bin_div"; "<", "bin_lt"; "=", "bin_equ";
"car", "mycar"; "cdr", "mycdr"; "cons", "mycons"; "set-car!", "set_car"; "set-cdr!", "set_cdr"; "apply", "myapply"];;
let make_prologue consts_tbl fvars_tbl =
let get_const_address const = Code_Gen.get_const_address const consts_tbl in
let get_fvar_address const = "fvar_tbl + 8 * " ^ (string_of_int (Code_Gen.get_free_var_index const fvars_tbl)) in
let make_primitive_closure (prim, label) =
" MAKE_CLOSURE(rax, SOB_NIL_ADDRESS, " ^ label ^ ")
mov [" ^ (get_fvar_address prim) ^ "], rax" in
let make_constant (c, (a, s)) = s in
"
;;; All the macros and the scheme-object printing procedure
;;; are defined in compiler.s
%include \"compiler.s\"
section .bss
malloc_pointer:
resq 1
section .data
const_tbl:
" ^ (String.concat "\n" (List.map make_constant consts_tbl)) ^ "
;;; These macro definitions are required for the primitive
;;; definitions in the epilogue to work properly
%define SOB_VOID_ADDRESS " ^ get_const_address Void ^ "
%define SOB_NIL_ADDRESS " ^ get_const_address (Sexpr Nil) ^ "
%define SOB_FALSE_ADDRESS " ^ get_const_address (Sexpr (Bool false)) ^ "
%define SOB_TRUE_ADDRESS " ^ get_const_address (Sexpr (Bool true)) ^ "
%define FVAR(i) [fvar_tbl+i*WORD_SIZE]
fvar_tbl:
" ^ (String.concat "\n" (List.map (fun _ -> "dq T_UNDEFINED") fvars_tbl)) ^ "
global main
section .text
main:
push rbp
mov rbp, rsp
;; set up the heap
mov rdi, GB(4)
call malloc
mov [malloc_pointer], rax
;; Set up the dummy activation frame
;; The dummy return address is T_UNDEFINED
;; (which a is a macro for 0) so that returning
;; from the top level (which SHOULD NOT HAPPEN
;; AND IS A BUG) will cause a segfault.
push 0
push qword SOB_NIL_ADDRESS
push qword T_UNDEFINED
push rsp
call code_fragment
add rsp, 4*8
ret
code_fragment:
;; Set up the primitive stdlib fvars:
;; Since the primtive procedures are defined in assembly,
;; they are not generated by scheme (define ...) expressions.
;; This is where we emulate the missing (define ...) expressions
;; for all the primitive procedures.
" ^ (String.concat "\n" (List.map make_primitive_closure primitive_names_to_labels)) ^ "
";;
(* **************IMPLEMENT!!!!!************** *)
let epilogue = "exit_program_label: \n ret";;
exception X_missing_input_file;;
try
let infile = Sys.argv.(1) in
let code = (file_to_string "stdlib.scm") ^ (file_to_string infile) in
let asts = string_to_asts code in
let consts_tbl = Code_Gen.make_consts_tbl asts in
let fvars_tbl = Code_Gen.make_fvars_tbl asts in
let generate = Code_Gen.generate consts_tbl fvars_tbl in
let code_fragment = String.concat "\n\n"
(List.map
(fun ast -> (generate ast) ^ "\n call write_sob_if_not_void")
asts) in
let provided_primitives = file_to_string "prims.s" in
print_string ((make_prologue consts_tbl fvars_tbl) ^
code_fragment ^ "\n debug_exit_label: \n jmp exit_program_label" ^
provided_primitives ^ "\n" ^ epilogue)
with Invalid_argument(x) -> raise X_missing_input_file;;