blob: 9e0a9a4a643aa05bdf7978dcb64acc2309bfded3 (
plain)
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
|
(ns cljcc.compiler
(:require [cljcc.parser :as p]
[instaparse.core :as insta]
[clojure.edn :as edn]
[cljcc.util :refer [get-os]]
[clojure.string :as str]))
(defn transform-function [return-type identifier args body]
{:op :function
:identifier identifier
:args args
:body body})
(defn ast->compile [ast]
(insta/transform
{:function transform-function
:identifier str
:constant (comp edn/read-string str)
:exp (fn [v]
{:op :movl
:src v
:dst :eax})
:statement (fn [_ v]
[v {:op :ret}])}
ast))
(defn handle-function-name [name]
(if (= :mac (get-os))
(str "_" name)
name))
(defn emit-instruction
([inst]
(str " " (symbol inst)))
([inst src dst]
(str " " (symbol inst) " " "$" src ", %" (symbol dst))))
(defn statement-fn [stmt]
(condp = (:op stmt)
:ret (emit-instruction :ret)
:movl (emit-instruction (:op stmt) (:src stmt) (:dst stmt))))
(statement-fn {:op :movl :src 1 :dst :eax})
(defn emit-function-assembly [fn-ast]
(let [name (handle-function-name (:identifier fn-ast))
globl-line (str " .globl " name)
fn-start-line (str name ":")
body-statements (map statement-fn (:body fn-ast))]
(flatten [globl-line fn-start-line body-statements])))
(def linux-assembly-end ".section .note.GNU-stack,\"\",@progbits")
(defn il->assembly [il]
(let [fn-assembly (emit-function-assembly (first il))]
(if (= :linux (get-os))
(concat fn-assembly [linux-assembly-end])
fn-assembly)))
(conj [1 2 3] 1)
(defn join-assembly [assembly-lines]
(str/join "\n" assembly-lines))
(defn run-compile [source]
(-> source
p/parse
ast->compile
il->assembly
join-assembly))
(comment
(def ex "int main(void) {return 2;}")
(-> ex
p/parse)
(-> ex
p/parse
ast->compile)
(-> ex
p/parse
ast->compile
il->assembly
join-assembly)
,)
|