Generate a call to _divide_by_zero_error on RiscV
This commit is contained in:
parent
6b92e5059c
commit
43882a3a06
5
TODO
5
TODO
@ -21,11 +21,6 @@
|
|||||||
there more variables the allocation will fail with out of bounds runtime
|
there more variables the allocation will fail with out of bounds runtime
|
||||||
error. Implement spill over.
|
error. Implement spill over.
|
||||||
|
|
||||||
# Prarsing and abstract syntax tree
|
|
||||||
|
|
||||||
- Parse signed hexadecimal numbers.
|
|
||||||
|
|
||||||
# Other
|
# Other
|
||||||
|
|
||||||
- Type analysis.
|
- Type analysis.
|
||||||
- Generate a call to _divide_by_zero_error on RiscV.
|
|
||||||
|
@ -15,9 +15,10 @@ module Language.Elna.Frontend.AST
|
|||||||
import Data.Char (chr)
|
import Data.Char (chr)
|
||||||
import Data.Int (Int32)
|
import Data.Int (Int32)
|
||||||
import Data.List (intercalate)
|
import Data.List (intercalate)
|
||||||
import Data.Word (Word8, Word32)
|
import Data.Word (Word8)
|
||||||
import Language.Elna.Location (Identifier(..), showArrayType)
|
import Language.Elna.Location (Identifier(..), showArrayType)
|
||||||
import Numeric (showHex)
|
import Numeric (showHex)
|
||||||
|
import Data.Bifunctor (Bifunctor(bimap))
|
||||||
|
|
||||||
newtype Program = Program [Declaration]
|
newtype Program = Program [Declaration]
|
||||||
deriving Eq
|
deriving Eq
|
||||||
@ -57,13 +58,14 @@ showParameters parameters =
|
|||||||
|
|
||||||
data TypeExpression
|
data TypeExpression
|
||||||
= NamedType Identifier
|
= NamedType Identifier
|
||||||
| ArrayType Word32 TypeExpression
|
| ArrayType Literal TypeExpression
|
||||||
deriving Eq
|
deriving Eq
|
||||||
|
|
||||||
instance Show TypeExpression
|
instance Show TypeExpression
|
||||||
where
|
where
|
||||||
show (NamedType typeName) = show typeName
|
show (NamedType typeName) = show typeName
|
||||||
show (ArrayType elementCount typeName) = showArrayType elementCount typeName
|
show (ArrayType elementCount typeName) =
|
||||||
|
showArrayType elementCount typeName
|
||||||
|
|
||||||
data Statement
|
data Statement
|
||||||
= EmptyStatement
|
= EmptyStatement
|
||||||
@ -96,18 +98,59 @@ data VariableDeclaration =
|
|||||||
deriving Eq
|
deriving Eq
|
||||||
|
|
||||||
data Literal
|
data Literal
|
||||||
= IntegerLiteral Int32
|
= DecimalLiteral Int32
|
||||||
| HexadecimalLiteral Int32
|
| HexadecimalLiteral Int32
|
||||||
| CharacterLiteral Word8
|
| CharacterLiteral Word8
|
||||||
deriving Eq
|
deriving Eq
|
||||||
|
|
||||||
instance Show Literal
|
instance Show Literal
|
||||||
where
|
where
|
||||||
show (IntegerLiteral integer) = show integer
|
show (DecimalLiteral 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) : ['\'']
|
||||||
|
|
||||||
|
instance Ord Literal
|
||||||
|
where
|
||||||
|
compare x y = compare (int32Literal x) (int32Literal y)
|
||||||
|
|
||||||
|
instance Num Literal
|
||||||
|
where
|
||||||
|
x + y = DecimalLiteral $ int32Literal x + int32Literal y
|
||||||
|
x * y = DecimalLiteral $ int32Literal x * int32Literal y
|
||||||
|
abs (DecimalLiteral x) = DecimalLiteral $ abs x
|
||||||
|
abs (HexadecimalLiteral x) = HexadecimalLiteral $ abs x
|
||||||
|
abs (CharacterLiteral x) = CharacterLiteral $ abs x
|
||||||
|
negate (DecimalLiteral x) = DecimalLiteral $ negate x
|
||||||
|
negate (HexadecimalLiteral x) = HexadecimalLiteral $ negate x
|
||||||
|
negate (CharacterLiteral x) = CharacterLiteral $ negate x
|
||||||
|
signum (DecimalLiteral x) = DecimalLiteral $ signum x
|
||||||
|
signum (HexadecimalLiteral x) = HexadecimalLiteral $ signum x
|
||||||
|
signum (CharacterLiteral x) = CharacterLiteral $ signum x
|
||||||
|
fromInteger = DecimalLiteral . fromInteger
|
||||||
|
|
||||||
|
instance Real Literal
|
||||||
|
where
|
||||||
|
toRational (DecimalLiteral integer) = toRational integer
|
||||||
|
toRational (HexadecimalLiteral integer) = toRational integer
|
||||||
|
toRational (CharacterLiteral integer) = toRational integer
|
||||||
|
|
||||||
|
instance Enum Literal
|
||||||
|
where
|
||||||
|
toEnum = DecimalLiteral . fromIntegral
|
||||||
|
fromEnum = fromEnum . int32Literal
|
||||||
|
|
||||||
|
instance Integral Literal
|
||||||
|
where
|
||||||
|
toInteger = toInteger . int32Literal
|
||||||
|
quotRem x y = bimap DecimalLiteral DecimalLiteral
|
||||||
|
$ quotRem (int32Literal x) (int32Literal y)
|
||||||
|
|
||||||
|
int32Literal :: Literal -> Int32
|
||||||
|
int32Literal (DecimalLiteral integer) = integer
|
||||||
|
int32Literal (HexadecimalLiteral integer) = integer
|
||||||
|
int32Literal (CharacterLiteral integer) = fromIntegral integer
|
||||||
|
|
||||||
instance Show VariableDeclaration
|
instance Show VariableDeclaration
|
||||||
where
|
where
|
||||||
show (VariableDeclaration identifier typeExpression) =
|
show (VariableDeclaration identifier typeExpression) =
|
||||||
|
@ -134,7 +134,7 @@ dataType environmentSymbolTable (AST.NamedType baseType) = do
|
|||||||
| otherwise -> NameAnalysis $ throwE $ UnexpectedTypeInfoError baseInfo
|
| otherwise -> NameAnalysis $ throwE $ UnexpectedTypeInfoError baseInfo
|
||||||
_ -> NameAnalysis $ throwE $ UndefinedTypeError baseType
|
_ -> NameAnalysis $ throwE $ UndefinedTypeError baseType
|
||||||
dataType environmentSymbolTable (AST.ArrayType arraySize baseType) =
|
dataType environmentSymbolTable (AST.ArrayType arraySize baseType) =
|
||||||
dataType environmentSymbolTable baseType <&> ArrayType arraySize
|
dataType environmentSymbolTable baseType <&> ArrayType (fromIntegral arraySize)
|
||||||
|
|
||||||
checkSymbol :: SymbolTable -> Identifier -> NameAnalysis ()
|
checkSymbol :: SymbolTable -> Identifier -> NameAnalysis ()
|
||||||
checkSymbol globalTable identifier
|
checkSymbol globalTable identifier
|
||||||
|
@ -46,8 +46,8 @@ type Parser = Parsec Void Text
|
|||||||
|
|
||||||
literalP :: Parser Literal
|
literalP :: Parser Literal
|
||||||
literalP
|
literalP
|
||||||
= HexadecimalLiteral <$> (string "0x" *> lexeme Lexer.hexadecimal)
|
= HexadecimalLiteral <$> Lexer.signed space hexadecimalP
|
||||||
<|> IntegerLiteral <$> Lexer.signed space integerP
|
<|> DecimalLiteral <$> Lexer.signed space decimalP
|
||||||
<|> CharacterLiteral <$> lexeme charP
|
<|> CharacterLiteral <$> lexeme charP
|
||||||
where
|
where
|
||||||
charP = fromIntegral . fromEnum
|
charP = fromIntegral . fromEnum
|
||||||
@ -141,8 +141,11 @@ commaP = void $ symbol ","
|
|||||||
semicolonP :: Parser ()
|
semicolonP :: Parser ()
|
||||||
semicolonP = void $ symbol ";"
|
semicolonP = void $ symbol ";"
|
||||||
|
|
||||||
integerP :: Integral a => Parser a
|
decimalP :: Integral a => Parser a
|
||||||
integerP = lexeme Lexer.decimal
|
decimalP = lexeme Lexer.decimal
|
||||||
|
|
||||||
|
hexadecimalP :: Integral a => Parser a
|
||||||
|
hexadecimalP = string "0x" *> lexeme Lexer.hexadecimal
|
||||||
|
|
||||||
identifierP :: Parser Identifier
|
identifierP :: Parser Identifier
|
||||||
identifierP =
|
identifierP =
|
||||||
@ -166,7 +169,7 @@ typeExpressionP = arrayTypeExpression
|
|||||||
<?> "type expression"
|
<?> "type expression"
|
||||||
where
|
where
|
||||||
arrayTypeExpression = ArrayType
|
arrayTypeExpression = ArrayType
|
||||||
<$> (symbol "array" *> bracketsP integerP)
|
<$> (symbol "array" *> bracketsP literalP)
|
||||||
<*> (symbol "of" *> typeExpressionP)
|
<*> (symbol "of" *> typeExpressionP)
|
||||||
|
|
||||||
procedureDeclarationP :: Parser Declaration
|
procedureDeclarationP :: Parser Declaration
|
||||||
|
@ -267,6 +267,6 @@ expression localTable = \case
|
|||||||
)
|
)
|
||||||
|
|
||||||
literal :: AST.Literal -> Operand Variable
|
literal :: AST.Literal -> Operand Variable
|
||||||
literal (AST.IntegerLiteral integer) = IntOperand integer
|
literal (AST.DecimalLiteral 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
|
||||||
|
@ -53,6 +53,6 @@ instance Hashable Identifier
|
|||||||
where
|
where
|
||||||
hashWithSalt salt (Identifier identifier) = hashWithSalt salt identifier
|
hashWithSalt salt (Identifier identifier) = hashWithSalt salt identifier
|
||||||
|
|
||||||
showArrayType :: Show a => Word32 -> a -> String
|
showArrayType :: (Show a, Show b) => a -> b -> String
|
||||||
showArrayType elementCount typeName = concat
|
showArrayType elementCount typeName = concat
|
||||||
["array[", show elementCount, "] of ", show typeName]
|
["array[", show elementCount, "] of ", show typeName]
|
||||||
|
@ -234,20 +234,31 @@ quadruple (DivisionQuadruple operand1 operand2 (Store register))
|
|||||||
, IntOperand immediateOperand2 <- operand2 =
|
, IntOperand immediateOperand2 <- operand2 =
|
||||||
let statements2 = lui immediateOperand2 register
|
let statements2 = lui immediateOperand2 register
|
||||||
Store operandRegister1 = variableOperand1
|
Store operandRegister1 = variableOperand1
|
||||||
in pure $ Vector.snoc statements2
|
operationInstruction
|
||||||
$ Instruction
|
| immediateOperand2 == 0 =
|
||||||
$ RiscV.BaseInstruction RiscV.Op
|
RiscV.CallInstruction "_divide_by_zero_error"
|
||||||
$ RiscV.R register RiscV.DIV operandRegister1 register
|
| otherwise = RiscV.BaseInstruction RiscV.Op
|
||||||
$ RiscV.Funct7 0b0000001
|
$ RiscV.R register RiscV.DIV operandRegister1 register
|
||||||
|
$ RiscV.Funct7 0b0000001
|
||||||
|
in pure $ Vector.snoc statements2
|
||||||
|
$ Instruction operationInstruction
|
||||||
| IntOperand immediateOperand1 <- operand1
|
| IntOperand immediateOperand1 <- operand1
|
||||||
, VariableOperand variableOperand2 <- operand2 =
|
, VariableOperand variableOperand2 <- operand2 = do
|
||||||
let statements1 = lui immediateOperand1 register
|
let statements1 = lui immediateOperand1 register
|
||||||
Store operandRegister2 = variableOperand2
|
Store operandRegister2 = variableOperand2
|
||||||
in pure $ Vector.snoc statements1
|
divisionInstruction = Instruction
|
||||||
$ Instruction
|
$ RiscV.BaseInstruction RiscV.Op
|
||||||
$ RiscV.BaseInstruction RiscV.Op
|
$ RiscV.R register RiscV.DIV register operandRegister2 (RiscV.Funct7 0b0000001)
|
||||||
$ RiscV.R register RiscV.DIV register operandRegister2
|
branchLabel <- createLabel
|
||||||
$ RiscV.Funct7 0b0000001
|
let branchInstruction = Instruction
|
||||||
|
$ RiscV.RelocatableInstruction RiscV.Branch
|
||||||
|
$ RiscV.RBranch branchLabel RiscV.BNE RiscV.Zero operandRegister2
|
||||||
|
pure $ mappend statements1 $ Vector.fromList
|
||||||
|
[ branchInstruction
|
||||||
|
, Instruction (RiscV.CallInstruction "_divide_by_zero_error")
|
||||||
|
, JumpLabel branchLabel []
|
||||||
|
, divisionInstruction
|
||||||
|
]
|
||||||
quadruple (LabelQuadruple (Label label)) = pure $ Vector.singleton $ JumpLabel label mempty
|
quadruple (LabelQuadruple (Label label)) = pure $ Vector.singleton $ JumpLabel label mempty
|
||||||
quadruple (GoToQuadruple label) = pure $ Vector.singleton $ unconditionalJal label
|
quadruple (GoToQuadruple label) = pure $ Vector.singleton $ unconditionalJal label
|
||||||
quadruple (EqualQuadruple operand1 operand2 goToLabel)
|
quadruple (EqualQuadruple operand1 operand2 goToLabel)
|
||||||
|
1
tests/expectations/printi_negative_hex.txt
Normal file
1
tests/expectations/printi_negative_hex.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
-129
|
1
tests/expectations/printi_signed_hex.txt
Normal file
1
tests/expectations/printi_signed_hex.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
129
|
3
tests/vm/printi_negative_hex.elna
Normal file
3
tests/vm/printi_negative_hex.elna
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
proc main() {
|
||||||
|
printi(-0x81);
|
||||||
|
}
|
3
tests/vm/printi_signed_hex.elna
Normal file
3
tests/vm/printi_signed_hex.elna
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
proc main() {
|
||||||
|
printi(+0x81);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user