diff --git a/TODO b/TODO index ef7c324..3731f6e 100644 --- a/TODO +++ b/TODO @@ -17,8 +17,9 @@ # Register allocation -- Temporary variables always use the same register, t0. Allocate registers for - temporaries. +- Each temporary variales gets a tn register where n is the variable index. If + there more variables the allocation will fail with out of bounds runtime + error. Implement spill over. # Prarsing and abstract syntax tree @@ -27,3 +28,4 @@ # Other - Type analysis. +- Generate call a to _divide_by_zero_error on RiscV. diff --git a/lib/Language/Elna/Backend/Allocator.hs b/lib/Language/Elna/Backend/Allocator.hs index 1ffc85d..701beb8 100644 --- a/lib/Language/Elna/Backend/Allocator.hs +++ b/lib/Language/Elna/Backend/Allocator.hs @@ -12,7 +12,7 @@ import Language.Elna.Location (Identifier(..)) newtype Store r = Store r newtype MachineConfiguration r = MachineConfiguration - { temporaryRegister :: r + { temporaryRegisters :: [r] } allocate @@ -30,14 +30,29 @@ allocate MachineConfiguration{..} = fmap function quadruple (ParameterQuadruple operand1) = ParameterQuadruple (operand operand1) quadruple (CallQuadruple name count) = CallQuadruple name count - quadruple (AddQuadruple operand1 operand2 _) = - 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) - quadruple (ProductQuadruple operand1 operand2 _) = - ProductQuadruple (operand operand1) (operand operand2) (Store temporaryRegister) + quadruple (AddQuadruple operand1 operand2 (TempVariable index)) + = AddQuadruple (operand operand1) (operand operand2) + $ Store + $ temporaryRegisters !! fromIntegral index + quadruple (SubtractionQuadruple operand1 operand2 (TempVariable index)) + = SubtractionQuadruple (operand operand1) (operand operand2) + $ Store + $ temporaryRegisters !! fromIntegral index + quadruple (NegationQuadruple operand1 (TempVariable index)) + = NegationQuadruple (operand operand1) + $ Store + $ temporaryRegisters !! fromIntegral index + quadruple (ProductQuadruple operand1 operand2 (TempVariable index)) + = ProductQuadruple (operand operand1) (operand operand2) + $ Store + $ temporaryRegisters !! fromIntegral index + quadruple (DivisionQuadruple operand1 operand2 (TempVariable index)) + = DivisionQuadruple (operand operand1) (operand operand2) + $ Store + $ temporaryRegisters !! fromIntegral index operand :: Operand Variable -> Operand (Store r) operand (IntOperand x) = IntOperand x - operand (VariableOperand _) = VariableOperand (Store temporaryRegister) + operand (VariableOperand (TempVariable index)) + = VariableOperand + $ Store + $ temporaryRegisters !! fromIntegral index diff --git a/lib/Language/Elna/Backend/Intermediate.hs b/lib/Language/Elna/Backend/Intermediate.hs index e7c66cf..380fba7 100644 --- a/lib/Language/Elna/Backend/Intermediate.hs +++ b/lib/Language/Elna/Backend/Intermediate.hs @@ -31,11 +31,11 @@ data Quadruple v | SubtractionQuadruple (Operand v) (Operand v) v | NegationQuadruple (Operand v) v | ProductQuadruple (Operand v) (Operand v) v + | DivisionQuadruple (Operand v) (Operand v) v {-| GoToQuadruple Label | AssignQuadruple Operand Variable | ArrayQuadruple Variable Operand Variable | ArrayAssignQuadruple Operand Operand Variable - | DivisionQuadruple Operand Operand Variable | EqualQuadruple Operand Operand Label | NonEqualQuadruple Operand Operand Label | LessQuadruple Operand Operand Label diff --git a/lib/Language/Elna/Frontend/AST.hs b/lib/Language/Elna/Frontend/AST.hs index 4c1c20b..b9ed539 100644 --- a/lib/Language/Elna/Frontend/AST.hs +++ b/lib/Language/Elna/Frontend/AST.hs @@ -119,8 +119,8 @@ data Expression | SubtractionExpression Expression Expression | NegationExpression Expression | ProductExpression Expression Expression -{- | VariableExpression VariableAccess - | DivisionExpression Expression Expression -} + | DivisionExpression Expression Expression + -- | VariableExpression VariableAccess deriving Eq instance Show Expression @@ -130,8 +130,8 @@ instance Show Expression show (SubtractionExpression lhs rhs) = concat [show lhs, " - ", show rhs] show (NegationExpression negation) = '-' : show negation show (ProductExpression lhs rhs) = concat [show lhs, " * ", show rhs] - {- show (VariableExpression variable) = show variable - show (DivisionExpression lhs rhs) = concat [show lhs, " / ", show rhs] -} + show (DivisionExpression lhs rhs) = concat [show lhs, " / ", show rhs] + -- show (VariableExpression variable) = show variable {- data VariableAccess = VariableAccess Identifier diff --git a/lib/Language/Elna/Frontend/NameAnalysis.hs b/lib/Language/Elna/Frontend/NameAnalysis.hs index dc39826..18ae6dd 100644 --- a/lib/Language/Elna/Frontend/NameAnalysis.hs +++ b/lib/Language/Elna/Frontend/NameAnalysis.hs @@ -147,11 +147,11 @@ expression globalTable (AST.NegationExpression negation) = expression globalTable (AST.ProductExpression lhs rhs) = expression globalTable lhs >> expression globalTable rhs -{- expression globalTable (AST.VariableExpression variableExpression) = - variableAccess globalTable variableExpression expression globalTable (AST.DivisionExpression lhs rhs) = expression globalTable lhs >> expression globalTable rhs +{- expression globalTable (AST.VariableExpression variableExpression) = + variableAccess globalTable variableExpression -} statement :: SymbolTable -> AST.Statement -> NameAnalysis () statement _ AST.EmptyStatement = pure () diff --git a/lib/Language/Elna/Frontend/Parser.hs b/lib/Language/Elna/Frontend/Parser.hs index 75f359e..9d6bb60 100644 --- a/lib/Language/Elna/Frontend/Parser.hs +++ b/lib/Language/Elna/Frontend/Parser.hs @@ -80,7 +80,7 @@ operatorTable = ] factorOperator = [ binary "*" ProductExpression - -- , binary "/" DivisionExpression + , binary "/" DivisionExpression ] termOperator = [ binary "+" SumExpression diff --git a/lib/Language/Elna/Glue.hs b/lib/Language/Elna/Glue.hs index 85c8401..31c31e0 100644 --- a/lib/Language/Elna/Glue.hs +++ b/lib/Language/Elna/Glue.hs @@ -235,6 +235,8 @@ expression localTable = \case ) (AST.ProductExpression lhs rhs) -> binaryExpression ProductQuadruple lhs rhs + (AST.DivisionExpression lhs rhs) -> + binaryExpression DivisionQuadruple lhs rhs {- (AST.VariableExpression variableExpression) -> do let variableType' = variableType variableExpression localTable variableAccess' <- variableAccess localTable variableExpression Nothing variableType' mempty @@ -247,9 +249,7 @@ expression localTable = \case pure ( VariableOperand arrayAddress , Vector.snoc statements arrayStatement - ) - (AST.DivisionExpression lhs rhs) -> - binaryExpression DivisionQuadruple lhs rhs -} + ) -} where binaryExpression f lhs rhs = do (lhsOperand, lhsStatements) <- expression localTable lhs diff --git a/lib/Language/Elna/RiscV/CodeGenerator.hs b/lib/Language/Elna/RiscV/CodeGenerator.hs index 439f99c..5bc9228 100644 --- a/lib/Language/Elna/RiscV/CodeGenerator.hs +++ b/lib/Language/Elna/RiscV/CodeGenerator.hs @@ -29,7 +29,15 @@ data Statement riscVConfiguration :: MachineConfiguration RiscV.XRegister riscVConfiguration = MachineConfiguration - { temporaryRegister = RiscV.T0 + { temporaryRegisters = + [ RiscV.T0 + , RiscV.T1 + , RiscV.T2 + , RiscV.T3 + , RiscV.T4 + , RiscV.T5 + , RiscV.T6 + ] } type RiscVStore = Store RiscV.XRegister @@ -158,6 +166,35 @@ quadruple (ProductQuadruple operand1 operand2 (Store register)) $ RiscV.BaseInstruction RiscV.Op $ RiscV.R register RiscV.MUL register operandRegister $ RiscV.Funct7 0b0000001 +quadruple (DivisionQuadruple operand1 operand2 (Store register)) + | IntOperand immediateOperand1 <- operand1 + , IntOperand immediateOperand2 <- operand2 = + lui (quot immediateOperand1 immediateOperand2) register + | VariableOperand variableOperand1 <- operand1 + , VariableOperand variableOperand2 <- operand2 = + let Store operandRegister1 = variableOperand1 + Store operandRegister2 = variableOperand2 + in pure $ Instruction + $ RiscV.BaseInstruction RiscV.Op + $ RiscV.R register RiscV.DIV operandRegister1 operandRegister2 (RiscV.Funct7 0b0000001) + | VariableOperand variableOperand1 <- operand1 + , IntOperand immediateOperand2 <- operand2 = + let statements2 = lui immediateOperand2 register + Store operandRegister1 = variableOperand1 + in Vector.snoc statements2 + $ Instruction + $ RiscV.BaseInstruction RiscV.Op + $ RiscV.R register RiscV.DIV operandRegister1 register + $ RiscV.Funct7 0b0000001 + | IntOperand immediateOperand1 <- operand1 + , VariableOperand variableOperand2 <- operand2 = + let statements1 = lui immediateOperand1 register + Store operandRegister2 = variableOperand2 + in Vector.snoc statements1 + $ Instruction + $ RiscV.BaseInstruction RiscV.Op + $ RiscV.R register RiscV.DIV register operandRegister2 + $ RiscV.Funct7 0b0000001 loadImmediateOrRegister :: RiscVOperand -> RiscV.XRegister -> (RiscV.XRegister, Vector Statement) loadImmediateOrRegister (IntOperand intValue) targetRegister = diff --git a/tests/expectations/add_products.txt b/tests/expectations/add_products.txt new file mode 100644 index 0000000..e522732 --- /dev/null +++ b/tests/expectations/add_products.txt @@ -0,0 +1 @@ +38 diff --git a/tests/expectations/printi_divide_by_zero.txt b/tests/expectations/printi_divide_by_zero.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/expectations/printi_quotient.txt b/tests/expectations/printi_quotient.txt new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/tests/expectations/printi_quotient.txt @@ -0,0 +1 @@ +2 diff --git a/tests/vm/add_products.elna b/tests/vm/add_products.elna new file mode 100644 index 0000000..a5c116f --- /dev/null +++ b/tests/vm/add_products.elna @@ -0,0 +1,3 @@ +proc main() { + printi(2 * 3 + 4 * 8); +} diff --git a/tests/vm/printi_divide_by_zero.elna b/tests/vm/printi_divide_by_zero.elna new file mode 100644 index 0000000..7e2fdea --- /dev/null +++ b/tests/vm/printi_divide_by_zero.elna @@ -0,0 +1,3 @@ +proc main() { + printi(4 / (2 - 2)); +} diff --git a/tests/vm/printi_quotient.elna b/tests/vm/printi_quotient.elna new file mode 100644 index 0000000..0f30f4d --- /dev/null +++ b/tests/vm/printi_quotient.elna @@ -0,0 +1,3 @@ +proc main() { + printi(4 / 2); +} diff --git a/tools/builtin.s b/tools/builtin.s index 0f5f82c..d7f214d 100644 --- a/tools/builtin.s +++ b/tools/builtin.s @@ -7,6 +7,9 @@ .global exit .type exit, @function +.global _divide_by_zero_error +.type _divide_by_zero_error, @function + .global _start .type _start, @function @@ -51,7 +54,7 @@ printi: addi a0, zero, 1 addi a1, a1, 1 sub a2, s0, a1 - addi a7, zero, 64 + addi a7, zero, 64 # write ecall lw s0, 0(sp) @@ -74,7 +77,7 @@ printc: addi a0, zero, 1 addi a1, s0, -2 addi a2, zero, 2 - addi a7, zero, 64 + addi a7, zero, 64 # write ecall lw s0, 0(sp) @@ -84,10 +87,19 @@ printc: exit: addi a0, zero, 0 - addi a7, zero, 93 + addi a7, zero, 93 # exit ecall # ret +_divide_by_zero_error: + addi a7, zero, 172 # getpid + ecall + + addi a1, zero, 8 # SIGFPE + addi a7, zero, 129 # kill + ecall + ret + _start: call main call exit