Add printc and exit builtin functions

This commit is contained in:
Eugen Wissner 2024-10-04 18:26:10 +02:00
parent fdf56ce9d0
commit 35742aa525
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
20 changed files with 139 additions and 53 deletions

9
TODO
View File

@ -15,16 +15,15 @@
- Format error messages. - Format error messages.
- Return non-zero error code on errors. - Return non-zero error code on errors.
# Built-in
- Implement printc (with int argument).
- Implement exit() as standalone function.
# Register allocation # Register allocation
- Temporary variables always use the same register, t0. Allocate registers for - Temporary variables always use the same register, t0. Allocate registers for
temporaries. temporaries.
# Prarsing and abstract syntax tree
- Parse signed hexadecimal numbers.
# Other # Other
- Type analysis. - Type analysis.

View File

@ -36,6 +36,8 @@ allocate MachineConfiguration{..} = fmap function
SubtractionQuadruple (operand operand1) (operand operand2) (Store temporaryRegister) SubtractionQuadruple (operand operand1) (operand operand2) (Store temporaryRegister)
quadruple (NegationQuadruple operand1 _) = quadruple (NegationQuadruple operand1 _) =
NegationQuadruple (operand operand1) (Store temporaryRegister) NegationQuadruple (operand operand1) (Store temporaryRegister)
quadruple (ProductQuadruple operand1 operand2 _) =
ProductQuadruple (operand operand1) (operand operand2) (Store temporaryRegister)
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 _) = VariableOperand (Store temporaryRegister)

View File

