aboutsummaryrefslogtreecommitdiff
path: root/BuildIR.hs
diff options
context:
space:
mode:
Diffstat (limited to 'BuildIR.hs')
-rw-r--r--BuildIR.hs49
1 files changed, 47 insertions, 2 deletions
diff --git a/BuildIR.hs b/BuildIR.hs
index a4be797..c64adb1 100644
--- a/BuildIR.hs
+++ b/BuildIR.hs
@@ -23,6 +23,7 @@ data BuildState = BuildState
scopeStack :: [Scope],
loopStack :: [Id],
currentBlock :: Id,
+ errorBlock :: Id,
blockMap :: Map.Map Id BB }
initBuildState :: BuildState
@@ -31,6 +32,7 @@ initBuildState = BuildState
scopeStack = [],
loopStack = [],
currentBlock = undefined,
+ errorBlock = undefined,
blockMap = Map.empty }
newtype BuildM a = BuildM {unBuildM :: StateT BuildState (Except String) a}
@@ -56,6 +58,9 @@ newBlockNoSwitch = do
modify $ \s -> s {blockMap = Map.insert i block (blockMap s)}
return i
+setErrorBlock :: Id -> BuildM ()
+setErrorBlock i = modify $ \s -> s {errorBlock = i}
+
addIns :: IRIns -> BuildM ()
addIns ins =
modify $ \s -> s {
@@ -121,6 +126,8 @@ buildIR (Program vars funcs) =
clearBlockMap
firstid <- newBlock
lastid <- newBlockNoSwitch
+ makeErrorBlock >>= setErrorBlock
+ switchBlock firstid
withScope $ do
forM_ al $ \(at, an) -> scopeInsert an (Argument (sizeof at) an) at
convertBlock bl lastid
@@ -129,6 +136,13 @@ buildIR (Program vars funcs) =
bblist <- getAllBlocks
return $ IRFunc rt n al bblist firstid
+ makeErrorBlock :: BuildM Id
+ makeErrorBlock = do
+ bl <- newBlock
+ addIns $ ICall "_builtin_outofbounds" []
+ setTerm IUnreachable
+ return bl
+
result :: BuildM IRProgram
result = do
withScope $ do
@@ -196,6 +210,9 @@ convertStatement (SReturn (Just e)) _ = do
setTerm $ IRetr ref
convertStatement (SExpr e) nextnext = do
void $ convertExpression e nextnext
+convertStatement SDebugger nextnext = do
+ addIns IDebugger
+ setTerm $ IJmp nextnext
convertExpression :: Expression -> Id -> BuildM Ref
convertExpression (ELit (LInt n) _) nextnext = do
@@ -282,6 +299,9 @@ convertExpression (EBin bo e1 e2 _) nextnext = do
BOGeq -> addIns $ IAri AGeq ref ref1 ref2
BOLeq -> addIns $ IAri ALeq ref ref1 ref2
BOPow -> error $ "Pow operator not implemented"
+ BOBitAnd -> addIns $ IAri AAnd ref ref1 ref2
+ BOBitOr -> addIns $ IAri AOr ref ref1 ref2
+ BOBitXor -> addIns $ IAri AXor ref ref1 ref2
BOAnd -> undefined
BOOr -> undefined
setTerm $ IJmp nextnext
@@ -301,6 +321,15 @@ convertExpression (ESubscript arr sub t) nextnext = do
offref <- genTemp (refSize subref)
off8ref <- genTemp (refSize subref)
elemptr <- genTemp (refSize arrref)
+ arrsz <- genTemp (sizeof TInt)
+
+ errbl <- gets errorBlock
+
+ addIns $ ILoad arrsz arrref
+ bl4 <- newBlockNoSwitch
+ setTerm $ IJcc CUGeq subref arrsz errbl bl4
+
+ switchBlock bl4
addIns $ IAri AMul offref subref (Constant (refSize subref) (fromIntegral elemsz))
addIns $ IAri AAdd off8ref offref (Constant (refSize subref) (fromIntegral $ sizeof TInt))
addIns $ IAri AAdd elemptr arrref off8ref
@@ -355,7 +384,15 @@ convertAsExpression (AESubscript ae2 expr mrt) valueref nextnext = do
offref' <- genTemp (sizeof TInt)
offref <- genTemp (sizeof TInt)
elemptr <- genTemp (sizeof TInt)
- -- TODO: do bounds checking
+ arrsz <- genTemp (sizeof TInt)
+
+ errbl <- gets errorBlock
+
+ addIns $ ILoad arrsz ae2ref
+ bl3 <- newBlockNoSwitch
+ setTerm $ IJcc CUGeq subref arrsz errbl bl3
+
+ switchBlock bl3
addIns $ IAri AMul offref' subref (Constant (sizeof TInt) (fromIntegral elemsz))
addIns $ IAri AAdd offref offref' (Constant (sizeof TInt) (fromIntegral $ sizeof TInt))
addIns $ IAri AAdd elemptr ae2ref offref
@@ -381,7 +418,15 @@ convertAsExpression (AESubscript ae2 expr mrt) valueref nextnext = do
offref' <- genTemp (sizeof TInt)
offref <- genTemp (sizeof TInt)
elemptr <- genTemp (sizeof TInt)
- -- TODO: do bounds checking
+ arrsz <- genTemp (sizeof TInt)
+
+ errbl <- gets errorBlock
+
+ addIns $ ILoad arrsz ref
+ bl3 <- newBlockNoSwitch
+ setTerm $ IJcc CUGeq eref arrsz errbl bl3
+
+ switchBlock bl3
addIns $ IAri AMul offref' eref (Constant (sizeof TInt) (fromIntegral elemsz))
addIns $ IAri AAdd offref offref' (Constant (sizeof TInt) (fromIntegral $ sizeof TInt))
addIns $ IAri AAdd elemptr ref offref