feat: almost implemented arrays
This commit is contained in:
parent
18534a64a6
commit
52ed404a73
@ -148,9 +148,22 @@ object asmGenerator {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
chain ++= wrapBuiltinFunc(
|
||||||
|
labelGenerator.getLabel(Builtin.PrintCharArray),
|
||||||
|
Chain(
|
||||||
|
stack.align(),
|
||||||
|
Load(RDX, IndexAddress(RSI, 8)),
|
||||||
|
Move(RSI, MemLocation(RSI)),
|
||||||
|
assemblyIR.Call(CLibFunc.PrintF),
|
||||||
|
Xor(RDI, RDI),
|
||||||
|
assemblyIR.Call(CLibFunc.Fflush)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
chain ++= wrapBuiltinFunc(
|
chain ++= wrapBuiltinFunc(
|
||||||
labelGenerator.getLabel(Builtin.Malloc),
|
labelGenerator.getLabel(Builtin.Malloc),
|
||||||
Chain.one(stack.align())
|
Chain(stack.align(), assemblyIR.Call(CLibFunc.Malloc))
|
||||||
|
// Out of memory check is optional
|
||||||
)
|
)
|
||||||
|
|
||||||
chain ++= wrapBuiltinFunc(labelGenerator.getLabel(Builtin.Free), Chain.empty)
|
chain ++= wrapBuiltinFunc(labelGenerator.getLabel(Builtin.Free), Chain.empty)
|
||||||
@ -211,19 +224,25 @@ object asmGenerator {
|
|||||||
var chain = Chain.empty[AsmLine]
|
var chain = Chain.empty[AsmLine]
|
||||||
stmt match {
|
stmt match {
|
||||||
case Assign(lhs, rhs) =>
|
case Assign(lhs, rhs) =>
|
||||||
var dest: () => IndexAddress = () => IndexAddress(RAX, 0) // overwritten below
|
|
||||||
|
|
||||||
lhs match {
|
lhs match {
|
||||||
case ident: Ident =>
|
case ident: Ident =>
|
||||||
dest = stack.accessVar(ident)
|
val dest = stack.accessVar(ident)
|
||||||
if (!stack.contains(ident)) chain += stack.reserve(ident)
|
if (!stack.contains(ident)) chain += stack.reserve(ident)
|
||||||
// TODO lhs = arrayElem
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
|
|
||||||
chain ++= evalExprOntoStack(rhs)
|
chain ++= evalExprOntoStack(rhs)
|
||||||
chain += stack.pop(RAX)
|
chain += stack.pop(RDX)
|
||||||
chain += Move(dest(), RAX)
|
chain += Move(dest(), RDX)
|
||||||
|
case ArrayElem(x, i) =>
|
||||||
|
chain ++= evalExprOntoStack(x)
|
||||||
|
chain ++= evalExprOntoStack(i)
|
||||||
|
chain ++= evalExprOntoStack(rhs)
|
||||||
|
chain += stack.pop(RAX)
|
||||||
|
chain += stack.pop(RCX)
|
||||||
|
chain += stack.pop(RDX)
|
||||||
|
|
||||||
|
chain += Move(IndexAddress(RDX, 8, RCX, 8), RAX)
|
||||||
|
}
|
||||||
|
|
||||||
case If(cond, thenBranch, elseBranch) =>
|
case If(cond, thenBranch, elseBranch) =>
|
||||||
val elseLabel = labelGenerator.getLabel()
|
val elseLabel = labelGenerator.getLabel()
|
||||||
@ -290,19 +309,43 @@ object asmGenerator {
|
|||||||
strings += elems.collect { case CharLiter(v) => v }.mkString
|
strings += elems.collect { case CharLiter(v) => v }.mkString
|
||||||
chain += Load(RAX, IndexAddress(RIP, LabelArg(s".L.str${strings.size - 1}")))
|
chain += Load(RAX, IndexAddress(RIP, LabelArg(s".L.str${strings.size - 1}")))
|
||||||
chain += stack.push(RAX)
|
chain += stack.push(RAX)
|
||||||
case _ => // Other array types TODO
|
case _ =>
|
||||||
|
chain ++= generateCall(
|
||||||
|
microWacc.Call(Builtin.Malloc, List(IntLiter((elems.size + 1) * 8))),
|
||||||
|
isTail = false
|
||||||
|
)
|
||||||
|
chain += stack.push(RAX)
|
||||||
|
// Store the length of the array at the start
|
||||||
|
chain += Move(MemLocation(RAX, SizeDir.DWord), ImmediateVal(elems.size))
|
||||||
|
elems.zipWithIndex.foldMap { (elem, i) =>
|
||||||
|
chain ++= evalExprOntoStack(elem)
|
||||||
|
chain += stack.pop(RCX)
|
||||||
|
chain += stack.pop(RAX)
|
||||||
|
chain += Move(IndexAddress(RAX, 8 * (i + 1)), RCX)
|
||||||
|
chain += stack.push(RAX)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case BoolLiter(true) => chain += stack.push(ImmediateVal(1))
|
case BoolLiter(true) => chain += stack.push(ImmediateVal(1))
|
||||||
case BoolLiter(false) =>
|
case BoolLiter(false) =>
|
||||||
chain += Xor(RAX, RAX)
|
chain += Xor(RAX, RAX)
|
||||||
chain += stack.push(RAX)
|
chain += stack.push(RAX)
|
||||||
case NullLiter() => chain += stack.push(ImmediateVal(0))
|
case NullLiter() => chain += stack.push(ImmediateVal(0))
|
||||||
case ArrayElem(_, _) => // TODO: Implement handling
|
case ArrayElem(x, i) =>
|
||||||
|
chain ++= evalExprOntoStack(x)
|
||||||
|
chain ++= evalExprOntoStack(i)
|
||||||
|
chain += stack.pop(RCX)
|
||||||
|
chain += stack.pop(RAX)
|
||||||
|
// + 1 because we store the length of the array at the start
|
||||||
|
chain += stack.push(IndexAddress(RAX, 8, RCX, 8))
|
||||||
case UnaryOp(x, op) =>
|
case UnaryOp(x, op) =>
|
||||||
chain ++= evalExprOntoStack(x)
|
chain ++= evalExprOntoStack(x)
|
||||||
op match {
|
op match {
|
||||||
case UnaryOperator.Chr | UnaryOperator.Ord | UnaryOperator.Len => // No op needed
|
case UnaryOperator.Chr | UnaryOperator.Ord => // No op needed
|
||||||
|
case UnaryOperator.Len =>
|
||||||
|
// Access the elem
|
||||||
|
chain += stack.pop(RAX)
|
||||||
|
chain += Push(MemLocation(RAX))
|
||||||
case UnaryOperator.Negate => chain += Negate(stack.head(SizeDir.DWord))
|
case UnaryOperator.Negate => chain += Negate(stack.head(SizeDir.DWord))
|
||||||
case UnaryOperator.Not =>
|
case UnaryOperator.Not =>
|
||||||
chain += Xor(stack.head(SizeDir.DWord), ImmediateVal(1))
|
chain += Xor(stack.head(SizeDir.DWord), ImmediateVal(1))
|
||||||
|
@ -48,7 +48,9 @@ object assemblyIR {
|
|||||||
case Scanf,
|
case Scanf,
|
||||||
Fflush,
|
Fflush,
|
||||||
Exit,
|
Exit,
|
||||||
PrintF
|
PrintF,
|
||||||
|
Malloc,
|
||||||
|
Free
|
||||||
|
|
||||||
private val plt = "@plt"
|
private val plt = "@plt"
|
||||||
|
|
||||||
@ -57,6 +59,8 @@ object assemblyIR {
|
|||||||
case Fflush => "fflush" + plt
|
case Fflush => "fflush" + plt
|
||||||
case Exit => "exit" + plt
|
case Exit => "exit" + plt
|
||||||
case PrintF => "printf" + plt
|
case PrintF => "printf" + plt
|
||||||
|
case Malloc => "malloc" + plt
|
||||||
|
case Free => "free" + plt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,13 +76,20 @@ object assemblyIR {
|
|||||||
case reg: Register => opSize.toString + s"[$reg]"
|
case reg: Register => opSize.toString + s"[$reg]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO to string is wacky
|
||||||
case class IndexAddress(
|
case class IndexAddress(
|
||||||
base: Register,
|
base: Register,
|
||||||
offset: Int | LabelArg,
|
offset: Int | LabelArg,
|
||||||
opSize: SizeDir = SizeDir.Unspecified
|
indexReg: Register = Register(RegSize.R64, RegName.AX),
|
||||||
|
scale: Int = 0
|
||||||
) extends Dest
|
) extends Dest
|
||||||
with Src {
|
with Src {
|
||||||
override def toString = s"$opSize[$base + $offset]"
|
override def toString = if (scale != 0) {
|
||||||
|
s"[$base + $indexReg * $scale + $offset]"
|
||||||
|
} else {
|
||||||
|
s"[$base + $offset]"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case class ImmediateVal(value: Int) extends Src {
|
case class ImmediateVal(value: Int) extends Src {
|
||||||
@ -185,7 +196,7 @@ object assemblyIR {
|
|||||||
|
|
||||||
override def toString(): String = this match {
|
override def toString(): String = this match {
|
||||||
case Byte => "byte " + ptr
|
case Byte => "byte " + ptr
|
||||||
case Word => "word " + ptr // TODO check word/doubleword/quadword
|
case Word => "word " + ptr
|
||||||
case DWord => "dword " + ptr
|
case DWord => "dword " + ptr
|
||||||
case Unspecified => ""
|
case Unspecified => ""
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,7 @@ object microWacc {
|
|||||||
object Exit extends Builtin("exit")(?)
|
object Exit extends Builtin("exit")(?)
|
||||||
object Free extends Builtin("free")(?)
|
object Free extends Builtin("free")(?)
|
||||||
object Malloc extends Builtin("malloc")(?)
|
object Malloc extends Builtin("malloc")(?)
|
||||||
|
object PrintCharArray extends Builtin("printCharArray")(?)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class Assign(lhs: LValue, rhs: Expr) extends Stmt
|
case class Assign(lhs: LValue, rhs: Expr) extends Stmt
|
||||||
|
@ -218,6 +218,7 @@ object typeChecker {
|
|||||||
val exprTyped = checkValue(expr, Constraint.Unconstrained)
|
val exprTyped = checkValue(expr, Constraint.Unconstrained)
|
||||||
val exprFormat = exprTyped.ty match {
|
val exprFormat = exprTyped.ty match {
|
||||||
case KnownType.Bool | KnownType.String => "%s"
|
case KnownType.Bool | KnownType.String => "%s"
|
||||||
|
case KnownType.Array(KnownType.Char) => "%.*s"
|
||||||
case KnownType.Char => "%c"
|
case KnownType.Char => "%c"
|
||||||
case KnownType.Int => "%d"
|
case KnownType.Int => "%d"
|
||||||
case KnownType.Pair(_, _) | KnownType.Array(_) | ? => "%p"
|
case KnownType.Pair(_, _) | KnownType.Array(_) | ? => "%p"
|
||||||
|
@ -73,7 +73,7 @@ class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll {
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert(process.exitValue == expectedExit)
|
assert(process.exitValue == expectedExit)
|
||||||
assert(stdout.toString == expectedOutput)
|
assert(stdout.toString.replaceAll("0x[0-9a-f]+", "#addrs#") == expectedOutput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll {
|
|||||||
// format: off
|
// format: off
|
||||||
// disable formatting to avoid binPack
|
// disable formatting to avoid binPack
|
||||||
"^.*wacc-examples/valid/advanced.*$",
|
"^.*wacc-examples/valid/advanced.*$",
|
||||||
"^.*wacc-examples/valid/array.*$",
|
// "^.*wacc-examples/valid/array.*$",
|
||||||
// "^.*wacc-examples/valid/basic/exit.*$",
|
// "^.*wacc-examples/valid/basic/exit.*$",
|
||||||
// "^.*wacc-examples/valid/basic/skip.*$",
|
// "^.*wacc-examples/valid/basic/skip.*$",
|
||||||
// "^.*wacc-examples/valid/expressions.*$",
|
// "^.*wacc-examples/valid/expressions.*$",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user