aboutsummaryrefslogtreecommitdiff
path: root/src/cljcc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cljcc')
-rw-r--r--src/cljcc/analyze/typecheck.clj31
-rw-r--r--src/cljcc/schema.clj7
-rw-r--r--src/cljcc/tacky.clj30
-rw-r--r--src/cljcc/util.clj16
4 files changed, 50 insertions, 34 deletions
diff --git a/src/cljcc/analyze/typecheck.clj b/src/cljcc/analyze/typecheck.clj
index 0c5d155..e042adc 100644
--- a/src/cljcc/analyze/typecheck.clj
+++ b/src/cljcc/analyze/typecheck.clj
@@ -7,7 +7,8 @@
[cljcc.symbol :as sym]
[cljcc.analyze.resolve :as r]
[cljcc.analyze.label-loops :as l]
- [cljcc.exception :as exc]))
+ [cljcc.exception :as exc]
+ [cljcc.util :as u]))
(declare typecheck-block typecheck-declaration to-static-init)
@@ -54,31 +55,15 @@
:logical-not (set-type unary-exp {:type :int})
(set-type unary-exp (get-type typed-inner-e)))))
-(defn- get-type-size [t]
- (condp = t
- {:type :int} 5
- {:type :uint} 5
- {:type :long} 10
- {:type :ulong} 10
- (exc/analyzer-error "Invalid type passed to get-type-size." {:type t})))
-
-(defn type-signed? [t]
- (condp = t
- {:type :int} true
- {:type :long} true
- {:type :uint} false
- {:type :ulong} false
- (exc/analyzer-error "Invalid type passed to type-signed?." {:type t})))
-
(defn- get-common-type [t1 t2]
(cond
(= t1 t2) t1
- (= (get-type-size t1)
- (get-type-size t2)) (if (type-signed? t1)
- t2
- t1)
- (> (get-type-size t1)
- (get-type-size t2)) t1
+ (= (u/get-type-size t1)
+ (u/get-type-size t2)) (if (u/type-signed? t1)
+ t2
+ t1)
+ (> (u/get-type-size t1)
+ (u/get-type-size t2)) t1
:else t2))
(defn- convert-to-exp
diff --git a/src/cljcc/schema.clj b/src/cljcc/schema.clj
index 6a4fb1f..46aa316 100644
--- a/src/cljcc/schema.clj
+++ b/src/cljcc/schema.clj
@@ -382,6 +382,12 @@
[:src #'TackyVal]
[:dst #'TackyVal]])
+(def TackyZeroExtend
+ [:map
+ [:type [:= :zero-extend]]
+ [:src #'TackyVal]
+ [:dst #'TackyVal]])
+
(def TackyUnary
[:map
[:type [:= :unary]]
@@ -437,6 +443,7 @@
[:return #'TackyReturn]
[:sign-extend #'TackySignExtend]
[:truncate #'TackyTruncate]
+ [:zero-extend #'TackyZeroExtend]
[:unary #'TackyUnary]
[:binary #'TackyBinary]
[:copy #'TackyCopy]
diff --git a/src/cljcc/tacky.clj b/src/cljcc/tacky.clj
index 678c74e..b88411e 100644
--- a/src/cljcc/tacky.clj
+++ b/src/cljcc/tacky.clj
@@ -5,6 +5,7 @@
[cljcc.parser :as p]
[cljcc.exception :as exc]
[cljcc.symbol :as sym]
+ [malli.core :as m]
[malli.dev.pretty :as pretty]
[cljcc.analyze.typecheck :as tc]
[cljcc.analyze.core :as a]
@@ -118,6 +119,11 @@
:src src
:dst dst})
+(defn- zero-extend-instruction [src dst]
+ {:type :zero-extend
+ :src src
+ :dst dst})
+
(defn- copy-instruction [src dst]
{:type :copy
:src src
@@ -187,15 +193,18 @@
value
(let [dst (variable "cast_")
_ (add-var-to-symbol dst target-type symbols)
+ inner-type (tc/get-type typed-inner)
{res :val
- insts :instructions} value]
- (if (= :long (:type target-type))
- {:val dst
- :instructions (flatten [insts
- (sign-extend-instruction res dst)])}
- {:val dst
- :instructions (flatten [insts
- (truncate-instruction res dst)])}))))
+ insts :instructions} value
+ cast-i (cond
+ (= (u/get-type-size target-type)
+ (u/get-type-size inner-type)) (copy-instruction res dst)
+ (< (u/get-type-size target-type)
+ (u/get-type-size inner-type)) (truncate-instruction res dst)
+ (u/type-signed? inner-type) (sign-extend-instruction res dst)
+ :else (zero-extend-instruction res dst))]
+ {:val dst
+ :instructions (flatten [insts cast-i])})))
(defmethod exp-handler :unary-exp
[exp symbols]
@@ -517,9 +526,8 @@
symbols (atom ident->symbol)
function-instructions (tacky-function-instructions ast symbols)
program (vec (concat variable-instructions function-instructions))
- ;_ (m/coerce s/TackyProgram program)
- ;_ (m/coerce s/SymbolMap @symbols)
- ]
+ _ (m/coerce s/TackyProgram program)
+ _ (m/coerce s/SymbolMap @symbols)]
{:program program
:ident->symbol @symbols}))
diff --git a/src/cljcc/util.clj b/src/cljcc/util.clj
index eb77ad6..c9fc208 100644
--- a/src/cljcc/util.clj
+++ b/src/cljcc/util.clj
@@ -110,3 +110,19 @@
[v]
(and (>= v Integer/MIN_VALUE)
(<= v Integer/MAX_VALUE)))
+
+(defn get-type-size [t]
+ (condp = t
+ {:type :int} 5
+ {:type :uint} 5
+ {:type :long} 10
+ {:type :ulong} 10
+ (exc/analyzer-error "Invalid type passed to get-type-size." {:type t})))
+
+(defn type-signed? [t]
+ (condp = t
+ {:type :int} true
+ {:type :long} true
+ {:type :uint} false
+ {:type :ulong} false
+ (exc/analyzer-error "Invalid type passed to type-signed?." {:type t})))