diff --git a/TODO b/TODO index 2d6b5c3..6327ff2 100644 --- a/TODO +++ b/TODO @@ -28,4 +28,3 @@ # Other - Type analysis. -- Move platform dependent code generation into a submodule. diff --git a/elna.cabal b/elna.cabal index 2c80ea5..4f3fc8e 100644 --- a/elna.cabal +++ b/elna.cabal @@ -35,20 +35,21 @@ common warnings library elna-internal import: warnings exposed-modules: - Language.Elna.Allocator Language.Elna.Architecture.RiscV - Language.Elna.AST - Language.Elna.CodeGenerator + Language.Elna.Backend.Allocator + Language.Elna.Backend.Intermediate Language.Elna.CommandLine - Language.Elna.PrinterWriter - Language.Elna.Intermediate + Language.Elna.Frontend.AST + Language.Elna.Frontend.NameAnalysis + Language.Elna.Frontend.Parser + Language.Elna.Frontend.SymbolTable + Language.Elna.Frontend.TypeAnalysis + Language.Elna.Frontend.Types + Language.Elna.Glue Language.Elna.Location - Language.Elna.NameAnalysis Language.Elna.Object.Elf - Language.Elna.Parser - Language.Elna.SymbolTable - Language.Elna.TypeAnalysis - Language.Elna.Types + Language.Elna.RiscV.CodeGenerator + Language.Elna.RiscV.ElfWriter build-depends: exceptions ^>= 0.10, hashable ^>= 1.4.3, diff --git a/lib/Language/Elna/Allocator.hs b/lib/Language/Elna/Backend/Allocator.hs similarity index 85% rename from lib/Language/Elna/Allocator.hs rename to lib/Language/Elna/Backend/Allocator.hs index 3b32de4..9ad849e 100644 --- a/lib/Language/Elna/Allocator.hs +++ b/lib/Language/Elna/Backend/Allocator.hs @@ -1,4 +1,4 @@ -module Language.Elna.Allocator +module Language.Elna.Backend.Allocator ( MachineConfiguration(..) , Store(..) , allocate @@ -6,7 +6,7 @@ module Language.Elna.Allocator import Data.HashMap.Strict (HashMap) import Data.Vector (Vector) -import Language.Elna.Intermediate (Operand(..), Quadruple(..), Variable(..)) +import Language.Elna.Backend.Intermediate (Operand(..), Quadruple(..), Variable(..)) import Language.Elna.Location (Identifier(..)) newtype Store r = Store r @@ -34,6 +34,8 @@ allocate MachineConfiguration{..} = fmap function AddQuadruple (operand operand1) (operand operand2) (Store temporaryRegister) quadruple (SubtractionQuadruple operand1 operand2 _) = SubtractionQuadruple (operand operand1) (operand operand2) (Store temporaryRegister) + quadruple (NegationQuadruple operand1 _) = + NegationQuadruple (operand operand1) (Store temporaryRegister) operand :: Operand Variable -> Operand (Store r) operand (IntOperand x) = IntOperand x operand (VariableOperand _) = VariableOperand (Store temporaryRegister) diff --git a/lib/Language/Elna/Backend/Intermediate.hs b/lib/Language/Elna/Backend/Intermediate.hs new file mode 100644 index 0000000..01a026b --- /dev/null +++ b/lib/Language/Elna/Backend/Intermediate.hs @@ -0,0 +1,46 @@ +module Language.Elna.Backend.Intermediate + ( Operand(..) + , Quadruple(..) + {- , Label(..) -} + , Variable(..) + ) where + +import Data.Int (Int32) +import Data.Word (Word32) +import Data.Text (Text) + +newtype Variable = TempVariable Word32 -- | Variable Text + deriving Eq + +instance Show Variable + where + -- show (Variable variable) = '$' : Text.unpack variable + show (TempVariable variable) = '$' : show variable + +data Operand v + = IntOperand Int32 + | VariableOperand v + deriving (Eq, Show) + +data Quadruple v + = StartQuadruple + | StopQuadruple + | ParameterQuadruple (Operand v) + | CallQuadruple Text Word32 + | AddQuadruple (Operand v) (Operand v) v + | SubtractionQuadruple (Operand v) (Operand v) v + | NegationQuadruple (Operand v) v + {-| GoToQuadruple Label + | AssignQuadruple Operand Variable + | ArrayQuadruple Variable Operand Variable + | ArrayAssignQuadruple Operand Operand Variable + | ProductQuadruple Operand Operand Variable + | DivisionQuadruple Operand Operand Variable + | EqualQuadruple Operand Operand Label + | NonEqualQuadruple Operand Operand Label + | LessQuadruple Operand Operand Label + | GreaterQuadruple Operand Operand Label + | LessOrEqualQuadruple Operand Operand Label + | GreaterOrEqualQuadruple Operand Operand Label + | LabelQuadruple Label -} + deriving (Eq, Show) diff --git a/lib/Language/Elna/AST.hs b/lib/Language/Elna/Frontend/AST.hs similarity index 99% rename from lib/Language/Elna/AST.hs rename to lib/Language/Elna/Frontend/AST.hs index 4861318..738ddcc 100644 --- a/lib/Language/Elna/AST.hs +++ b/lib/Language/Elna/Frontend/AST.hs @@ -1,4 +1,4 @@ -module Language.Elna.AST +module Language.Elna.Frontend.AST ( Declaration(..) , Identifier(..) , Parameter(..) @@ -119,8 +119,8 @@ data Expression = LiteralExpression Literal | SumExpression Expression Expression | SubtractionExpression Expression Expression -{- | VariableExpression VariableAccess | NegationExpression Expression +{- | VariableExpression VariableAccess | ProductExpression Expression Expression | DivisionExpression Expression Expression -} deriving Eq @@ -130,8 +130,8 @@ instance Show Expression show (LiteralExpression literal) = show literal show (SumExpression lhs rhs) = concat [show lhs, " + ", show rhs] show (SubtractionExpression lhs rhs) = concat [show lhs, " - ", show rhs] - {- show (VariableExpression variable) = show variable show (NegationExpression negation) = '-' : show negation + {- show (VariableExpression variable) = show variable show (ProductExpression lhs rhs) = concat [show lhs, " * ", show rhs] show (DivisionExpression lhs rhs) = concat [show lhs, " / ", show rhs] -} {- diff --git a/lib/Language/Elna/NameAnalysis.hs b/lib/Language/Elna/Frontend/NameAnalysis.hs similarity index 97% rename from lib/Language/Elna/NameAnalysis.hs rename to lib/Language/Elna/Frontend/NameAnalysis.hs index 10045e9..2915331 100644 --- a/lib/Language/Elna/NameAnalysis.hs +++ b/lib/Language/Elna/Frontend/NameAnalysis.hs @@ -1,13 +1,13 @@ -module Language.Elna.NameAnalysis +module Language.Elna.Frontend.NameAnalysis ( nameAnalysis , Error(..) ) where import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Vector as Vector -import qualified Language.Elna.SymbolTable as SymbolTable -import qualified Language.Elna.AST as AST -import Language.Elna.SymbolTable +import qualified Language.Elna.Frontend.AST as AST +import qualified Language.Elna.Frontend.SymbolTable as SymbolTable +import Language.Elna.Frontend.SymbolTable ( SymbolTable , Info(..) , ParameterInfo(..) @@ -15,7 +15,7 @@ import Language.Elna.SymbolTable import Control.Monad.Trans.Except (Except, runExcept, throwE) import Data.Functor ((<&>)) import Language.Elna.Location (Identifier(..)) -import Language.Elna.Types (Type(..)) +import Language.Elna.Frontend.Types (Type(..)) import Data.Foldable (traverse_) import Control.Monad (foldM, unless) @@ -142,10 +142,10 @@ expression globalTable (AST.SumExpression lhs rhs) expression globalTable (AST.SubtractionExpression lhs rhs) = expression globalTable lhs >> expression globalTable rhs -{- expression globalTable (AST.VariableExpression variableExpression) = - variableAccess globalTable variableExpression expression globalTable (AST.NegationExpression negation) = expression globalTable negation +{- expression globalTable (AST.VariableExpression variableExpression) = + variableAccess globalTable variableExpression expression globalTable (AST.ProductExpression lhs rhs) = expression globalTable lhs >> expression globalTable rhs diff --git a/lib/Language/Elna/Parser.hs b/lib/Language/Elna/Frontend/Parser.hs similarity index 93% rename from lib/Language/Elna/Parser.hs rename to lib/Language/Elna/Frontend/Parser.hs index 3c98fff..4093f25 100644 --- a/lib/Language/Elna/Parser.hs +++ b/lib/Language/Elna/Frontend/Parser.hs @@ -1,4 +1,4 @@ -module Language.Elna.Parser +module Language.Elna.Frontend.Parser ( Parser , programP ) where @@ -8,7 +8,7 @@ import Control.Monad.Combinators.Expr (Operator(..), makeExprParser) import Data.Text (Text) import qualified Data.Text as Text import Data.Void (Void) -import Language.Elna.AST +import Language.Elna.Frontend.AST ( Declaration(..) , Identifier(..) , Parameter(..) @@ -48,7 +48,7 @@ type Parser = Parsec Void Text literalP :: Parser Literal literalP = {- HexadecimalLiteral <$> (string "0x" *> lexeme Lexer.hexadecimal) - <|> -} IntegerLiteral <$> lexeme Lexer.decimal + <|> -} IntegerLiteral <$> Lexer.signed space integerP {- <|> CharacterLiteral <$> lexeme charP <|> BooleanLiteral <$> (symbol "true" $> True) <|> BooleanLiteral <$> (symbol "false" $> False) @@ -72,16 +72,16 @@ termP = choice operatorTable :: [[Operator Parser Expression]] operatorTable = - [{- unaryOperator - , factorOperator - ,-} termOperator + [ unaryOperator + -- , factorOperator + , termOperator ] where - {- unaryOperator = + unaryOperator = [ prefix "-" NegationExpression , prefix "+" id ] - factorOperator = + {- factorOperator = [ binary "*" ProductExpression , binary "/" DivisionExpression ] -} @@ -89,7 +89,7 @@ operatorTable = [ binary "+" SumExpression , binary "-" SubtractionExpression ] - -- prefix name f = Prefix (f <$ symbol name) + prefix name f = Prefix (f <$ symbol name) binary name f = InfixL (f <$ symbol name) expressionP :: Parser Expression @@ -144,6 +144,9 @@ commaP = void $ symbol "," semicolonP :: Parser () semicolonP = void $ symbol ";" +integerP :: Integral a => Parser a +integerP = lexeme Lexer.decimal + identifierP :: Parser Identifier identifierP = let wordParser = (:) <$> letterChar <*> many alphaNumChar "identifier" @@ -166,7 +169,7 @@ typeExpressionP = arrayTypeExpression "type expression" where arrayTypeExpression = ArrayType - <$> (symbol "array" *> bracketsP (lexeme Lexer.decimal)) + <$> (symbol "array" *> bracketsP integerP) <*> (symbol "of" *> typeExpressionP) procedureDeclarationP :: Parser Declaration diff --git a/lib/Language/Elna/SymbolTable.hs b/lib/Language/Elna/Frontend/SymbolTable.hs similarity index 96% rename from lib/Language/Elna/SymbolTable.hs rename to lib/Language/Elna/Frontend/SymbolTable.hs index 97d9621..9ace33f 100644 --- a/lib/Language/Elna/SymbolTable.hs +++ b/lib/Language/Elna/Frontend/SymbolTable.hs @@ -1,4 +1,4 @@ -module Language.Elna.SymbolTable +module Language.Elna.Frontend.SymbolTable ( SymbolTable , Info(..) , ParameterInfo(..) @@ -22,7 +22,7 @@ import Data.Maybe (isJust) import Data.Vector (Vector) import qualified Data.Vector as Vector import Language.Elna.Location (Identifier(..)) -import Language.Elna.Types (Type(..), intType) +import Language.Elna.Frontend.Types (Type(..), intType) import Prelude hiding (lookup) data SymbolTable = SymbolTable (Maybe SymbolTable) (HashMap Identifier Info) diff --git a/lib/Language/Elna/TypeAnalysis.hs b/lib/Language/Elna/Frontend/TypeAnalysis.hs similarity index 97% rename from lib/Language/Elna/TypeAnalysis.hs rename to lib/Language/Elna/Frontend/TypeAnalysis.hs index ac61b62..7d0b050 100644 --- a/lib/Language/Elna/TypeAnalysis.hs +++ b/lib/Language/Elna/Frontend/TypeAnalysis.hs @@ -1,10 +1,10 @@ -module Language.Elna.TypeAnalysis +module Language.Elna.Frontend.TypeAnalysis ( typeAnalysis , -- Error(..) ) where -import qualified Language.Elna.AST as AST -import Language.Elna.SymbolTable ({-Info(..), ParameterInfo(..), -}SymbolTable) +import qualified Language.Elna.Frontend.AST as AST +import Language.Elna.Frontend.SymbolTable ({-Info(..), ParameterInfo(..), -}SymbolTable) typeAnalysis :: SymbolTable -> AST.Program -> () -- Maybe Error typeAnalysis _globalTable = const () {- either Just (const Nothing) diff --git a/lib/Language/Elna/Types.hs b/lib/Language/Elna/Frontend/Types.hs similarity index 94% rename from lib/Language/Elna/Types.hs rename to lib/Language/Elna/Frontend/Types.hs index ee76ec8..a3cc730 100644 --- a/lib/Language/Elna/Types.hs +++ b/lib/Language/Elna/Frontend/Types.hs @@ -1,4 +1,4 @@ -module Language.Elna.Types +module Language.Elna.Frontend.Types ( Type(..) , addressByteSize , booleanType diff --git a/lib/Language/Elna/Intermediate.hs b/lib/Language/Elna/Glue.hs similarity index 79% rename from lib/Language/Elna/Intermediate.hs rename to lib/Language/Elna/Glue.hs index 32c951e..2313b2b 100644 --- a/lib/Language/Elna/Intermediate.hs +++ b/lib/Language/Elna/Glue.hs @@ -1,95 +1,54 @@ -module Language.Elna.Intermediate - ( Operand(..) - , Quadruple(..) - {- , Label(..) -} - , Variable(..) - , intermediate +module Language.Elna.Glue + ( glue ) where +import Control.Monad.Trans.State (State, get, modify', runState) import Data.Bifunctor (Bifunctor(..)) +import Data.Foldable (Foldable(..)) import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap +import Data.Maybe (catMaybes) import Data.Vector (Vector) import qualified Data.Vector as Vector -import Data.Int (Int32) import Data.Word (Word32) -import Data.Text (Text) -import qualified Language.Elna.AST as AST -import Language.Elna.SymbolTable (SymbolTable{-, Info(..) -}) -import Data.Foldable (Foldable(..)) -import Control.Monad.Trans.State (State, get, modify', runState) -import Data.Maybe (catMaybes) +import qualified Language.Elna.Frontend.AST as AST +import Language.Elna.Backend.Intermediate (Operand(..), Quadruple(..), Variable(..)) +import Language.Elna.Frontend.SymbolTable (SymbolTable{-, Info(..) -}) -newtype Variable = TempVariable Word32 -- | Variable Text - deriving Eq +newtype Glue a = Glue + { runGlue :: State Word32 a } -instance Show Variable +instance Functor Glue where - -- show (Variable variable) = '$' : Text.unpack variable - show (TempVariable variable) = '$' : show variable + fmap f (Glue x) = Glue $ f <$> x -data Operand v - = IntOperand Int32 - | VariableOperand v - deriving (Eq, Show) - -data Quadruple v - = StartQuadruple - | StopQuadruple - | ParameterQuadruple (Operand v) - | CallQuadruple Text Word32 - | AddQuadruple (Operand v) (Operand v) v - | SubtractionQuadruple (Operand v) (Operand v) v - {-| GoToQuadruple Label - | AssignQuadruple Operand Variable - | ArrayQuadruple Variable Operand Variable - | ArrayAssignQuadruple Operand Operand Variable - | ProductQuadruple Operand Operand Variable - | DivisionQuadruple Operand Operand Variable - | NegationQuadruple Operand Variable - | EqualQuadruple Operand Operand Label - | NonEqualQuadruple Operand Operand Label - | LessQuadruple Operand Operand Label - | GreaterQuadruple Operand Operand Label - | LessOrEqualQuadruple Operand Operand Label - | GreaterOrEqualQuadruple Operand Operand Label - | LabelQuadruple Label -} - deriving (Eq, Show) - -newtype Intermediate a = Intermediate - { runIntermediate :: State Word32 a } - -instance Functor Intermediate +instance Applicative Glue where - fmap f (Intermediate x) = Intermediate $ f <$> x + pure = Glue . pure + (Glue f) <*> (Glue x) = Glue $ f <*> x -instance Applicative Intermediate +instance Monad Glue where - pure = Intermediate . pure - (Intermediate f) <*> (Intermediate x) = Intermediate $ f <*> x + (Glue x) >>= f = Glue $ x >>= (runGlue . f) -instance Monad Intermediate - where - (Intermediate x) >>= f = Intermediate $ x >>= (runIntermediate . f) - -intermediate :: SymbolTable -> AST.Program -> HashMap AST.Identifier (Vector (Quadruple Variable)) -intermediate globalTable +glue :: SymbolTable -> AST.Program -> HashMap AST.Identifier (Vector (Quadruple Variable)) +glue globalTable = fst . flip runState 0 - . runIntermediate + . runGlue . program globalTable program :: SymbolTable -> AST.Program - -> Intermediate (HashMap AST.Identifier (Vector (Quadruple Variable))) + -> Glue (HashMap AST.Identifier (Vector (Quadruple Variable))) program globalTable (AST.Program declarations) = HashMap.fromList . catMaybes <$> traverse (declaration globalTable) declarations declaration :: SymbolTable -> AST.Declaration - -> Intermediate (Maybe (AST.Identifier, Vector (Quadruple Variable))) + -> Glue (Maybe (AST.Identifier, Vector (Quadruple Variable))) declaration globalTable (AST.ProcedureDeclaration procedureName _ _ statements) = Just . (procedureName,) @@ -99,7 +58,7 @@ declaration globalTable (AST.ProcedureDeclaration procedureName _ _ statements) <$> traverse (statement globalTable) statements -- declaration (AST.TypeDefinition _ _) accumulator = pure accumulator -statement :: SymbolTable -> AST.Statement -> Intermediate (Vector (Quadruple Variable)) +statement :: SymbolTable -> AST.Statement -> Glue (Vector (Quadruple Variable)) statement _ AST.EmptyStatement = pure mempty statement localTable (AST.CallStatement (AST.Identifier callName) arguments) = do visitedArguments <- traverse (expression localTable) arguments @@ -150,10 +109,10 @@ statement localTable (AST.WhileStatement whileCondition whileStatement) = do statement localTable (AST.CompoundStatement statements) = fold <$> traverse (statement localTable) statements -} -createTemporary :: Intermediate Variable +createTemporary :: Glue Variable createTemporary = do - currentCounter <- Intermediate get - Intermediate $ modify' (+ 1) + currentCounter <- Glue get + Glue $ modify' (+ 1) pure $ TempVariable currentCounter {- @@ -171,10 +130,10 @@ instance Show Label where show (Label label) = '.' : Text.unpack label -createLabel :: Intermediate Label +createLabel :: Glue Label createLabel = do - currentCounter <- Intermediate $ gets labelCounter - Intermediate $ modify' modifier + currentCounter <- Glue $ gets labelCounter + Glue $ modify' modifier pure $ Label $ Text.Lazy.toStrict @@ -188,7 +147,7 @@ createLabel = do condition :: SymbolTable -> AST.Condition - -> Intermediate (Vector Quadruple, Label -> Quadruple) + -> Glue (Vector Quadruple, Label -> Quadruple) condition localTable (AST.EqualCondition lhs rhs) = do (lhsOperand, lhsStatements) <- expression localTable lhs (rhsOperand, rhsStatements) <- expression localTable rhs @@ -235,7 +194,7 @@ variableAccess -> Maybe Operand -> Type -> Vector Quadruple - -> Intermediate (AST.Identifier, Maybe Operand, Vector Quadruple) + -> Glue (AST.Identifier, Maybe Operand, Vector Quadruple) variableAccess _ (AST.VariableAccess identifier) accumulatedIndex _ accumulatedStatements = pure (identifier, accumulatedIndex, accumulatedStatements) variableAccess localTable (AST.ArrayAccess access1 index1) Nothing (ArrayType _ baseType) _ = do @@ -260,12 +219,20 @@ variableType (AST.VariableAccess identifier) symbolTable variableType (AST.ArrayAccess arrayAccess' _) symbolTable = variableType arrayAccess' symbolTable -} -expression :: SymbolTable -> AST.Expression -> Intermediate (Operand Variable, Vector (Quadruple Variable)) +expression :: SymbolTable -> AST.Expression -> Glue (Operand Variable, Vector (Quadruple Variable)) expression localTable = \case (AST.LiteralExpression literal') -> pure (literal literal', mempty) (AST.SumExpression lhs rhs) -> binaryExpression AddQuadruple lhs rhs (AST.SubtractionExpression lhs rhs) -> binaryExpression SubtractionQuadruple lhs rhs + (AST.NegationExpression negation) -> do + (operand, statements) <- expression localTable negation + tempVariable <- createTemporary + let negationQuadruple = NegationQuadruple operand tempVariable + pure + ( VariableOperand tempVariable + , Vector.snoc statements negationQuadruple + ) {- (AST.VariableExpression variableExpression) -> do let variableType' = variableType variableExpression localTable variableAccess' <- variableAccess localTable variableExpression Nothing variableType' mempty @@ -279,14 +246,6 @@ expression localTable = \case ( VariableOperand arrayAddress , Vector.snoc statements arrayStatement ) - (AST.NegationExpression negation) -> do - (operand, statements) <- expression localTable negation - tempVariable <- createTemporary - let negationQuadruple = NegationQuadruple operand tempVariable - pure - ( VariableOperand tempVariable - , Vector.snoc statements negationQuadruple - ) (AST.ProductExpression lhs rhs) -> binaryExpression ProductQuadruple lhs rhs (AST.DivisionExpression lhs rhs) -> diff --git a/lib/Language/Elna/CodeGenerator.hs b/lib/Language/Elna/RiscV/CodeGenerator.hs similarity index 89% rename from lib/Language/Elna/CodeGenerator.hs rename to lib/Language/Elna/RiscV/CodeGenerator.hs index a561cb8..d20488c 100644 --- a/lib/Language/Elna/CodeGenerator.hs +++ b/lib/Language/Elna/RiscV/CodeGenerator.hs @@ -1,4 +1,4 @@ -module Language.Elna.CodeGenerator +module Language.Elna.RiscV.CodeGenerator ( Statement(..) , generateRiscV , riscVConfiguration @@ -11,10 +11,10 @@ import Data.Int (Int32) import Data.Vector (Vector) import qualified Data.Vector as Vector import qualified Data.Text.Encoding as Text.Encoding -import Language.Elna.Allocator (MachineConfiguration(..), Store(..)) -import Language.Elna.Location (Identifier(..)) -import Language.Elna.Intermediate (Operand(..), Quadruple(..)) import qualified Language.Elna.Architecture.RiscV as RiscV +import Language.Elna.Backend.Allocator (MachineConfiguration(..), Store(..)) +import Language.Elna.Backend.Intermediate (Operand(..), Quadruple(..)) +import Language.Elna.Location (Identifier(..)) import Data.Bits (Bits(..)) data Directive @@ -91,7 +91,8 @@ quadruple (AddQuadruple operand1 operand2 (Store register)) in Vector.snoc statements $ Instruction $ RiscV.BaseInstruction RiscV.Op - $ RiscV.R register RiscV.ADD register operandRegister (RiscV.Funct7 0b0000000) + $ RiscV.R register RiscV.ADD register operandRegister + $ RiscV.Funct7 0b0000000 quadruple (SubtractionQuadruple operand1 operand2 (Store register)) | IntOperand immediateOperand1 <- operand1 , IntOperand immediateOperand2 <- operand2 = @@ -102,7 +103,8 @@ quadruple (SubtractionQuadruple operand1 operand2 (Store register)) Store operandRegister2 = variableOperand2 in pure $ Instruction $ RiscV.BaseInstruction RiscV.Op - $ RiscV.R register RiscV.SUB operandRegister1 operandRegister2 (RiscV.Funct7 0b0100000) + $ RiscV.R register RiscV.SUB operandRegister1 operandRegister2 + $ RiscV.Funct7 0b0100000 | IntOperand immediateOperand1 <- operand1 , VariableOperand variableOperand2 <- operand2 = let statements1 = lui immediateOperand1 register @@ -110,7 +112,8 @@ quadruple (SubtractionQuadruple operand1 operand2 (Store register)) in Vector.snoc statements1 $ Instruction $ RiscV.BaseInstruction RiscV.Op - $ RiscV.R register RiscV.SUB register operandRegister2 (RiscV.Funct7 0b0100000) + $ RiscV.R register RiscV.SUB register operandRegister2 + $ RiscV.Funct7 0b0100000 | VariableOperand variableOperand1 <- operand1 , IntOperand immediateOperand2 <- operand2 = let statements2 = lui (negate immediateOperand2) register @@ -118,7 +121,17 @@ quadruple (SubtractionQuadruple operand1 operand2 (Store register)) in Vector.snoc statements2 $ Instruction $ RiscV.BaseInstruction RiscV.Op - $ RiscV.R register RiscV.ADD register operandRegister1 (RiscV.Funct7 0b0000000) + $ RiscV.R register RiscV.ADD register operandRegister1 + $ RiscV.Funct7 0b0000000 +quadruple (NegationQuadruple operand1 (Store register)) + | IntOperand immediateOperand1 <- operand1 = lui (negate immediateOperand1) register + | VariableOperand variableOperand1 <- operand1 = + let Store operandRegister1 = variableOperand1 + in Vector.singleton + $ Instruction + $ RiscV.BaseInstruction RiscV.Op + $ RiscV.R register RiscV.SUB RiscV.Zero operandRegister1 + $ RiscV.Funct7 0b0100000 loadImmediateOrRegister :: RiscVOperand -> RiscV.XRegister -> (RiscV.XRegister, Vector Statement) loadImmediateOrRegister (IntOperand intValue) targetRegister = diff --git a/lib/Language/Elna/PrinterWriter.hs b/lib/Language/Elna/RiscV/ElfWriter.hs similarity index 99% rename from lib/Language/Elna/PrinterWriter.hs rename to lib/Language/Elna/RiscV/ElfWriter.hs index 40b60de..a83aca3 100644 --- a/lib/Language/Elna/PrinterWriter.hs +++ b/lib/Language/Elna/RiscV/ElfWriter.hs @@ -1,5 +1,5 @@ -- | Writer assembler to an object file. -module Language.Elna.PrinterWriter +module Language.Elna.RiscV.ElfWriter ( riscv32Elf ) where @@ -44,7 +44,7 @@ import qualified Language.Elna.Architecture.RiscV as RiscV import qualified Data.Text.Encoding as Text.Encoding import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Trans.State (get) -import Language.Elna.CodeGenerator (Statement(..)) +import Language.Elna.RiscV.CodeGenerator (Statement(..)) import qualified Data.HashSet as HashSet import GHC.Records (HasField(..)) diff --git a/src/Main.hs b/src/Main.hs index 456c5ad..e5a217f 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -3,14 +3,14 @@ module Main ) where import Language.Elna.CommandLine (CommandLine(..), commandLine, execParser) -import Language.Elna.PrinterWriter (riscv32Elf) import Language.Elna.Object.Elf (elfObject) -import Language.Elna.Allocator (allocate) -import Language.Elna.Parser (programP) -import Language.Elna.NameAnalysis (nameAnalysis) -import Language.Elna.TypeAnalysis (typeAnalysis) -import Language.Elna.Intermediate (intermediate) -import Language.Elna.CodeGenerator (generateRiscV, riscVConfiguration) +import Language.Elna.Backend.Allocator (allocate) +import Language.Elna.Glue (glue) +import Language.Elna.Frontend.NameAnalysis (nameAnalysis) +import Language.Elna.Frontend.Parser (programP) +import Language.Elna.Frontend.TypeAnalysis (typeAnalysis) +import Language.Elna.RiscV.CodeGenerator (generateRiscV, riscVConfiguration) +import Language.Elna.RiscV.ElfWriter (riscv32Elf) import Data.Maybe (fromMaybe) import System.FilePath (replaceExtension, takeFileName) import Text.Megaparsec (runParser, errorBundlePretty) @@ -34,6 +34,6 @@ main = execParser commandLine >>= withCommandLine let _ = typeAnalysis symbolTable program instructions = generateRiscV $ allocate riscVConfiguration - $ intermediate symbolTable program + $ glue symbolTable program in elfObject output $ riscv32Elf instructions diff --git a/tests/expectations/parse_negative_numbers.txt b/tests/expectations/parse_negative_numbers.txt new file mode 100644 index 0000000..de71f88 --- /dev/null +++ b/tests/expectations/parse_negative_numbers.txt @@ -0,0 +1 @@ +-8 diff --git a/tests/expectations/print_negate.txt b/tests/expectations/print_negate.txt new file mode 100644 index 0000000..de71f88 --- /dev/null +++ b/tests/expectations/print_negate.txt @@ -0,0 +1 @@ +-8 diff --git a/tests/vm/parse_negative_numbers.elna b/tests/vm/parse_negative_numbers.elna new file mode 100644 index 0000000..ce5d797 --- /dev/null +++ b/tests/vm/parse_negative_numbers.elna @@ -0,0 +1,3 @@ +proc main() { + printi(-8); +} diff --git a/tests/vm/print_negate.elna b/tests/vm/print_negate.elna new file mode 100644 index 0000000..791bc81 --- /dev/null +++ b/tests/vm/print_negate.elna @@ -0,0 +1,3 @@ +proc main() { + printi(-(8)); +}