From f46d5a027456784538bbf7a483f3b764c424428d Mon Sep 17 00:00:00 2001 From: Merlin <36685500+Merlin-san@users.noreply.github.com> Date: Sat, 18 Apr 2020 21:15:00 -0700 Subject: [PATCH] Fix issues with implicit casts on increment/decrement and switch conditions - Fix issues with not correctly implicitly casting numeric types correctly in pre and post increment/decrement operators. This meant that low precision types like byte could not be incremented in place. - Fix switch conditions not performing implicit numeric casts for the correct comparision type. This will later be improved when constant folding is implemented. --- .../UdonSharp/Editor/UdonSharpASTVisitor.cs | 47 ++++++++++++++----- Assets/UdonSharp/Editor/UdonSharpUtils.cs | 5 ++ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/Assets/UdonSharp/Editor/UdonSharpASTVisitor.cs b/Assets/UdonSharp/Editor/UdonSharpASTVisitor.cs index b1dec200..374976e1 100644 --- a/Assets/UdonSharp/Editor/UdonSharpASTVisitor.cs +++ b/Assets/UdonSharp/Editor/UdonSharpASTVisitor.cs @@ -1147,7 +1147,7 @@ public override void VisitPrefixUnaryExpression(PrefixUnaryExpressionSyntax node { resultSymbol = operatorMethodCapture.Invoke(new SymbolDefinition[] { operandCapture.ExecuteGet(), valueConstant }); - operandCapture.ExecuteSet(resultSymbol); + operandCapture.ExecuteSet(resultSymbol, true); } catch (System.Exception) { @@ -1205,7 +1205,7 @@ public override void VisitPostfixUnaryExpression(PostfixUnaryExpressionSyntax no SymbolDefinition resultSymbol = operatorMethodCapture.Invoke(new SymbolDefinition[] { operandCapture.ExecuteGet(), valueConstant }); - operandCapture.ExecuteSet(resultSymbol); + operandCapture.ExecuteSet(resultSymbol, true); } } catch (System.Exception) @@ -2292,22 +2292,43 @@ public override void VisitSwitchStatement(SwitchStatementSyntax node) visitorContext.uasmBuilder.AddJumpLabel(nextLabelJump); nextLabelJump = visitorContext.labelTable.GetNewJumpLabel("nextSwitchLabelJump"); + SymbolDefinition conditionEqualitySymbol = null; + using (ExpressionCaptureScope conditionValueCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(switchLabel); - if (!conditionValueCapture.IsUnknownArchetype()) - switchLabelValue = conditionValueCapture.ExecuteGet(); - } + using (ExpressionCaptureScope equalityCheckScope = new ExpressionCaptureScope(visitorContext, null)) + { + List operatorMethods = new List(); + operatorMethods.AddRange(UdonSharpUtils.GetOperators(switchExpressionSymbol.symbolCsType, BuiltinOperatorType.Equality)); + operatorMethods.AddRange(GetImplicitHigherPrecisionOperator(switchExpressionSymbol.symbolCsType, conditionValueCapture.GetReturnType(), BuiltinOperatorType.Equality)); + + // The condition has a numeric value that needs to be converted for the condition + // This is done on the condition symbol because once constant folding is implemented, this will turn into a nop at runtime + if (visitorContext.resolverContext.FindBestOverloadFunction(operatorMethods.ToArray(), new List { switchExpressionSymbol.symbolCsType, conditionValueCapture.GetReturnType() }) == null && + UdonSharpUtils.IsNumericExplicitCastValid(conditionValueCapture.GetReturnType(), switchExpressionSymbol.symbolCsType)) + { + SymbolDefinition convertedNumericType = visitorContext.topTable.CreateUnnamedSymbol(conditionValueCapture.GetReturnType(), SymbolDeclTypeFlags.Internal); - SymbolDefinition conditionEqualitySymbol = null; - using (ExpressionCaptureScope equalityCheckScope = new ExpressionCaptureScope(visitorContext, null)) - { - List operatorMethods = new List(); - operatorMethods.AddRange(UdonSharpUtils.GetOperators(switchExpressionSymbol.symbolCsType, BuiltinOperatorType.Equality)); - operatorMethods.AddRange(GetImplicitHigherPrecisionOperator(switchExpressionSymbol.symbolCsType, switchLabelValue.symbolCsType, BuiltinOperatorType.Equality)); - equalityCheckScope.SetToMethods(operatorMethods.ToArray()); - conditionEqualitySymbol = equalityCheckScope.Invoke(new SymbolDefinition[] { switchExpressionSymbol, switchLabelValue }); + using (ExpressionCaptureScope numericConversionScope = new ExpressionCaptureScope(visitorContext, null)) + { + numericConversionScope.SetToLocalSymbol(convertedNumericType); + numericConversionScope.ExecuteSetDirect(conditionValueCapture, true); + } + + switchLabelValue = convertedNumericType; + operatorMethods.AddRange(UdonSharpUtils.GetOperators(switchLabelValue.symbolCsType, BuiltinOperatorType.Equality)); + operatorMethods.AddRange(GetImplicitHigherPrecisionOperator(switchExpressionSymbol.symbolCsType, switchLabelValue.symbolCsType, BuiltinOperatorType.Equality)); + } + else + { + switchLabelValue = conditionValueCapture.ExecuteGet(); + } + + equalityCheckScope.SetToMethods(operatorMethods.ToArray()); + conditionEqualitySymbol = equalityCheckScope.Invoke(new SymbolDefinition[] { switchExpressionSymbol, switchLabelValue }); + } } // Jump past the jump to the section if false diff --git a/Assets/UdonSharp/Editor/UdonSharpUtils.cs b/Assets/UdonSharp/Editor/UdonSharpUtils.cs index 1473b37b..b14003aa 100644 --- a/Assets/UdonSharp/Editor/UdonSharpUtils.cs +++ b/Assets/UdonSharp/Editor/UdonSharpUtils.cs @@ -154,6 +154,11 @@ public static MethodInfo GetNumericConversionMethod(System.Type targetType, Syst return foundMethods.FirstOrDefault(); } + public static bool IsNumericExplicitCastValid(System.Type targetType, System.Type sourceType) + { + return IsNumericType(sourceType) && GetNumericConversionMethod(targetType, sourceType) != null; + } + public static bool IsImplicitlyAssignableFrom(this System.Type targetType, System.Type assignee) { // Normal explicit assign