From 4efda21007aed3f91e9360aaa1cea93975abd994 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sun, 1 Dec 2024 11:17:14 +0100 Subject: [PATCH] Add array assignment to the IR --- TODO | 6 ---- lib/Language/Elna/Backend/Allocator.hs | 4 +++ lib/Language/Elna/Backend/Intermediate.hs | 4 +-- lib/Language/Elna/RiscV/CodeGenerator.hs | 36 +++++++++++++++++++++++ 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/TODO b/TODO index 1fa05f5..964de44 100644 --- a/TODO +++ b/TODO @@ -1,9 +1,3 @@ -# Intermediate code generation - -- To access named parameters inside a procedure, IR should be able to reference - them. During the generation the needed information (e.g. offsets or registers) - can be extracted from the symbol table and saved in the operands. - # ELF generation - Don't ignore relocations where the symbol is not defined in the symbol table. diff --git a/lib/Language/Elna/Backend/Allocator.hs b/lib/Language/Elna/Backend/Allocator.hs index f0f285b..acdf3e5 100644 --- a/lib/Language/Elna/Backend/Allocator.hs +++ b/lib/Language/Elna/Backend/Allocator.hs @@ -135,6 +135,10 @@ quadruple = \case AssignQuadruple operand1 variable -> do operand1' <- operand operand1 AssignQuadruple operand1' <$> storeVariable variable + ArrayAssignQuadruple operand1 operand2 variable -> do + operand1' <- operand operand1 + operand2' <- operand operand2 + ArrayAssignQuadruple operand1' operand2' <$> storeVariable variable operand :: Operand Variable -> Allocator r (Operand (Store r)) operand (IntOperand x) = pure $ IntOperand x diff --git a/lib/Language/Elna/Backend/Intermediate.hs b/lib/Language/Elna/Backend/Intermediate.hs index 331d044..dcf0ede 100644 --- a/lib/Language/Elna/Backend/Intermediate.hs +++ b/lib/Language/Elna/Backend/Intermediate.hs @@ -50,8 +50,8 @@ data Quadruple v | DivisionQuadruple (Operand v) (Operand v) v | GoToQuadruple Label | AssignQuadruple (Operand v) v - {-| ArrayQuadruple Variable Operand Variable - | ArrayAssignQuadruple Operand Operand Variable -} + {-| ArrayQuadruple Variable Operand Variable -} + | ArrayAssignQuadruple (Operand v) (Operand v) v | LessOrEqualQuadruple (Operand v) (Operand v) Label | GreaterOrEqualQuadruple (Operand v) (Operand v) Label | GreaterQuadruple (Operand v) (Operand v) Label diff --git a/lib/Language/Elna/RiscV/CodeGenerator.hs b/lib/Language/Elna/RiscV/CodeGenerator.hs index a0ad5f9..6e7a8cd 100644 --- a/lib/Language/Elna/RiscV/CodeGenerator.hs +++ b/lib/Language/Elna/RiscV/CodeGenerator.hs @@ -259,6 +259,42 @@ quadruple _ (AssignQuadruple operand1 store) $ RiscV.BaseInstruction RiscV.OpImm $ RiscV.I storeRegister RiscV.ADDI operandRegister1 0 in pure $ statements1 <> Vector.cons instruction storeStatements +quadruple _ (ArrayAssignQuadruple assigneeOperand indexOperand store) + | IntOperand immediateAssigneeOperand <- assigneeOperand = + let (storeRegister, storeStatements) = storeWithOffset store indexOperand + in pure $ lui immediateAssigneeOperand storeRegister <> storeStatements + | VariableOperand variableAssigneeOperand <- assigneeOperand = + let (assigneeOperandRegister, assigneeStatements) = loadFromStore variableAssigneeOperand + (storeRegister, storeStatements) = storeWithOffset store indexOperand + instruction = Instruction + $ RiscV.BaseInstruction RiscV.OpImm + $ RiscV.I storeRegister RiscV.ADDI assigneeOperandRegister 0 + in pure $ assigneeStatements <> Vector.cons instruction storeStatements + where + storeWithOffset :: RiscVStore -> Operand RiscVStore -> (RiscV.XRegister, Vector Statement) + storeWithOffset (RegisterStore register) _ = (register, mempty) + storeWithOffset (StackStore offset register) (IntOperand indexOffset) = + let storeInstruction = Instruction + $ RiscV.BaseInstruction RiscV.Store + $ RiscV.S (fromIntegral $ offset + indexOffset) RiscV.SW RiscV.S0 register + in (register, Vector.singleton storeInstruction) + storeWithOffset (StackStore offset register) (VariableOperand indexOffset) = + let baseRegisterInstruction = 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.S (fromIntegral offset) RiscV.SW immediateRegister register + statements = Vector.fromList + [ baseRegisterInstruction + , registerWithOffset + , storeInstruction + ] + in (register, indexStatements <> statements) unconditionalJal :: Label -> Statement unconditionalJal (Label goToLabel) = Instruction