Add pre-/post-increment/decrement expressions

This commit is contained in:
MrLetsplay 2024-04-18 21:14:55 +02:00
parent e9074e1632
commit 157c0bf217
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
3 changed files with 118 additions and 4 deletions

View File

@ -91,6 +91,14 @@ func (c *Compiler) getAddressWATType() string {
} }
} }
func (c *Compiler) getEffectiveAddressType() PrimitiveType {
if c.Wasm64 {
return Primitive_U64
} else {
return Primitive_U32
}
}
func (c *Compiler) getWATType(t Type) string { func (c *Compiler) getWATType(t Type) string {
switch t.Type { switch t.Type {
case Type_Primitive: case Type_Primitive:
@ -212,6 +220,83 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio
panic("assignment expr not implemented") panic("assignment expr not implemented")
} }
func (c *Compiler) compileAssignmentUpdateExpressionWAT(lhs Expression, updateWAT string, evaluateToOldValue bool) (string, error) {
switch lhs.Type {
case Expression_VariableReference:
ref := lhs.Value.(VariableReferenceExpression)
local := strconv.Itoa(getLocal(c.CurrentBlock, ref.Variable).Index)
exprWAT, err := c.compileExpressionWAT(lhs)
if err != nil {
return "", err
}
var tmpLocal Local
wat := exprWAT
if evaluateToOldValue {
tmpLocal = Local{Name: "", Type: *lhs.ValueType, IsParameter: false, Index: len(c.CurrentFunction.Locals)}
c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, tmpLocal)
wat += "local.tee $" + strconv.Itoa(tmpLocal.Index) + "\n"
}
wat += updateWAT
if evaluateToOldValue {
wat += "local.set $" + local + "\n"
wat += "local.get $" + strconv.Itoa(tmpLocal.Index) + "\n"
} else {
wat += "local.tee $" + local + "\n"
}
return wat, nil
case Expression_ArrayAccess:
panic("TODO") // TODO
case Expression_RawMemoryReference:
raw := lhs.Value.(RawMemoryReferenceExpression)
localAddress := Local{Name: "", Type: Type{Type: Type_Primitive, Value: c.getEffectiveAddressType()}, IsParameter: false, Index: len(c.CurrentFunction.Locals)}
c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, localAddress)
localValue := Local{Name: "", Type: *lhs.ValueType, IsParameter: false, Index: len(c.CurrentFunction.Locals)}
c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, localValue)
if raw.Type.Type != Type_Primitive {
panic("TODO") //TODO
}
addrWAT, err := c.compileExpressionWAT(raw.Address)
if err != nil {
return "", err
}
wat := addrWAT
// dup address
wat += "local.tee $" + strconv.Itoa(localAddress.Index) + "\n"
wat += "local.get $" + strconv.Itoa(localAddress.Index) + "\n"
wat += c.getWATType(raw.Type) + ".load\n"
if evaluateToOldValue {
wat += "local.tee $" + strconv.Itoa(localValue.Index) + "\n"
}
wat += updateWAT
if !evaluateToOldValue {
wat += "local.tee $" + strconv.Itoa(localValue.Index) + "\n"
}
wat += c.getWATType(raw.Type) + ".store\n"
wat += "local.get $" + strconv.Itoa(localValue.Index) + "\n"
return wat, nil
}
panic("assignment expr not implemented")
}
func (c *Compiler) compileExpressionWAT(expr Expression) (string, error) { func (c *Compiler) compileExpressionWAT(expr Expression) (string, error) {
var err error var err error
@ -351,7 +436,16 @@ func (c *Compiler) compileExpressionWAT(expr Expression) (string, error) {
case UnaryOperation_LogicalNot: case UnaryOperation_LogicalNot:
return wat + "i32.eqz\n", nil return wat + "i32.eqz\n", nil
case UnaryOperation_PreIncrement, UnaryOperation_PreDecrement, UnaryOperation_PostIncrement, UnaryOperation_PostDecrement: case UnaryOperation_PreIncrement, UnaryOperation_PreDecrement, UnaryOperation_PostIncrement, UnaryOperation_PostDecrement:
// TODO: implement valueType := c.getWATType(*unary.Value.ValueType)
updateWAT := valueType + ".const 1\n"
if unary.Operation == UnaryOperation_PreIncrement || unary.Operation == UnaryOperation_PostIncrement {
updateWAT += valueType + ".add\n"
} else {
updateWAT += valueType + ".sub\n"
}
return c.compileAssignmentUpdateExpressionWAT(unary.Value, updateWAT, unary.Operation == UnaryOperation_PostIncrement || unary.Operation == UnaryOperation_PostDecrement)
} }
case Expression_Cast: case Expression_Cast:
cast := expr.Value.(CastExpression) cast := expr.Value.(CastExpression)
@ -379,7 +473,7 @@ func (c *Compiler) compileExpressionWAT(expr Expression) (string, error) {
} }
if raw.Type.Type == Type_Primitive { if raw.Type.Type == Type_Primitive {
wat += c.getWATType(raw.Type) + ".load\n" wat += c.getWATType(raw.Type) + ".load\n" // TODO: use load8/load16(_s/u) for smaller types
} }
return wat, nil return wat, nil

View File

@ -20,3 +20,16 @@ u64 fib(u64 i) {
return fibA; return fibA;
} }
(u64, u64) add(u64 a) {
u64 x = a++;
return x, a;
}
(u64, u64) tuple() {
return 1u64, 2u64;
}
u64 sub(u64 a) {
return --raw(u64, 0xFFu64);
}

11
main.go
View File

@ -151,7 +151,7 @@ func main() {
parsedFiles = append(parsedFiles, parsed) parsedFiles = append(parsedFiles, parsed)
} }
validator := Validator{Files: parsedFiles} validator := Validator{Files: parsedFiles, Wasm64: *wasm64}
errors := validator.validate() errors := validator.validate()
if len(errors) != 0 { if len(errors) != 0 {
for _, err := range errors { for _, err := range errors {
@ -188,7 +188,14 @@ func main() {
return return
} }
cmd := exec.Command("wat2wasm", "-o", *outputFile, "-") var command []string
if *wasm64 {
// TODO: wasm64 support is currently broken because x.load doesn't accept 64-bit addresses
command = append(command, "--enable-memory64")
}
command = append(command, "-o", *outputFile, "-")
cmd := exec.Command("wat2wasm", command...)
var input bytes.Buffer var input bytes.Buffer
input.Write([]byte(wat)) input.Write([]byte(wat))