Implement division
This commit is contained in:
		
							
								
								
									
										6
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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 ()
 | 
			
		||||
 
 | 
			
		||||
@@ -80,7 +80,7 @@ operatorTable =
 | 
			
		||||
        ]
 | 
			
		||||
    factorOperator =
 | 
			
		||||
        [ binary "*" ProductExpression
 | 
			
		||||
        -- , binary "/" DivisionExpression
 | 
			
		||||
        , binary "/" DivisionExpression
 | 
			
		||||
        ]
 | 
			
		||||
    termOperator =
 | 
			
		||||
        [ binary "+" SumExpression
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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 =
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								tests/expectations/add_products.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/expectations/add_products.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
38
 | 
			
		||||
							
								
								
									
										1
									
								
								tests/expectations/printi_quotient.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/expectations/printi_quotient.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
2
 | 
			
		||||
							
								
								
									
										3
									
								
								tests/vm/add_products.elna
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tests/vm/add_products.elna
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
proc main() {
 | 
			
		||||
  printi(2 * 3 + 4 * 8);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								tests/vm/printi_quotient.elna
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tests/vm/printi_quotient.elna
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
proc main() {
 | 
			
		||||
  printi(4 / 2);
 | 
			
		||||
}
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user