From d8a80de37c9cd830cb5f9bebea36df1aa0ce6eea Mon Sep 17 00:00:00 2001 From: MrLetsplay Date: Sat, 23 Nov 2024 19:18:38 +0100 Subject: [PATCH] Move compileAssignmentExpressionWAT into compileAssignmentUpdateExpressionWAT --- backend_wat.go | 145 ++++++++++++++++++++----------------------------- types.go | 13 +++++ 2 files changed, 71 insertions(+), 87 deletions(-) diff --git a/backend_wat.go b/backend_wat.go index 94c0fe1..8f459e8 100644 --- a/backend_wat.go +++ b/backend_wat.go @@ -214,12 +214,9 @@ func castPrimitiveWAT(from PrimitiveType, to PrimitiveType) (Code, error) { return code, nil } -func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpression) (Code, error) { - lhs := assignment.Lhs - - exprWAT, err := c.compileExpressionWAT(assignment.Value) - if err != nil { - return emptyCode(), err +func (c *Compiler) compileAssignmentUpdateExpressionWAT(lhs Expression, update bool, valueOrUpdateWAT Code, evaluateToOldValue bool) (Code, error) { + if !isValidLHS(lhs.Type) { + panic(fmt.Sprintf("invalid LHS type passed to compileAssignmentUpdateExpressionWAT(): %s", lhs.Type)) } switch lhs.Type { @@ -227,10 +224,40 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio ref := lhs.Value.(VariableReferenceExpression) local := strconv.Itoa(getLocal(c.CurrentBlock, ref.Variable).Index) - exprWAT.add("local.tee $" + local + " (;" + ref.Variable + ";)") - return exprWAT, nil + code := emptyCode() + + // Load variable + if update || evaluateToOldValue { + exprWAT, err := c.compileExpressionWAT(lhs) + if err != nil { + return emptyCode(), err + } + + code.addAll(exprWAT) + } + + var tmpLocal Local + if update && evaluateToOldValue { + tmpLocal = Local{Name: "", Type: *lhs.ValueType, IsParameter: false, Index: len(c.CurrentFunction.Locals)} + c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, tmpLocal) + + // dup old value + code.add("local.tee $" + strconv.Itoa(tmpLocal.Index)) + code.add("local.get $" + strconv.Itoa(tmpLocal.Index)) + } + + code.addAll(valueOrUpdateWAT) + + if evaluateToOldValue { + code.add("local.set $" + local + " (;" + ref.Variable + ";)") + } else { + code.add("local.tee $" + local + " (;" + ref.Variable + ";)") + } + + return code, nil case Expression_ArrayAccess: array := lhs.Value.(ArrayAccessExpression) + elementType := array.Array.ValueType.Value.(ArrayType).ElementType localArray := Local{Name: "", Type: Type{Type: Type_Primitive, Value: c.getEffectiveAddressType(), Position: unknownPosition()}, IsParameter: false, Index: len(c.CurrentFunction.Locals)} c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, localArray) @@ -238,7 +265,7 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio localIndex := Local{Name: "", Type: Type{Type: Type_Primitive, Value: c.getEffectiveAddressType(), Position: unknownPosition()}, IsParameter: false, Index: len(c.CurrentFunction.Locals)} c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, localIndex) - localElement := Local{Name: "", Type: *assignment.Value.ValueType, IsParameter: false, Index: len(c.CurrentFunction.Locals)} + localElement := Local{Name: "", Type: elementType, IsParameter: false, Index: len(c.CurrentFunction.Locals)} c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, localElement) arrayWAT, err := c.compileExpressionWAT(array.Array) @@ -270,6 +297,7 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio // Error if index < 0 wat.add( "block", + "(;bounds check < 0;)", "local.get $"+strconv.Itoa(localIndex.Index)+" (;array index;)", c.getAddressWATType()+".const 0", c.getAddressWATType()+".ge_s", @@ -281,6 +309,7 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio // Error if index >= array length wat.add( "block", + "(;bounds check >= array length;)", "local.get $"+strconv.Itoa(localIndex.Index)+" (;array index;)", "local.get $"+strconv.Itoa(localArray.Index)+" (;array base address;)", "i32.load", // Load array length @@ -291,7 +320,6 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio ) } - elementType := array.Array.ValueType.Value.(ArrayType).ElementType wat.add( "local.get $"+strconv.Itoa(localIndex.Index)+" (;array index;)", c.getAddressWATType()+".const "+strconv.Itoa(c.getTypeSizeBytes(elementType)), @@ -302,7 +330,7 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio c.getAddressWATType()+".add", ) - wat.addAll(exprWAT) + wat.addAll(valueOrUpdateWAT) wat.add( "local.tee $"+strconv.Itoa(localElement.Index), @@ -314,63 +342,6 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio case Expression_RawMemoryReference: raw := lhs.Value.(RawMemoryReferenceExpression) - local := Local{Name: "", Type: *lhs.ValueType, IsParameter: false, Index: len(c.CurrentFunction.Locals)} - c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, local) - - if raw.Type.Type != Type_Primitive { - panic("TODO") //TODO - } - - addrWAT, err := c.compileExpressionWAT(raw.Address) - if err != nil { - return emptyCode(), err - } - - // TODO: should leave a copy of the stored value on the stack - code := addrWAT.clone() - code.addAll(exprWAT) - code.add( - "local.tee $"+strconv.Itoa(local.Index), - c.getWATType(raw.Type)+".store", - "local.get $"+strconv.Itoa(local.Index), - ) - - return code, nil - } - - panic("assignment expr not implemented") -} - -func (c *Compiler) compileAssignmentUpdateExpressionWAT(lhs Expression, updateWAT Code, evaluateToOldValue bool) (Code, 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 emptyCode(), err - } - - wat := exprWAT.clone() - if evaluateToOldValue { - wat.add("local.get $" + local + " (;" + ref.Variable + ";)") - } - - wat.addAll(updateWAT) - - if evaluateToOldValue { - wat.add("local.set $" + local + " (;" + ref.Variable + ";)") - } else { - wat.add("local.tee $" + local + " (;" + ref.Variable + ";)") - } - - 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) @@ -388,27 +359,29 @@ func (c *Compiler) compileAssignmentUpdateExpressionWAT(lhs Expression, updateWA wat := addrWAT - // dup address - wat.add( - "local.tee $"+strconv.Itoa(localAddress.Index), - "local.get $"+strconv.Itoa(localAddress.Index), - ) + if update { + // dup address + wat.add( + "local.tee $"+strconv.Itoa(localAddress.Index)+" (;address;)", + "local.get $"+strconv.Itoa(localAddress.Index)+" (;address;)", + ) - wat.add(c.getWATType(raw.Type) + ".load") - - if evaluateToOldValue { - wat.add("local.tee $" + strconv.Itoa(localValue.Index)) + wat.add(c.getWATType(raw.Type) + ".load") } - wat.addAll(updateWAT) + if evaluateToOldValue { + wat.add("local.tee $" + strconv.Itoa(localValue.Index) + " (;temp storage for value;)") + } + + wat.addAll(valueOrUpdateWAT) if !evaluateToOldValue { - wat.add("local.tee $" + strconv.Itoa(localValue.Index)) + wat.add("local.tee $" + strconv.Itoa(localValue.Index) + " (;temp storage for value;)") } wat.add( c.getWATType(raw.Type)+".store", - "local.get $"+strconv.Itoa(localValue.Index), + "local.get $"+strconv.Itoa(localValue.Index)+" (;temp storage for value;)", ) return wat, nil @@ -424,10 +397,6 @@ func (c *Compiler) compileExpressionWAT(expr Expression) (Code, error) { case Expression_Assignment: ass := expr.Value.(AssignmentExpression) - if ass.Operation == Operation_Nop { - return c.compileAssignmentExpressionWAT(ass) - } - watRight, err := c.compileExpressionWAT(ass.Value) if err != nil { return emptyCode(), err @@ -436,7 +405,7 @@ func (c *Compiler) compileExpressionWAT(expr Expression) (Code, error) { updateOp := c.compileOperationWAT(ass.Operation, ass.Lhs.ValueType.Value.(PrimitiveType)) watRight.addAll(updateOp) - return c.compileAssignmentUpdateExpressionWAT(ass.Lhs, watRight, false) + return c.compileAssignmentUpdateExpressionWAT(ass.Lhs, ass.Operation != Operation_Nop, watRight, false) case Expression_Literal: lit := expr.Value.(LiteralExpression) switch lit.Literal.Type { @@ -600,7 +569,7 @@ func (c *Compiler) compileExpressionWAT(expr Expression) (Code, error) { updateWAT.add(valueType + ".sub") } - return c.compileAssignmentUpdateExpressionWAT(unary.Value, updateWAT, unary.Operation == UnaryOperation_PostIncrement || unary.Operation == UnaryOperation_PostDecrement) + return c.compileAssignmentUpdateExpressionWAT(unary.Value, true, updateWAT, unary.Operation == UnaryOperation_PostIncrement || unary.Operation == UnaryOperation_PostDecrement) } case Expression_Cast: cast := expr.Value.(CastExpression) @@ -721,6 +690,8 @@ func (c *Compiler) compileOperationWAT(operation Operation, operandType Primitiv } switch operation { + case Operation_Nop: + return emptyCode() case Operation_Add: op = getPrimitiveWATType(operandType) + ".add" case Operation_Sub: @@ -768,7 +739,7 @@ func (c *Compiler) compileStatementWAT(stmt Statement, block *Block) (Code, erro } } - for _ = range numItems { + for range numItems { wat.add("drop") } diff --git a/types.go b/types.go index 9205c09..0507d61 100644 --- a/types.go +++ b/types.go @@ -128,6 +128,10 @@ func (t PrimitiveType) String() string { return getPrimitiveTypeName(t) } +func (t ExpressionType) String() string { + return strconv.Itoa(int(t)) +} + func getOperation(operator Operator) Operation { switch operator { case Operator_Greater: @@ -186,3 +190,12 @@ func isBooleanOperation(operation Operation) bool { func isArithmeticOperation(operation Operation) bool { return !isBooleanOperation(operation) } + +func isValidLHS(expressionType ExpressionType) bool { + switch expressionType { + case Expression_ArrayAccess, Expression_VariableReference, Expression_RawMemoryReference: + return true + default: + return false + } +}