aboutsummaryrefslogtreecommitdiff
path: root/src/cljcc/emit.clj
blob: 3cd4f009a2b26fadbbab5bd97b2f7af25975b3b8 (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
(ns cljcc.emit
  (:require [cljcc.parser :as p]
            [cljcc.util :refer [get-os]]
            [clojure.string :as str]))

(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))))

(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 emit-assembly [ast]
  (let [fn-assembly (emit-function-assembly (first ast))]
    (if (= :linux (get-os))
      (concat fn-assembly [linux-assembly-end])
      fn-assembly)))

(defn join-assembly [assembly-lines]
  (str/join "\n" assembly-lines))

(comment

  (def ex "int main(void) {return 2;}")

  (-> ex
      p/parse)

  ())