elna/lib/Language/Elna/CodeGenerator.hs

69 lines
3.1 KiB
Haskell
Raw Normal View History

2024-08-30 14:55:40 +02:00
module Language.Elna.CodeGenerator
2024-09-24 22:20:57 +02:00
( Statement(..)
2024-09-21 23:35:32 +02:00
, generateCode
2024-08-30 14:55:40 +02:00
) where
2024-09-08 02:08:13 +02:00
import Data.ByteString (ByteString)
2024-09-25 23:06:02 +02:00
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
2024-09-08 02:08:13 +02:00
import Data.Vector (Vector)
import qualified Data.Vector as Vector
2024-09-25 23:06:02 +02:00
import qualified Data.Text.Encoding as Text.Encoding
import Language.Elna.Location (Identifier(..))
2024-09-27 00:22:44 +02:00
import Language.Elna.Intermediate (Operand(..), Quadruple(..))
2024-09-08 02:08:13 +02:00
import qualified Language.Elna.Architecture.RiscV as RiscV
import Language.Elna.SymbolTable (SymbolTable)
2024-09-27 00:22:44 +02:00
import Data.Bits (Bits(..))
2024-09-08 02:08:13 +02:00
2024-09-21 23:35:32 +02:00
data Directive
= GlobalDirective
| FunctionDirective
deriving (Eq, Show)
2024-09-24 22:20:57 +02:00
data Statement
2024-09-21 23:35:32 +02:00
= Instruction RiscV.Instruction
| JumpLabel ByteString [Directive]
2024-09-21 23:35:32 +02:00
deriving Eq
2024-09-25 23:06:02 +02:00
generateCode :: SymbolTable -> HashMap Identifier (Vector Quadruple) -> Vector Statement
generateCode _ = HashMap.foldlWithKey' go Vector.empty
where
go accumulator (Identifier key) value =
let code = Vector.cons (JumpLabel (Text.Encoding.encodeUtf8 key) [GlobalDirective, FunctionDirective])
$ Vector.foldMap quadruple value
in accumulator <> code
quadruple :: Quadruple -> Vector Statement
quadruple StartQuadruple = Vector.fromList
2024-09-27 00:22:44 +02:00
[ Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.SP RiscV.ADDI RiscV.SP (negate 8))
, Instruction (RiscV.BaseInstruction RiscV.Store $ RiscV.S 4 RiscV.SW RiscV.SP RiscV.S0)
, Instruction (RiscV.BaseInstruction RiscV.Store $ RiscV.S 8 RiscV.SW RiscV.SP RiscV.RA)
, Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.S0 RiscV.ADDI RiscV.SP 8)
2024-09-25 23:06:02 +02:00
]
2024-09-27 00:22:44 +02:00
quadruple (ParameterQuadruple (IntOperand intValue))
= Vector.snoc go
$ Instruction (RiscV.BaseInstruction RiscV.Store $ RiscV.S 0 RiscV.SW RiscV.SP RiscV.A0)
where
hi = intValue `shiftR` 12
lo = intValue
go
| intValue >= -2048
, intValue <= 2047 = Vector.singleton
$ Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.A0 RiscV.ADDI RiscV.A0 $ fromIntegral lo)
| intValue .&. 0x800 /= 0 = Vector.fromList
[ Instruction (RiscV.BaseInstruction RiscV.Lui $ RiscV.U RiscV.A0 $ fromIntegral $ succ hi)
, Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.A0 RiscV.ADDI RiscV.A0 $ fromIntegral lo)
]
| otherwise = Vector.fromList
[ Instruction (RiscV.BaseInstruction RiscV.Lui $ RiscV.U RiscV.A0 $ fromIntegral hi)
, Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.A0 RiscV.ADDI RiscV.A0 $ fromIntegral lo)
]
2024-09-25 23:06:02 +02:00
quadruple (CallQuadruple callName _) = Vector.singleton
$ Instruction (RiscV.CallInstruction callName)
quadruple StopQuadruple = Vector.fromList
2024-09-27 00:22:44 +02:00
[ Instruction (RiscV.BaseInstruction RiscV.Load $ RiscV.I RiscV.S0 RiscV.LW RiscV.SP 4)
, Instruction (RiscV.BaseInstruction RiscV.Load $ RiscV.I RiscV.RA RiscV.LW RiscV.SP 8)
, Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.SP RiscV.ADDI RiscV.SP 8)
2024-09-21 23:35:32 +02:00
, Instruction (RiscV.BaseInstruction RiscV.Jalr $ RiscV.I RiscV.RA RiscV.JALR RiscV.Zero 0)
2024-09-08 02:08:13 +02:00
]