Calculate stack offset from array index
This commit is contained in:
parent
1c996b3c8b
commit
7fc90f1d2d
@ -7,7 +7,6 @@ module Language.Elna.Backend.Allocator
|
|||||||
import Data.HashMap.Strict (HashMap)
|
import Data.HashMap.Strict (HashMap)
|
||||||
import qualified Data.HashMap.Strict as HashMap
|
import qualified Data.HashMap.Strict as HashMap
|
||||||
import Data.Int (Int32)
|
import Data.Int (Int32)
|
||||||
import Data.Word (Word32)
|
|
||||||
import Data.Vector (Vector)
|
import Data.Vector (Vector)
|
||||||
import Language.Elna.Backend.Intermediate
|
import Language.Elna.Backend.Intermediate
|
||||||
( ProcedureQuadruples(..)
|
( ProcedureQuadruples(..)
|
||||||
|
@ -276,25 +276,14 @@ quadruple _ (ArrayAssignQuadruple assigneeOperand indexOperand store)
|
|||||||
storeWithOffset (StackStore offset register) (IntOperand indexOffset) =
|
storeWithOffset (StackStore offset register) (IntOperand indexOffset) =
|
||||||
let storeInstruction = Instruction
|
let storeInstruction = Instruction
|
||||||
$ RiscV.BaseInstruction RiscV.Store
|
$ RiscV.BaseInstruction RiscV.Store
|
||||||
$ RiscV.S (fromIntegral $ offset + indexOffset) RiscV.SW RiscV.S0 register
|
$ RiscV.S (fromIntegral $ offset + indexOffset * 4) RiscV.SW RiscV.S0 register
|
||||||
in (register, Vector.singleton storeInstruction)
|
in (register, Vector.singleton storeInstruction)
|
||||||
storeWithOffset (StackStore offset register) (VariableOperand indexOffset) =
|
storeWithOffset (StackStore offset register) (VariableOperand indexOffset) =
|
||||||
let baseRegisterInstruction = Instruction
|
let storeInstruction = Instruction
|
||||||
$ RiscV.BaseInstruction RiscV.OpImm
|
|
||||||
$ RiscV.I immediateRegister RiscV.ADDI RiscV.S0 0
|
|
||||||
(indexRegister, indexStatements) = loadFromStore indexOffset
|
|
||||||
registerWithOffset = Instruction
|
|
||||||
$ RiscV.BaseInstruction RiscV.OpImm
|
|
||||||
$ RiscV.I immediateRegister RiscV.ADDI indexRegister 0
|
|
||||||
storeInstruction = Instruction
|
|
||||||
$ RiscV.BaseInstruction RiscV.Store
|
$ RiscV.BaseInstruction RiscV.Store
|
||||||
$ RiscV.S (fromIntegral offset) RiscV.SW immediateRegister register
|
$ RiscV.S (fromIntegral offset) RiscV.SW immediateRegister register
|
||||||
statements = Vector.fromList
|
statements = calculateIndexOffset indexOffset
|
||||||
[ baseRegisterInstruction
|
in (register, Vector.snoc statements storeInstruction)
|
||||||
, registerWithOffset
|
|
||||||
, storeInstruction
|
|
||||||
]
|
|
||||||
in (register, indexStatements <> statements)
|
|
||||||
quadruple _ (ArrayQuadruple assigneeVariable indexOperand store) =
|
quadruple _ (ArrayQuadruple assigneeVariable indexOperand store) =
|
||||||
let (operandRegister1, statements1) = loadWithOffset assigneeVariable indexOperand
|
let (operandRegister1, statements1) = loadWithOffset assigneeVariable indexOperand
|
||||||
(storeRegister, storeStatements) = storeToStore store
|
(storeRegister, storeStatements) = storeToStore store
|
||||||
@ -308,25 +297,33 @@ quadruple _ (ArrayQuadruple assigneeVariable indexOperand store) =
|
|||||||
loadWithOffset (StackStore offset register) (IntOperand indexOffset) =
|
loadWithOffset (StackStore offset register) (IntOperand indexOffset) =
|
||||||
let loadInstruction = Instruction
|
let loadInstruction = Instruction
|
||||||
$ RiscV.BaseInstruction RiscV.Load
|
$ RiscV.BaseInstruction RiscV.Load
|
||||||
$ RiscV.I register RiscV.LW RiscV.S0 (fromIntegral $ offset + indexOffset)
|
$ RiscV.I register RiscV.LW RiscV.S0 (fromIntegral $ offset + indexOffset * 4)
|
||||||
in (register, Vector.singleton loadInstruction)
|
in (register, Vector.singleton loadInstruction)
|
||||||
loadWithOffset (StackStore offset register) (VariableOperand indexOffset) =
|
loadWithOffset (StackStore offset register) (VariableOperand indexOffset) =
|
||||||
let baseRegisterInstruction = Instruction
|
let loadInstruction = Instruction
|
||||||
$ RiscV.BaseInstruction RiscV.OpImm
|
|
||||||
$ RiscV.I immediateRegister RiscV.ADDI RiscV.S0 0
|
|
||||||
(indexRegister, indexStatements) = loadFromStore indexOffset
|
|
||||||
registerWithOffset = Instruction
|
|
||||||
$ RiscV.BaseInstruction RiscV.OpImm
|
|
||||||
$ RiscV.I immediateRegister RiscV.ADDI indexRegister 0
|
|
||||||
loadInstruction = Instruction
|
|
||||||
$ RiscV.BaseInstruction RiscV.Load
|
$ RiscV.BaseInstruction RiscV.Load
|
||||||
$ RiscV.I register RiscV.SW immediateRegister (fromIntegral offset)
|
$ RiscV.I register RiscV.SW immediateRegister (fromIntegral offset)
|
||||||
|
statements = calculateIndexOffset indexOffset
|
||||||
|
in (register, Vector.snoc statements loadInstruction)
|
||||||
|
|
||||||
|
calculateIndexOffset :: RiscVStore -> Vector Statement
|
||||||
|
calculateIndexOffset indexOffset =
|
||||||
|
let (indexRegister, indexStatements) = loadFromStore indexOffset
|
||||||
|
baseRegisterInstruction = Instruction
|
||||||
|
$ RiscV.BaseInstruction RiscV.OpImm
|
||||||
|
$ RiscV.I immediateRegister RiscV.ADDI RiscV.Zero 4
|
||||||
|
indexRelativeOffset = Instruction
|
||||||
|
$ RiscV.BaseInstruction RiscV.Op
|
||||||
|
$ RiscV.R immediateRegister RiscV.MUL immediateRegister indexRegister (RiscV.Funct7 0b0000001)
|
||||||
|
registerWithOffset = Instruction
|
||||||
|
$ RiscV.BaseInstruction RiscV.Op
|
||||||
|
$ RiscV.R immediateRegister RiscV.ADD immediateRegister RiscV.S0 (RiscV.Funct7 0b0000000)
|
||||||
statements = Vector.fromList
|
statements = Vector.fromList
|
||||||
[ baseRegisterInstruction
|
[ baseRegisterInstruction
|
||||||
|
, indexRelativeOffset
|
||||||
, registerWithOffset
|
, registerWithOffset
|
||||||
, loadInstruction
|
|
||||||
]
|
]
|
||||||
in (register, indexStatements <> statements)
|
in indexStatements <> statements
|
||||||
|
|
||||||
unconditionalJal :: Label -> Statement
|
unconditionalJal :: Label -> Statement
|
||||||
unconditionalJal (Label goToLabel) = Instruction
|
unconditionalJal (Label goToLabel) = Instruction
|
||||||
|
2
tests/expectations/array_with_variable_index.txt
Normal file
2
tests/expectations/array_with_variable_index.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
5
|
||||||
|
7
|
11
tests/vm/array_with_variable_index.elna
Normal file
11
tests/vm/array_with_variable_index.elna
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
proc main() {
|
||||||
|
var a: array[2] of int;
|
||||||
|
var i: int;
|
||||||
|
|
||||||
|
i := 1;
|
||||||
|
a[0] := 5;
|
||||||
|
a[i] := 7;
|
||||||
|
|
||||||
|
printi(a[0]);
|
||||||
|
printi(a[i]);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user