style: improve code formatting and consistency in typeChecker and assemblyIR

This commit is contained in:
Guy C 2025-02-25 00:05:10 +00:00
parent 1488281223
commit f30cf42c4b
3 changed files with 147 additions and 138 deletions

View File

@ -19,7 +19,7 @@ object asmGenerator {
val RBP = Register(RegSize.R64, RegName.BP) val RBP = Register(RegSize.R64, RegName.BP)
val RSI = Register(RegSize.R64, RegName.SI) val RSI = Register(RegSize.R64, RegName.SI)
val _8_BIT_MASK = 0xFF val _8_BIT_MASK = 0xff
object labelGenerator { object labelGenerator {
var labelVal = -1 var labelVal = -1
@ -27,8 +27,8 @@ object asmGenerator {
labelVal += 1 labelVal += 1
s".L$labelVal" s".L$labelVal"
} }
def getLabel(target: CallTarget): String = target match{ def getLabel(target: CallTarget): String = target match {
case Ident(v,_) => s"wacc_$v" case Ident(v, _) => s"wacc_$v"
case Builtin(name) => s"_$name" case Builtin(name) => s"_$name"
} }
} }
@ -61,33 +61,31 @@ object asmGenerator {
strings: ListBuffer[String] strings: ListBuffer[String]
): List[AsmLine] = { ): List[AsmLine] = {
LabelDef(labelName) :: LabelDef(labelName) ::
funcPrologue() ++ funcPrologue() ++
funcBody ++ funcBody ++
funcEpilogue() funcEpilogue()
} }
def generateBuiltInFuncs()(using def generateBuiltInFuncs()(using
stack: LinkedHashMap[Ident, Int], stack: LinkedHashMap[Ident, Int],
strings: ListBuffer[String] strings: ListBuffer[String]
): List[AsmLine] = { ): List[AsmLine] = {
wrapFunc(labelGenerator.getLabel(Builtin.Exit), wrapFunc(
labelGenerator.getLabel(Builtin.Exit),
alignStack() ++ alignStack() ++
List(Pop(RDI), List(Pop(RDI), assemblyIR.Call(CLibFunc.Exit))
assemblyIR.Call(CLibFunc.Exit))
) ++ ) ++
wrapFunc(labelGenerator.getLabel(Builtin.Printf), wrapFunc(
alignStack() ++ labelGenerator.getLabel(Builtin.Printf),
List(assemblyIR.Call(CLibFunc.PrintF), alignStack() ++
Move(RDI, ImmediateVal(0)), List(
assemblyIR.Call(CLibFunc.Fflush) assemblyIR.Call(CLibFunc.PrintF),
) Move(RDI, ImmediateVal(0)),
)++ assemblyIR.Call(CLibFunc.Fflush)
wrapFunc(labelGenerator.getLabel(Builtin.Malloc), )
List() ) ++
)++ wrapFunc(labelGenerator.getLabel(Builtin.Malloc), List()) ++
wrapFunc(labelGenerator.getLabel(Builtin.Free), wrapFunc(labelGenerator.getLabel(Builtin.Free), List())
List()
)
} }
def generateStmt( def generateStmt(
@ -95,7 +93,7 @@ object asmGenerator {
)(using stack: LinkedHashMap[Ident, Int], strings: ListBuffer[String]): List[AsmLine] = )(using stack: LinkedHashMap[Ident, Int], strings: ListBuffer[String]): List[AsmLine] =
stmt match { stmt match {
case microWacc.Call(Builtin.Exit, code :: _) => case microWacc.Call(Builtin.Exit, code :: _) =>
List() List()
case Assign(lhs, rhs) => case Assign(lhs, rhs) =>
var dest: IndexAddress = var dest: IndexAddress =
IndexAddress(RSP, 0) // gets overrwitten IndexAddress(RSP, 0) // gets overrwitten
@ -188,97 +186,100 @@ object asmGenerator {
// TODO other array types // TODO other array types
case _ => List() case _ => List()
} }
case BoolLiter(v) => List(Push(ImmediateVal(if (v) 1 else 0))) case BoolLiter(v) => List(Push(ImmediateVal(if (v) 1 else 0)))
case NullLiter() => List(Push(ImmediateVal(0))) case NullLiter() => List(Push(ImmediateVal(0)))
case ArrayElem(value, indices) => List() case ArrayElem(value, indices) => List()
case UnaryOp(x, op) => op match { case UnaryOp(x, op) =>
// TODO: chr and ord are TYPE CASTS. They do not change the internal value, op match {
// but will need bound checking e.t.c. // TODO: chr and ord are TYPE CASTS. They do not change the internal value,
case UnaryOperator.Chr => List() // but will need bound checking e.t.c.
case UnaryOperator.Ord => List() case UnaryOperator.Chr => List()
case UnaryOperator.Len => List() case UnaryOperator.Ord => List()
case UnaryOperator.Negate => List( case UnaryOperator.Len => List()
Negate(MemLocation(RSP,SizeDir.Word)) case UnaryOperator.Negate =>
) List(
case UnaryOperator.Not => Negate(MemLocation(RSP, SizeDir.Word))
evalExprOntoStack(x) ++
List(
Xor(MemLocation(RSP, SizeDir.Word), ImmediateVal(1))
)
}
case BinaryOp(x, y, op) => op match {
case BinaryOperator.Add =>
evalExprOntoStack(x) ++
evalExprOntoStack(y) ++
List(
Pop(EAX),
Add(MemLocation(RSP, SizeDir.Word), EAX)
// TODO OVERFLOWING
)
case BinaryOperator.Sub =>
evalExprOntoStack(x) ++
evalExprOntoStack(y) ++
List(
Pop(EAX),
Subtract(MemLocation(RSP, SizeDir.Word), EAX)
// TODO OVERFLOWING
)
case BinaryOperator.Mul =>
evalExprOntoStack(x) ++
evalExprOntoStack(y) ++
List(
Pop(EAX),
Multiply(MemLocation(RSP, SizeDir.Word), EAX)
// TODO OVERFLOWING
)
case BinaryOperator.Div =>
evalExprOntoStack(y) ++
evalExprOntoStack(x) ++
List(
Pop(EAX),
Divide(MemLocation(RSP, SizeDir.Word)),
Add(RSP, ImmediateVal(8)),
Push(EAX)
// TODO CHECK DIVISOR IS NOT 0
)
case BinaryOperator.Mod =>
evalExprOntoStack(y) ++
evalExprOntoStack(x) ++
List(
Pop(EAX),
Divide(MemLocation(RSP, SizeDir.Word)),
Add(RSP, ImmediateVal(8)),
Push(EDX)
// TODO CHECK DIVISOR IS NOT 0
) )
case BinaryOperator.Eq => case UnaryOperator.Not =>
generateComparison(x, y, Cond.Equal) evalExprOntoStack(x) ++
case BinaryOperator.Neq => List(
generateComparison(x, y, Cond.NotEqual) Xor(MemLocation(RSP, SizeDir.Word), ImmediateVal(1))
case BinaryOperator.Greater => )
generateComparison(x, y, Cond.Greater)
case BinaryOperator.GreaterEq => }
generateComparison(x, y, Cond.GreaterEqual) case BinaryOp(x, y, op) =>
case BinaryOperator.Less => op match {
generateComparison(x, y, Cond.Less) case BinaryOperator.Add =>
case BinaryOperator.LessEq => evalExprOntoStack(x) ++
generateComparison(x, y, Cond.LessEqual) evalExprOntoStack(y) ++
case BinaryOperator.And => List(
evalExprOntoStack(x) ++ Pop(EAX),
evalExprOntoStack(y) ++ Add(MemLocation(RSP, SizeDir.Word), EAX)
List( // TODO OVERFLOWING
Pop(EAX), )
And(MemLocation(RSP, SizeDir.Word), EAX), case BinaryOperator.Sub =>
) evalExprOntoStack(x) ++
case BinaryOperator.Or => evalExprOntoStack(y) ++
evalExprOntoStack(x) ++ List(
evalExprOntoStack(y) ++ Pop(EAX),
List( Subtract(MemLocation(RSP, SizeDir.Word), EAX)
Pop(EAX), // TODO OVERFLOWING
Or(MemLocation(RSP, SizeDir.Word), EAX), )
) case BinaryOperator.Mul =>
} evalExprOntoStack(x) ++
evalExprOntoStack(y) ++
List(
Pop(EAX),
Multiply(MemLocation(RSP, SizeDir.Word), EAX)
// TODO OVERFLOWING
)
case BinaryOperator.Div =>
evalExprOntoStack(y) ++
evalExprOntoStack(x) ++
List(
Pop(EAX),
Divide(MemLocation(RSP, SizeDir.Word)),
Add(RSP, ImmediateVal(8)),
Push(EAX)
// TODO CHECK DIVISOR IS NOT 0
)
case BinaryOperator.Mod =>
evalExprOntoStack(y) ++
evalExprOntoStack(x) ++
List(
Pop(EAX),
Divide(MemLocation(RSP, SizeDir.Word)),
Add(RSP, ImmediateVal(8)),
Push(EDX)
// TODO CHECK DIVISOR IS NOT 0
)
case BinaryOperator.Eq =>
generateComparison(x, y, Cond.Equal)
case BinaryOperator.Neq =>
generateComparison(x, y, Cond.NotEqual)
case BinaryOperator.Greater =>
generateComparison(x, y, Cond.Greater)
case BinaryOperator.GreaterEq =>
generateComparison(x, y, Cond.GreaterEqual)
case BinaryOperator.Less =>
generateComparison(x, y, Cond.Less)
case BinaryOperator.LessEq =>
generateComparison(x, y, Cond.LessEqual)
case BinaryOperator.And =>
evalExprOntoStack(x) ++
evalExprOntoStack(y) ++
List(
Pop(EAX),
And(MemLocation(RSP, SizeDir.Word), EAX)
)
case BinaryOperator.Or =>
evalExprOntoStack(x) ++
evalExprOntoStack(y) ++
List(
Pop(EAX),
Or(MemLocation(RSP, SizeDir.Word), EAX)
)
}
case microWacc.Call(target, args) => List() case microWacc.Call(target, args) => List()
} }
} }
@ -308,19 +309,19 @@ object asmGenerator {
// } // }
def generateComparison(x : Expr, y: Expr, cond: Cond)(using def generateComparison(x: Expr, y: Expr, cond: Cond)(using
stack: LinkedHashMap[Ident, Int], stack: LinkedHashMap[Ident, Int],
strings: ListBuffer[String] strings: ListBuffer[String]
): List[AsmLine] = { ): List[AsmLine] = {
evalExprOntoStack(x) ++ evalExprOntoStack(x) ++
evalExprOntoStack(y) ++ evalExprOntoStack(y) ++
List( List(
Pop(EAX), Pop(EAX),
Compare(MemLocation(RSP, SizeDir.Word), EAX), Compare(MemLocation(RSP, SizeDir.Word), EAX),
Set(Register(RegSize.Byte, RegName.AL), cond), Set(Register(RegSize.Byte, RegName.AL), cond),
And(EAX, ImmediateVal(_8_BIT_MASK)), And(EAX, ImmediateVal(_8_BIT_MASK)),
Push(EAX) Push(EAX)
) )
} }
def accessVar(ident: Ident)(using stack: LinkedHashMap[Ident, Int]): IndexAddress = def accessVar(ident: Ident)(using stack: LinkedHashMap[Ident, Int]): IndexAddress =
IndexAddress(RSP, (stack.size - stack(ident)) * 8) IndexAddress(RSP, (stack.size - stack(ident)) * 8)
@ -397,8 +398,8 @@ object asmGenerator {
) )
} else { } else {
evalExprOntoStack(expr) ++ evalExprOntoStack(expr) ++
List(Pop(RSI)) List(Pop(RSI))
}) })
// print the value // print the value
++ ++

