Bug #12

Compiler does not correctly compile System.String.Substring(I4) method

Added by Phil Garcia over 1 year ago. Updated over 1 year ago.

Status:Closed Start date:07/26/2010
Priority:High Due date:
Assignee:Simon Wollwage % Done:

0%

Category:Compiler Spent time: -
Target version:0.9

Description

The problem with System.String.SubString(I4) is the compiler does not compile this line correctly:

if (startIndex < 0 || startIndex > this.length)

For now, this is worked around it by splitting the if statement into two separate statements.

History

Updated by Simon Wollwage over 1 year ago

  • Assignee set to Simon Wollwage

I'll take a closer look tomorrow.

Updated by Simon Wollwage over 1 year ago

The combined statement's IL code as a start:

IL_0012:  ldarg.1
IL_0013:  ldc.i4.0
IL_0014:  blt        IL_0025
IL_0019:  ldarg.1
IL_001a:  ldarg.0
IL_001b:  ldfld      int32 System.String::length
IL_0020:  ble        IL_002b
IL_0025:  ldsfld     string System.String::Empty
IL_002a:  ret

Can't find any direct error. The first part, startIndex < 0, is translated into:

L_000C: X86.Mov EDX [I] <- startIndex
L_000C: X86.Mov T_7 <- EDX [I4]
L_000D: X86.Mov T_8 <- const 0 [Type: I4]
L_000E: X86.Nop
L_000E: X86.Mov EDX [I4] <- T_8
L_000E: X86.Cmp T_7 <- EDX [I4]
L_000E: X86.Setcc [less] EAX [U1]
L_000E: X86.Movzx ECX [I4] <- EAX [U1]
L_000E: X86.Mov T_39 <- ECX [I4]
L_000E: X86.Branch [greater or equal] T_39 L_0013
L_001F: X86.Mov EDX [I] <- [Type=String, Member=System.String.Empty]
L_001F: X86.Mov T_12 <- EDX [String]
L_0024: X86.Nop
L_0024: X86.Mov EAX [String] <- T_12
L_0024: X86.Jmp L_7FFFFFFF

The second part, startIndex > this.length, into:

L_0013: X86.Mov EDX [I] <- startIndex
L_0013: X86.Mov T_9 <- EDX [I4]
L_0014: X86.Mov EDX [I] <- this
L_0014: X86.Mov T_10 <- EDX [Class]
L_0015: X86.Mov EAX [Class] <- T_10
L_0015: X86.Mov EDX [Class] <- [EAX+8h] [Class]
L_0015: X86.Mov T_11 <- EDX [Class]
L_001A: X86.Nop
L_001A: X86.Mov EDX [I4] <- T_11
L_001A: X86.Cmp T_9 <- EDX [I4]
L_001A: X86.Setcc [less or equal] EAX [U1]
L_001A: X86.Movzx ECX [I4] <- EAX [U1]
L_001A: X86.Mov T_40 <- ECX [I4]
L_001A: X86.Branch [less or equal (U)] T_40 L_001F

Below is the code if we split the statement into 2 single ifs:

L_000C: X86.Mov EDX [I] <- startIndex
L_000C: X86.Mov T_7 <- EDX [I4]
L_000D: X86.Mov T_8 <- const 0 [Type: I4]
L_000E: X86.Nop
L_000E: X86.Mov EDX [I4] <- T_8
L_000E: X86.Cmp T_7 <- EDX [I4]
L_000E: X86.Setcc [greater or equal] EAX [U1]
L_000E: X86.Movzx ECX [I4] <- EAX [U1]
L_000E: X86.Mov T_40 <- ECX [I4]
L_000E: X86.Branch [greater or equal] T_40 L_0019
L_0013: X86.Mov EDX [I] <- [Type=String, Member=System.String.Empty]
L_0013: X86.Mov T_9 <- EDX [String]
L_0018: X86.Nop
L_0018: X86.Mov EAX [String] <- T_9
L_0018: X86.Jmp L_7FFFFFFF
L_0019: X86.Mov EDX [I] <- startIndex
L_0019: X86.Mov T_10 <- EDX [I4]
L_001A: X86.Mov EDX [I] <- this
L_001A: X86.Mov T_11 <- EDX [Class]
L_001B: X86.Mov EAX [Class] <- T_11
L_001B: X86.Mov EDX [Class] <- [EAX+8h] [Class]
L_001B: X86.Mov T_12 <- EDX [Class]
L_0020: X86.Nop
L_0020: X86.Mov EDX [I4] <- T_12
L_0020: X86.Cmp T_10 <- EDX [I4]
L_0020: X86.Setcc [less or equal] EAX [U1]
L_0020: X86.Movzx ECX [I4] <- EAX [U1]
L_0020: X86.Mov T_41 <- ECX [I4]
L_0020: X86.Branch [less or equal] T_41 L_002B
L_0025: X86.Mov EDX [I] <- [Type=String, Member=System.String.Empty]
L_0025: X86.Mov T_13 <- EDX [String]
L_002A: X86.Nop
L_002A: X86.Mov EAX [String] <- T_13
L_002A: X86.Jmp L_7FFFFFFF

Updated by Simon Wollwage over 1 year ago

  • Status changed from New to Resolved

SimplePeepholeOptimizationStage.ImproveBranchAndJump seemed to be the problem.

- First fix by disabling ImproveBranchAndJump
- Restored 'full' if-statement and tested it

Updated by Simon Wollwage over 1 year ago

  • Status changed from Resolved to Closed

Also available in: Atom PDF