Implement division
This commit is contained in:
parent
35742aa525
commit
9dbc441042
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
|
0
tests/expectations/printi_divide_by_zero.txt
Normal file
0
tests/expectations/printi_divide_by_zero.txt
Normal file
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_divide_by_zero.elna
Normal file
3
tests/vm/printi_divide_by_zero.elna
Normal file
@ -0,0 +1,3 @@
|
||||
proc main() {
|
||||
printi(4 / (2 - 2));
|
||||
}
|
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
|
||||
|
Loading…
Reference in New Issue
Block a user