@ -30,11 +30,11 @@ data Quadruple v
| AddQuadruple (Operand v) (Operand v) v | AddQuadruple (Operand v) (Operand v) 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
{-| 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
| ProductQuadruple Operand Operand Variable
| DivisionQuadruple Operand Operand Variable | DivisionQuadruple Operand Operand Variable
| EqualQuadruple Operand Operand Label | EqualQuadruple Operand Operand Label
| NonEqualQuadruple Operand Operand Label | NonEqualQuadruple Operand Operand Label

View File

@ -12,10 +12,12 @@ module Language.Elna.Frontend.AST
, Literal(..) , Literal(..)
) where ) where
import Data.Char (chr)
import Data.Int (Int32) import Data.Int (Int32)
import Data.List (intercalate) import Data.List (intercalate)
import Data.Word ({-Word16, -}Word32) import Data.Word (Word8, Word32)
import Language.Elna.Location (Identifier(..), showArrayType) import Language.Elna.Location (Identifier(..), showArrayType)
import Numeric (showHex)
newtype Program = Program [Declaration] newtype Program = Program [Declaration]
deriving Eq deriving Eq
@ -67,8 +69,8 @@ data Statement
= EmptyStatement = EmptyStatement
{-| AssignmentStatement VariableAccess Expression {-| AssignmentStatement VariableAccess Expression
| IfStatement Condition Statement (Maybe Statement) | IfStatement Condition Statement (Maybe Statement)
| WhileStatement Condition Statement | WhileStatement Condition Statement -}
| CompoundStatement [Statement]-} | CompoundStatement [Statement]
| CallStatement Identifier [Expression] | CallStatement Identifier [Expression]
deriving Eq deriving Eq
@ -83,9 +85,9 @@ instance Show Statement
, maybe "" ((<> " else ") . show) else' , maybe "" ((<> " else ") . show) else'
] ]
show (WhileStatement expression statement) = show (WhileStatement expression statement) =
concat ["while (", show expression, ") ", show statement, ";"] concat ["while (", show expression, ") ", show statement, ";"]-}
show (CompoundStatement statements) = show (CompoundStatement statements) =
concat ["{\n", unlines (show <$> statements), " }"]-} concat ["{\n", unlines (show <$> statements), " }"]
show (CallStatement name parameters) = show name <> "(" show (CallStatement name parameters) = show name <> "("
<> intercalate ", " (show <$> parameters) <> ")" <> intercalate ", " (show <$> parameters) <> ")"
@ -93,22 +95,18 @@ data VariableDeclaration =
VariableDeclaration Identifier TypeExpression VariableDeclaration Identifier TypeExpression
deriving Eq deriving Eq
newtype Literal data Literal
= IntegerLiteral Int32 = IntegerLiteral Int32
{- | HexadecimalLiteral Int32 | HexadecimalLiteral Int32
| CharacterLiteral Word16 | CharacterLiteral Word8
| BooleanLiteral Bool -}
deriving Eq deriving Eq
instance Show Literal instance Show Literal
where where
show (IntegerLiteral integer) = show integer show (IntegerLiteral integer) = show integer
{- show (HexadecimalLiteral integer) = '0' : 'x' : showHex integer "" show (HexadecimalLiteral integer) = '0' : 'x' : showHex integer ""
show (CharacterLiteral character) = show (CharacterLiteral character) =
'\'' : chr (fromEnum character) : ['\''] '\'' : chr (fromEnum character) : ['\'']
show (BooleanLiteral boolean)
| boolean = "true"
| otherwise = "false" -}
instance Show VariableDeclaration instance Show VariableDeclaration
where where
@ -120,8 +118,8 @@ data Expression
| SumExpression Expression Expression | SumExpression Expression Expression
| SubtractionExpression Expression Expression | SubtractionExpression Expression Expression
| NegationExpression Expression | NegationExpression Expression
{- | VariableExpression VariableAccess
| ProductExpression Expression Expression | ProductExpression Expression Expression
{- | VariableExpression VariableAccess
| DivisionExpression Expression Expression -} | DivisionExpression Expression Expression -}
deriving Eq deriving Eq
@ -131,13 +129,10 @@ instance Show Expression
show (SumExpression lhs rhs) = concat [show lhs, " + ", show rhs] show (SumExpression lhs rhs) = concat [show lhs, " + ", show rhs]
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 (VariableExpression variable) = show variable
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] -}
{- {-
import Data.Char (chr)
import Numeric (showHex)
data VariableAccess data VariableAccess
= VariableAccess Identifier = VariableAccess Identifier
| ArrayAccess VariableAccess Expression | ArrayAccess VariableAccess Expression

View File

@ -144,11 +144,11 @@ expression globalTable (AST.SubtractionExpression lhs rhs)
>> expression globalTable rhs >> expression globalTable rhs
expression globalTable (AST.NegationExpression negation) = expression globalTable (AST.NegationExpression negation) =
expression globalTable negation expression globalTable negation
{- expression globalTable (AST.VariableExpression variableExpression) =
variableAccess globalTable variableExpression
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
@ -158,6 +158,8 @@ statement _ AST.EmptyStatement = pure ()
statement globalTable (AST.CallStatement name arguments) statement globalTable (AST.CallStatement name arguments)
= checkSymbol globalTable name = checkSymbol globalTable name
>> traverse_ (expression globalTable) arguments >> traverse_ (expression globalTable) arguments
statement globalTable (AST.CompoundStatement statements) =
traverse_ (statement globalTable) statements
{- statement globalTable (AST.AssignmentStatement lvalue rvalue) {- statement globalTable (AST.AssignmentStatement lvalue rvalue)
= variableAccess globalTable lvalue = variableAccess globalTable lvalue
>> expression globalTable rvalue >> expression globalTable rvalue
@ -168,8 +170,6 @@ statement globalTable (AST.IfStatement ifCondition ifStatement elseStatement)
statement globalTable (AST.WhileStatement whileCondition loop) statement globalTable (AST.WhileStatement whileCondition loop)
= condition globalTable whileCondition = condition globalTable whileCondition
>> statement globalTable loop >> statement globalTable loop
statement globalTable (AST.CompoundStatement statements) =
traverse_ (statement globalTable) statements
variableAccess :: SymbolTable -> AST.VariableAccess -> NameAnalysis () variableAccess :: SymbolTable -> AST.VariableAccess -> NameAnalysis ()
variableAccess globalTable (AST.ArrayAccess arrayExpression indexExpression) variableAccess globalTable (AST.ArrayAccess arrayExpression indexExpression)

View File

@ -34,27 +34,24 @@ import Text.Megaparsec
import qualified Text.Megaparsec.Char.Lexer as Lexer import qualified Text.Megaparsec.Char.Lexer as Lexer
import Text.Megaparsec.Char import Text.Megaparsec.Char
( alphaNumChar ( alphaNumChar
-- , char , char
, letterChar , letterChar
, space1 , space1
-- , string , string
) )
import Control.Applicative (Alternative(..)) import Control.Applicative (Alternative(..))
import Data.Maybe (isJust) import Data.Maybe (isJust)
-- import Data.Functor (($>))
type Parser = Parsec Void Text type Parser = Parsec Void Text
literalP :: Parser Literal literalP :: Parser Literal
literalP literalP
= {- HexadecimalLiteral <$> (string "0x" *> lexeme Lexer.hexadecimal) = HexadecimalLiteral <$> (string "0x" *> lexeme Lexer.hexadecimal)
<|> -} IntegerLiteral <$> Lexer.signed space integerP <|> IntegerLiteral <$> Lexer.signed space integerP
{- <|> CharacterLiteral <$> lexeme charP <|> CharacterLiteral <$> lexeme charP
<|> BooleanLiteral <$> (symbol "true" $> True)
<|> BooleanLiteral <$> (symbol "false" $> False)
where where
charP = fromIntegral . fromEnum charP = fromIntegral . fromEnum
<$> between (char '\'') (char '\'') Lexer.charLiteral -} <$> between (char '\'') (char '\'') Lexer.charLiteral
{- {-
typeDefinitionP :: Parser Declaration typeDefinitionP :: Parser Declaration
typeDefinitionP = TypeDefinition typeDefinitionP = TypeDefinition
@ -73,7 +70,7 @@ termP = choice
operatorTable :: [[Operator Parser Expression]] operatorTable :: [[Operator Parser Expression]]
operatorTable = operatorTable =
[ unaryOperator [ unaryOperator
-- , factorOperator , factorOperator
, termOperator , termOperator
] ]
where where
@ -81,10 +78,10 @@ operatorTable =
[ prefix "-" NegationExpression [ prefix "-" NegationExpression
, prefix "+" id , prefix "+" id
] ]
{- factorOperator = factorOperator =
[ binary "*" ProductExpression [ binary "*" ProductExpression
, binary "/" DivisionExpression -- , binary "/" DivisionExpression
] -} ]
termOperator = termOperator =
[ binary "+" SumExpression [ binary "+" SumExpression
, binary "-" SubtractionExpression , binary "-" SubtractionExpression

View File

@ -40,9 +40,22 @@ scope parent (SymbolTable _ mappings) = SymbolTable (Just parent) mappings
builtInSymbolTable :: SymbolTable builtInSymbolTable :: SymbolTable
builtInSymbolTable = SymbolTable Nothing $ HashMap.fromList builtInSymbolTable = SymbolTable Nothing $ HashMap.fromList
[ ("printi", ProcedureInfo empty Vector.empty) [ ("printi", ProcedureInfo empty (Vector.singleton printiX))
, ("printc", ProcedureInfo empty (Vector.singleton printcI))
, ("exit", ProcedureInfo empty Vector.empty)
, ("int", TypeInfo intType) , ("int", TypeInfo intType)
] ]
where
printiX = ParameterInfo
{ name = "x"
, type' = intType
, isReferenceParameter = False
}
printcI = ParameterInfo
{ name = "i"
, type' = intType
, isReferenceParameter = False
}
toMap :: SymbolTable -> HashMap Identifier Info toMap :: SymbolTable -> HashMap Identifier Info
toMap (SymbolTable _ map') = map' toMap (SymbolTable _ map') = map'

View File

@ -70,6 +70,8 @@ statement localTable (AST.CallStatement (AST.Identifier callName) arguments) = d
$ CallQuadruple callName $ CallQuadruple callName
$ fromIntegral $ fromIntegral
$ Vector.length argumentStatements $ Vector.length argumentStatements
statement localTable (AST.CompoundStatement statements) =
fold <$> traverse (statement localTable) statements
{- statement localTable (AST.AssignmentStatement variableAccess' assignee) = do {- statement localTable (AST.AssignmentStatement variableAccess' assignee) = do
(rhsOperand, rhsStatements) <- expression localTable assignee (rhsOperand, rhsStatements) <- expression localTable assignee
let variableType' = variableType variableAccess' localTable let variableType' = variableType variableAccess' localTable
@ -105,9 +107,7 @@ statement localTable (AST.WhileStatement whileCondition whileStatement) = do
<> conditionStatements <> conditionStatements
<> Vector.fromList [jumpConstructor startLabel, GoToQuadruple endLabel, LabelQuadruple startLabel] <> Vector.fromList [jumpConstructor startLabel, GoToQuadruple endLabel, LabelQuadruple startLabel]
<> whileStatements <> whileStatements
<> Vector.fromList [GoToQuadruple conditionLabel, LabelQuadruple endLabel] <> Vector.fromList [GoToQuadruple conditionLabel, LabelQuadruple endLabel] -}
statement localTable (AST.CompoundStatement statements) =
fold <$> traverse (statement localTable) statements -}
createTemporary :: Glue Variable createTemporary :: Glue Variable
createTemporary = do createTemporary = do
@ -233,6 +233,8 @@ expression localTable = \case
( VariableOperand tempVariable ( VariableOperand tempVariable
, Vector.snoc statements negationQuadruple , Vector.snoc statements negationQuadruple
) )
(AST.ProductExpression lhs rhs) ->
binaryExpression ProductQuadruple 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
@ -246,8 +248,6 @@ expression localTable = \case
( VariableOperand arrayAddress ( VariableOperand arrayAddress
, Vector.snoc statements arrayStatement , Vector.snoc statements arrayStatement
) )
(AST.ProductExpression lhs rhs) ->
binaryExpression ProductQuadruple lhs rhs
(AST.DivisionExpression lhs rhs) -> (AST.DivisionExpression lhs rhs) ->
binaryExpression DivisionQuadruple lhs rhs -} binaryExpression DivisionQuadruple lhs rhs -}
where where
@ -263,8 +263,5 @@ expression localTable = \case
literal :: AST.Literal -> Operand Variable literal :: AST.Literal -> Operand Variable
literal (AST.IntegerLiteral integer) = IntOperand integer literal (AST.IntegerLiteral integer) = IntOperand integer
{-literal (AST.HexadecimalLiteral integer) = IntOperand integer literal (AST.HexadecimalLiteral integer) = IntOperand integer
literal (AST.CharacterLiteral character) = IntOperand $ fromIntegral character literal (AST.CharacterLiteral character) = IntOperand $ fromIntegral character
literal (AST.BooleanLiteral boolean)
| boolean = IntOperand 1
| otherwise = IntOperand 0 -}

View File

@ -132,6 +132,32 @@ quadruple (NegationQuadruple operand1 (Store register))
$ RiscV.BaseInstruction RiscV.Op $ RiscV.BaseInstruction RiscV.Op
$ RiscV.R register RiscV.SUB RiscV.Zero operandRegister1 $ RiscV.R register RiscV.SUB RiscV.Zero operandRegister1
$ RiscV.Funct7 0b0100000 $ RiscV.Funct7 0b0100000
quadruple (ProductQuadruple operand1 operand2 (Store register))
| IntOperand immediateOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
lui (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.MUL operandRegister1 operandRegister2 (RiscV.Funct7 0b0000001)
| VariableOperand variableOperand1 <- operand1
, IntOperand immediateOperand2 <- operand2 =
multiplyImmediateRegister variableOperand1 immediateOperand2
| IntOperand immediateOperand1 <- operand1
, VariableOperand variableOperand2 <- operand2 =
multiplyImmediateRegister variableOperand2 immediateOperand1
where
multiplyImmediateRegister variableOperand immediateOperand =
let statements = lui immediateOperand register
Store operandRegister = variableOperand
in Vector.snoc statements
$ Instruction
$ RiscV.BaseInstruction RiscV.Op
$ RiscV.R register RiscV.MUL register operandRegister
$ 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 =

View File

@ -0,0 +1 @@
c

View File

@ -0,0 +1,2 @@
13
2097150

View File

@ -0,0 +1 @@
x

View File

@ -0,0 +1 @@
1000

View File

@ -0,0 +1 @@
129

View File

@ -0,0 +1,5 @@
proc main() {
printc('c');
exit();
printi(1234);
}

View File

@ -0,0 +1,4 @@
proc main() {
printi(13);
printi(2097150);
}

3
tests/vm/print_char.elna Normal file
View File

@ -0,0 +1,3 @@
proc main() {
printc('x');
}

View File

@ -0,0 +1,3 @@
proc main() {
printi(20 * 50);
}

3
tests/vm/printi_hex.elna Normal file
View File

@ -0,0 +1,3 @@
proc main() {
printi(0x81);
}

View File

@ -1,6 +1,12 @@
.global printi .global printi
.type printi, @function .type printi, @function
.global printc
.type printc, @function
.global exit
.type exit, @function
.global _start .global _start
.type _start, @function .type _start, @function
@ -53,8 +59,35 @@ printi:
addi sp, sp, 16 addi sp, sp, 16
ret ret
_start: printc:
call main addi sp, sp, -12
sw s0, 0(sp)
sw ra, 4(sp)
addi s0, sp, 12
addi t1, zero, '\n'
sb t1, -1(s0)
lw t0, 0(s0)
sb t0, -2(s0)
addi a0, zero, 1
addi a1, s0, -2
addi a2, zero, 2
addi a7, zero, 64
ecall
lw s0, 0(sp)
lw ra, 4(sp)
addi sp, sp, 12
ret
exit:
addi a0, zero, 0 addi a0, zero, 0
addi a7, zero, 93 addi a7, zero, 93
ecall ecall
# ret
_start:
call main
call exit