diff options
Diffstat (limited to 'src/cljcc/emit.clj')
| -rw-r--r-- | src/cljcc/emit.clj | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/cljcc/emit.clj b/src/cljcc/emit.clj new file mode 100644 index 0000000..3cd4f00 --- /dev/null +++ b/src/cljcc/emit.clj @@ -0,0 +1,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) + + ()) |
