Implement division
This commit is contained in:
parent
35742aa525
commit
699cc8684b
6
TODO
6
TODO
@ -17,8 +17,9 @@
|
|||||||
|
|
||||||
# Register allocation
|
# Register allocation
|
||||||
|
|
||||||
- Temporary variables always use the same register, t0. Allocate registers for
|
- Each temporary variales gets a tn register where n is the variable index. If
|
||||||
temporaries.
|
there more variables the allocation will fail with out of bounds runtime
|
||||||
|
error. Implement spill over.
|
||||||
|
|
||||||
# Prarsing and abstract syntax tree
|
# Prarsing and abstract syntax tree
|
||||||
|
|
||||||
@ -27,3 +28,4 @@
|
|||||||
# Other
|
# Other
|
||||||
|
|
||||||
- Type analysis.
|
- 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 Store r = Store r
|
||||||
|
|
||||||
newtype MachineConfiguration r = MachineConfiguration
|
newtype MachineConfiguration r = MachineConfiguration
|
||||||
{ temporaryRegister :: r
|
{ temporaryRegisters :: [r]
|
||||||
}
|
}
|
||||||
|
|
||||||
allocate
|
allocate
|
||||||
@ -30,14 +30,29 @@ allocate MachineConfiguration{..} = fmap function
|
|||||||
quadruple (ParameterQuadruple operand1) =
|
quadruple (ParameterQuadruple operand1) =
|
||||||
ParameterQuadruple (operand operand1)
|
ParameterQuadruple (operand operand1)
|
||||||
quadruple (CallQuadruple name count) = CallQuadruple name count
|
quadruple (CallQuadruple name count) = CallQuadruple name count
|
||||||
quadruple (AddQuadruple operand1 operand2 _) =
|
quadruple (AddQuadruple operand1 operand2 (TempVariable index))
|
||||||
AddQuadruple (operand operand1) (operand operand2) (Store temporaryRegister)
|
= AddQuadruple (operand operand1) (operand operand2)
|
||||||
quadruple (SubtractionQuadruple operand1 operand2 _) =
|
$ Store
|
||||||
SubtractionQuadruple (operand operand1) (operand operand2) (Store temporaryRegister)
|
$ temporaryRegisters !! fromIntegral index
|
||||||
quadruple (NegationQuadruple operand1 _) =
|
quadruple (SubtractionQuadruple operand1 operand2 (TempVariable index))
|
||||||
NegationQuadruple (operand operand1) (Store temporaryRegister)
|
= SubtractionQuadruple (operand operand1) (operand operand2)
|
||||||
quadruple (ProductQuadruple operand1 operand2 _) =
|
$ Store
|
||||||
ProductQuadruple (operand operand1) (operand operand2) (Store temporaryRegister)
|
$ 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 :: Operand Variable -> Operand (Store r)
|
||||||
operand (IntOperand x) = IntOperand x
|
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
|
| SubtractionQuadruple (Operand v) (Operand v) v
|
||||||
| NegationQuadruple (Operand v) v
|
| NegationQuadruple (Operand v) v
|
||||||
| ProductQuadruple (Operand v) (Operand v) v
|
| ProductQuadruple (Operand v) (Operand v) v
|
||||||
|
| DivisionQuadruple (Operand v) (Operand v) v
|
||||||
{-| GoToQuadruple Label
|
{-| GoToQuadruple Label
|
||||||
| AssignQuadruple Operand Variable
|
| AssignQuadruple Operand Variable
|
||||||
| ArrayQuadruple Variable Operand Variable
|
| ArrayQuadruple Variable Operand Variable
|
||||||
| ArrayAssignQuadruple Operand Operand Variable
|
| ArrayAssignQuadruple Operand Operand Variable
|
||||||
| DivisionQuadruple Operand Operand Variable
|
|
||||||
| EqualQuadruple Operand Operand Label
|
| EqualQuadruple Operand Operand Label
|
||||||
| NonEqualQuadruple Operand Operand Label
|
| NonEqualQuadruple Operand Operand Label
|
||||||
| LessQuadruple Operand Operand Label
|
| LessQuadruple Operand Operand Label
|
||||||
|
@ -119,8 +119,8 @@ data Expression
|
|||||||
| SubtractionExpression Expression Expression
|
| SubtractionExpression Expression Expression
|
||||||
| NegationExpression Expression
|
| NegationExpression Expression
|
||||||
| ProductExpression Expression Expression
|
| ProductExpression Expression Expression
|
||||||
{- | VariableExpression VariableAccess
|
| DivisionExpression Expression Expression
|
||||||
| DivisionExpression Expression Expression -}
|
-- | VariableExpression VariableAccess
|
||||||
deriving Eq
|
deriving Eq
|
||||||
|
|
||||||
instance Show Expression
|
instance Show Expression
|
||||||
@ -130,8 +130,8 @@ instance Show Expression
|
|||||||
show (SubtractionExpression lhs rhs) = concat [show lhs, " - ", show rhs]
|
show (SubtractionExpression lhs rhs) = concat [show lhs, " - ", show rhs]
|
||||||
show (NegationExpression negation) = '-' : show negation
|
show (NegationExpression negation) = '-' : show negation
|
||||||
show (ProductExpression lhs rhs) = concat [show lhs, " * ", show rhs]
|
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
|
data VariableAccess
|
||||||
= VariableAccess Identifier
|
= VariableAccess Identifier
|
||||||
|
@ -147,11 +147,11 @@ expression globalTable (AST.NegationExpression negation) =
|
|||||||
expression globalTable (AST.ProductExpression lhs rhs)
|
expression globalTable (AST.ProductExpression lhs rhs)
|
||||||
= expression globalTable lhs
|
= expression globalTable lhs
|
||||||
>> expression globalTable rhs
|
>> expression globalTable rhs
|
||||||
{- expression globalTable (AST.VariableExpression variableExpression) =
|
|
||||||
variableAccess globalTable variableExpression
|
|
||||||
expression globalTable (AST.DivisionExpression lhs rhs)
|
expression globalTable (AST.DivisionExpression lhs rhs)
|
||||||
= expression globalTable lhs
|
= expression globalTable lhs
|
||||||
>> expression globalTable rhs
|
>> expression globalTable rhs
|
||||||
|
{- expression globalTable (AST.VariableExpression variableExpression) =
|
||||||
|
variableAccess globalTable variableExpression
|
||||||
-}
|
-}
|
||||||
statement :: SymbolTable -> AST.Statement -> NameAnalysis ()
|
statement :: SymbolTable -> AST.Statement -> NameAnalysis ()
|
||||||
statement _ AST.EmptyStatement = pure ()
|
statement _ AST.EmptyStatement = pure ()
|
||||||
|
@ -80,7 +80,7 @@ operatorTable =
|
|||||||
]
|
]
|
||||||
factorOperator =
|
factorOperator =
|
||||||
[ binary "*" ProductExpression
|
[ binary "*" ProductExpression
|
||||||
-- , binary "/" DivisionExpression
|
, binary "/" DivisionExpression
|
||||||
]
|
]
|
||||||
termOperator =
|
termOperator =
|
||||||
[ binary "+" SumExpression
|
[ binary "+" SumExpression
|
||||||
|
@ -235,6 +235,8 @@ expression localTable = \case
|
|||||||
)
|
)
|
||||||
(AST.ProductExpression lhs rhs) ->
|
(AST.ProductExpression lhs rhs) ->
|
||||||
binaryExpression ProductQuadruple lhs rhs
|
binaryExpression ProductQuadruple lhs rhs
|
||||||
|
(AST.DivisionExpression lhs rhs) ->
|
||||||
|
binaryExpression DivisionQuadruple lhs rhs
|
||||||
{- (AST.VariableExpression variableExpression) -> do
|
{- (AST.VariableExpression variableExpression) -> do
|
||||||
let variableType' = variableType variableExpression localTable
|
let variableType' = variableType variableExpression localTable
|
||||||
variableAccess' <- variableAccess localTable variableExpression Nothing variableType' mempty
|
variableAccess' <- variableAccess localTable variableExpression Nothing variableType' mempty
|
||||||
@ -247,9 +249,7 @@ expression localTable = \case
|
|||||||
pure
|
pure
|
||||||
( VariableOperand arrayAddress
|
( VariableOperand arrayAddress
|
||||||
, Vector.snoc statements arrayStatement
|
, Vector.snoc statements arrayStatement
|
||||||
)
|
) -}
|
||||||
(AST.DivisionExpression lhs rhs) ->
|
|
||||||
binaryExpression DivisionQuadruple lhs rhs -}
|
|
||||||
where
|
where
|
||||||
binaryExpression f lhs rhs = do
|
binaryExpression f lhs rhs = do
|
||||||
(lhsOperand, lhsStatements) <- expression localTable lhs
|
(lhsOperand, lhsStatements) <- expression localTable lhs
|
||||||
|
@ -29,7 +29,15 @@ data Statement
|
|||||||
|
|
||||||
riscVConfiguration :: MachineConfiguration RiscV.XRegister
|
riscVConfiguration :: MachineConfiguration RiscV.XRegister
|
||||||
riscVConfiguration = MachineConfiguration
|
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
|
type RiscVStore = Store RiscV.XRegister
|
||||||
@ -158,6 +166,35 @@ quadruple (ProductQuadruple operand1 operand2 (Store register))
|
|||||||
$ RiscV.BaseInstruction RiscV.Op
|
$ RiscV.BaseInstruction RiscV.Op
|
||||||
$ RiscV.R register RiscV.MUL register operandRegister
|
$ RiscV.R register RiscV.MUL register operandRegister
|
||||||
$ RiscV.Funct7 0b0000001
|
$ 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 :: RiscVOperand -> RiscV.XRegister -> (RiscV.XRegister, Vector Statement)
|
||||||
loadImmediateOrRegister (IntOperand intValue) targetRegister =
|
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
|
.global exit
|
||||||
.type exit, @function
|
.type exit, @function
|
||||||
|
|
||||||
|
.global _divide_by_zero_error
|
||||||
|
.type _divide_by_zero_error, @function
|
||||||
|
|
||||||
.global _start
|
.global _start
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
|
|
||||||
@ -51,7 +54,7 @@ printi:
|
|||||||
addi a0, zero, 1
|
addi a0, zero, 1
|
||||||
addi a1, a1, 1
|
addi a1, a1, 1
|
||||||
sub a2, s0, a1
|
sub a2, s0, a1
|
||||||
addi a7, zero, 64
|
addi a7, zero, 64 # write
|
||||||
ecall
|
ecall
|
||||||
|
|
||||||
lw s0, 0(sp)
|
lw s0, 0(sp)
|
||||||
@ -74,7 +77,7 @@ printc:
|
|||||||
addi a0, zero, 1
|
addi a0, zero, 1
|
||||||
addi a1, s0, -2
|
addi a1, s0, -2
|
||||||
addi a2, zero, 2
|
addi a2, zero, 2
|
||||||
addi a7, zero, 64
|
addi a7, zero, 64 # write
|
||||||
ecall
|
ecall
|
||||||
|
|
||||||
lw s0, 0(sp)
|
lw s0, 0(sp)
|
||||||
@ -84,10 +87,19 @@ printc:
|
|||||||
|
|
||||||
exit:
|
exit:
|
||||||
addi a0, zero, 0
|
addi a0, zero, 0
|
||||||
addi a7, zero, 93
|
addi a7, zero, 93 # exit
|
||||||
ecall
|
ecall
|
||||||
# ret
|
# ret
|
||||||
|
|
||||||
|
_divide_by_zero_error:
|
||||||
|
addi a7, zero, 172 # getpid
|
||||||
|
ecall
|
||||||
|
|
||||||
|
addi a1, zero, 8 # SIGFPE
|
||||||
|
addi a7, zero, 129 # kill
|
||||||
|
ecall
|
||||||
|
ret
|
||||||
|
|
||||||
_start:
|
_start:
|
||||||
call main
|
call main
|
||||||
call exit
|
call exit
|
||||||
|
Loading…
Reference in New Issue
Block a user