Bug #12
Compiler does not correctly compile System.String.Substring(I4) method
| Status: | Closed | Start date: | 07/26/2010 | |
|---|---|---|---|---|
| Priority: | High | Due date: | ||
| Assignee: | % 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