View File

@ -12,14 +12,15 @@ object assemblyIR {
case Byte case Byte
override def toString = this match { override def toString = this match {
case R64 => "r" case R64 => "r"
case E32 => "e" case E32 => "e"
case Byte => "" case Byte => ""
} }
} }
enum RegName { enum RegName {
case AX, AL, BX, CX, DX, SI, DI, SP, BP, IP, Reg8, Reg9, Reg10, Reg11, Reg12, Reg13, Reg14, Reg15 case AX, AL, BX, CX, DX, SI, DI, SP, BP, IP, Reg8, Reg9, Reg10, Reg11, Reg12, Reg13, Reg14,
Reg15
override def toString = this match { override def toString = this match {
case AX => "ax" case AX => "ax"
case AL => "al" case AL => "al"
@ -59,17 +60,24 @@ object assemblyIR {
} }
} }
//TODO register naming conventions are wrong // TODO register naming conventions are wrong
case class Register(size: RegSize, name: RegName) extends Dest with Src { case class Register(size: RegSize, name: RegName) extends Dest with Src {
override def toString = s"${size}${name}" override def toString = s"${size}${name}"
} }
case class MemLocation(pointer: Long | Register, opSize: SizeDir = SizeDir.Unspecified) extends Dest with Src { case class MemLocation(pointer: Long | Register, opSize: SizeDir = SizeDir.Unspecified)
extends Dest
with Src {
override def toString = pointer match { override def toString = pointer match {
case hex: Long => opSize.toString + f"[0x$hex%X]" case hex: Long => opSize.toString + f"[0x$hex%X]"
case reg: Register => opSize.toString + s"[$reg]" case reg: Register => opSize.toString + s"[$reg]"
} }
} }
case class IndexAddress(base: Register, offset: Int | LabelArg, opSize: SizeDir = SizeDir.Unspecified) extends Dest with Src { case class IndexAddress(
base: Register,
offset: Int | LabelArg,
opSize: SizeDir = SizeDir.Unspecified
) extends Dest
with Src {
override def toString = s"$opSize[$base + $offset]" override def toString = s"$opSize[$base + $offset]"
} }
@ -111,7 +119,7 @@ object assemblyIR {
extends Operation(s"j${condition.toString}", op1) extends Operation(s"j${condition.toString}", op1)
case class Set(op1: Dest, condition: Cond = Cond.Always) case class Set(op1: Dest, condition: Cond = Cond.Always)
extends Operation(s"set${condition.toString}", op1) extends Operation(s"set${condition.toString}", op1)
case class LabelDef(name: String) extends AsmLine { case class LabelDef(name: String) extends AsmLine {
override def toString = s"$name:" override def toString = s"$name:"
@ -165,14 +173,14 @@ object assemblyIR {
} }
enum SizeDir { enum SizeDir {
case Byte, Word, Unspecified case Byte, Word, Unspecified
private val ptr = "ptr " private val ptr = "ptr "
override def toString(): String = this match { override def toString(): String = this match {
case Byte => "byte " + ptr case Byte => "byte " + ptr
case Word => "word " + ptr case Word => "word " + ptr
case Unspecified => "" case Unspecified => ""
} }
} }
} }

View File

@ -180,7 +180,7 @@ object typeChecker {
microWacc.Builtin.Read, microWacc.Builtin.Read,
List( List(
destTy match { destTy match {
case KnownType.Int => "%d".toMicroWaccCharArray case KnownType.Int => "%d".toMicroWaccCharArray
case KnownType.Char | _ => "%c".toMicroWaccCharArray case KnownType.Char | _ => "%c".toMicroWaccCharArray
}, },
destTyped destTyped
@ -218,9 +218,9 @@ object typeChecker {
val exprTyped = checkValue(expr, Constraint.Unconstrained) val exprTyped = checkValue(expr, Constraint.Unconstrained)
val format = exprTyped.ty match { val format = exprTyped.ty match {
case KnownType.Bool | KnownType.String => "%s" case KnownType.Bool | KnownType.String => "%s"
case KnownType.Char => "%c" case KnownType.Char => "%c"
case KnownType.Int => "%d" case KnownType.Int => "%d"
case _ => "%p" case _ => "%p"
} }
List( List(
microWacc.Call( microWacc.Call(