diff --git a/TODO b/TODO index e12d98e..2710951 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,9 @@ # Intermediate code generation -- Calculate maximum number of arguments that a function can have. Put procedure - arguments onto the stack, above the stack pointer. Should the offsets be - calculated during IR generation or target code generation? +- To access named parameters and local variables 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 @@ -16,4 +17,6 @@ # Built-in -Printi should be able to print numbers with multiple digits. +Printi should print a sign for negative numbers. + +# Type analysis diff --git a/elna.cabal b/elna.cabal index 2c3fc44..2c80ea5 100644 --- a/elna.cabal +++ b/elna.cabal @@ -35,6 +35,7 @@ common warnings library elna-internal import: warnings exposed-modules: + Language.Elna.Allocator Language.Elna.Architecture.RiscV Language.Elna.AST Language.Elna.CodeGenerator diff --git a/lib/Language/Elna/Allocator.hs b/lib/Language/Elna/Allocator.hs new file mode 100644 index 0000000..a5ca574 --- /dev/null +++ b/lib/Language/Elna/Allocator.hs @@ -0,0 +1,3 @@ +module Language.Elna.Allocator + ( + ) where diff --git a/lib/Language/Elna/CodeGenerator.hs b/lib/Language/Elna/CodeGenerator.hs index 3cb5c1d..1a9151a 100644 --- a/lib/Language/Elna/CodeGenerator.hs +++ b/lib/Language/Elna/CodeGenerator.hs @@ -10,9 +10,10 @@ import Data.Vector (Vector) import qualified Data.Vector as Vector import qualified Data.Text.Encoding as Text.Encoding import Language.Elna.Location (Identifier(..)) -import Language.Elna.Intermediate (Quadruple(..)) +import Language.Elna.Intermediate (Operand(..), Quadruple(..)) import qualified Language.Elna.Architecture.RiscV as RiscV import Language.Elna.SymbolTable (SymbolTable) +import Data.Bits (Bits(..)) data Directive = GlobalDirective @@ -39,9 +40,31 @@ quadruple StartQuadruple = Vector.fromList , Instruction (RiscV.BaseInstruction RiscV.Store $ RiscV.S 4 RiscV.SW RiscV.SP RiscV.RA) , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.S0 RiscV.ADDI RiscV.SP 4) ] -quadruple (ParameterQuadruple _) = mempty -quadruple (CallQuadruple callName _) = Vector.singleton - $ Instruction (RiscV.CallInstruction callName) +quadruple (ParameterQuadruple (IntOperand intValue)) + = mappend go + $ Vector.fromList + [ Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.SP RiscV.ADDI RiscV.SP (negate 4)) + , Instruction (RiscV.BaseInstruction RiscV.Store $ RiscV.S 0 RiscV.SW RiscV.SP RiscV.A0) + ] + where + hi = intValue `shiftR` 12 + lo = intValue + go + | intValue >= -2048 + , intValue <= 2047 = Vector.singleton + $ Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.A0 RiscV.ADDI RiscV.A0 $ fromIntegral lo) + | intValue .&. 0x800 /= 0 = Vector.fromList + [ Instruction (RiscV.BaseInstruction RiscV.Lui $ RiscV.U RiscV.A0 $ fromIntegral $ succ hi) + , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.A0 RiscV.ADDI RiscV.A0 $ fromIntegral lo) + ] + | otherwise = Vector.fromList + [ Instruction (RiscV.BaseInstruction RiscV.Lui $ RiscV.U RiscV.A0 $ fromIntegral hi) + , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.A0 RiscV.ADDI RiscV.A0 $ fromIntegral lo) + ] +quadruple (CallQuadruple callName numberOfArguments) = Vector.fromList + [ Instruction (RiscV.CallInstruction callName) + , Instruction (RiscV.BaseInstruction RiscV.OpImm $ RiscV.I RiscV.SP RiscV.ADDI RiscV.SP (numberOfArguments * 4)) + ] quadruple StopQuadruple = Vector.fromList [ Instruction (RiscV.BaseInstruction RiscV.Load $ RiscV.I RiscV.S0 RiscV.LW RiscV.SP 0) , Instruction (RiscV.BaseInstruction RiscV.Load $ RiscV.I RiscV.RA RiscV.LW RiscV.SP 4) diff --git a/tests/expectations/print_2_digits.txt b/tests/expectations/print_2_digits.txt new file mode 100644 index 0000000..b1bd38b --- /dev/null +++ b/tests/expectations/print_2_digits.txt @@ -0,0 +1 @@ +13 diff --git a/tests/expectations/print_more_20_bits.txt b/tests/expectations/print_more_20_bits.txt new file mode 100644 index 0000000..78db0b5 --- /dev/null +++ b/tests/expectations/print_more_20_bits.txt @@ -0,0 +1 @@ +2097150 diff --git a/tests/vm/print_2_digits.elna b/tests/vm/print_2_digits.elna new file mode 100644 index 0000000..9aac010 --- /dev/null +++ b/tests/vm/print_2_digits.elna @@ -0,0 +1,3 @@ +proc main() { + printi(13); +} diff --git a/tests/vm/print_more_20_bits.elna b/tests/vm/print_more_20_bits.elna new file mode 100644 index 0000000..e37480a --- /dev/null +++ b/tests/vm/print_more_20_bits.elna @@ -0,0 +1,3 @@ +proc main() { + printi(2097150); +} diff --git a/tools/builtin.s b/tools/builtin.s index 17e262d..7b14d95 100644 --- a/tools/builtin.s +++ b/tools/builtin.s @@ -6,29 +6,41 @@ .text printi: - addi sp, sp, -4 + addi sp, sp, -16 sw s0, 0(sp) sw ra, 4(sp) - addi s0, sp, 4 + addi s0, sp, 16 + + addi t1, zero, '\n' + sb t1, -1(s0) + + # t0 - Whole number. + # t1 - Constant 10. + # a1 - Local buffer. + # t2 - Current character. + lw t0, 0(s0) + addi t1, zero, 10 + addi a1, s0, -2 + +.digit10: + rem t2, t0, t1 + addi t2, t2, '0' + sb t2, 0(a1) + div t0, t0, t1 + addi a1, a1, -1 + bne zero, t0, .digit10 - addi t0, a0, 0 - addi a0, a0, '0' - sw a0, 0(s0) - addi a0, x0, 1 - addi a1, s0, 0 - addi a2, x0, 1 - addi a7, x0, 64 ecall - addi t1, x0, '\n' - sw t1, 0(s0) + addi a0, zero, 1 + addi a1, a1, 1 + sub a2, s0, a1 + addi a7, zero, 64 ecall - addi a0, t0, 0 - lw s0, 0(sp) lw ra, 4(sp) - addi sp, sp, 4 + addi sp, sp, 16 ret _start: