diff --git a/DMCompiler/DM/Builders/DMASTFolder.cs b/DMCompiler/DM/Builders/DMASTFolder.cs index 89f01fd584..0bbe08b1ea 100644 --- a/DMCompiler/DM/Builders/DMASTFolder.cs +++ b/DMCompiler/DM/Builders/DMASTFolder.cs @@ -219,13 +219,6 @@ private DMASTExpression FoldExpression(DMASTExpression? expression) { break; } - case DMASTAdd add: { - DMASTConstantString? lhsString = add.LHS as DMASTConstantString; - DMASTConstantString? rhsString = add.RHS as DMASTConstantString; - if (lhsString != null && rhsString != null) return new DMASTConstantString(expression.Location, lhsString.Value + rhsString.Value); - - break; - } #endregion Math diff --git a/DMCompiler/Optimizer/AnnotatedBytecode.cs b/DMCompiler/Optimizer/AnnotatedBytecode.cs index 4231539f36..3bb38adb09 100644 --- a/DMCompiler/Optimizer/AnnotatedBytecode.cs +++ b/DMCompiler/Optimizer/AnnotatedBytecode.cs @@ -235,6 +235,10 @@ public void SetLocation(Location loc) { public Location GetLocation() { return Location; } + + public string ResolveString(DMCompiler compiler) { + return compiler.DMObjectTree.StringTable[Id]; + } } internal sealed class AnnotatedBytecodeArgumentType(DMCallArgumentsType value, Location location) : IAnnotatedBytecode { diff --git a/DMCompiler/Optimizer/PeepholeOptimizations.cs b/DMCompiler/Optimizer/PeepholeOptimizations.cs index 395e0dc38e..a80d48f9d3 100644 --- a/DMCompiler/Optimizer/PeepholeOptimizations.cs +++ b/DMCompiler/Optimizer/PeepholeOptimizations.cs @@ -767,6 +767,33 @@ public void Apply(DMCompiler compiler, List input, int index } } +// PushString [constant] +// PushString [constant] +// Add +// -> PushString [result] +internal sealed class ConstFoldAddStrings : IPeepholeOptimization { + public ReadOnlySpan GetOpcodes() { + return [ + DreamProcOpcode.PushString, + DreamProcOpcode.PushString, + DreamProcOpcode.Add, + ]; + } + + public void Apply(DMCompiler compiler, List input, int index) { + var firstInstruction = (AnnotatedBytecodeInstruction)input[index]; + var firstString = firstInstruction.GetArg(0); + var secondString = ((AnnotatedBytecodeInstruction)input[index+1]).GetArg(0); + + var combinedId = compiler.DMObjectTree.AddString(firstString.ResolveString(compiler) + secondString.ResolveString(compiler)); // TODO: Currently doesn't handle removing strings from the string tree that have no other references + + var args = new List(1) {new AnnotatedBytecodeString(combinedId, firstInstruction.Location)}; + + IPeepholeOptimization.ReplaceInstructions(input, index, 3, + new AnnotatedBytecodeInstruction(DreamProcOpcode.PushString, 1, args)); + } +} + // PushFloat [constant] // PushFloat [constant] // Subtract