вторник, марта 11, 2014

Delphi. Ненависть. Продолжение истории.

В попытках найти решение проблемы с говнокодогенератором Delphi, я понял, что все хуже, чем я предполагал.

Оказалось, что компилятору сносит крышу не только при попытке развернуть вызовы методов вложенного класса, но и при разворачивании вызовов обычных функций, при условии, что типы параметров являются управляемыми. Я значительно упростил код демонстрирующий проблему:

program inline_bug;

{$APPTYPE CONSOLE}

{$OPTIMIZATION ON}
{$INLINE ON}

{$R *.res}

Type

TManagedType = Array Of Byte; // checked with: String, IInterface, TBytes and record with field of one of these types;

//
Function Func(Const ALeft, ARight : TManagedType) : Boolean;
Begin

Result := True;

End;
//

//
Function CompareVars(Const ALeft, ARight : TManagedType) : Boolean; Inline;
Begin
End;
//

//
Function CompareVarsAlt(Const ALeft, ARight : TManagedType) : Boolean; Inline;
Begin

Result := Func(ALeft, ARight);

End;
//

//
Function SameVars(Const ALeft, ARight : TManagedType; AAlternativeWay : Boolean = True) : Boolean; Inline;
begin

If AAlternativeWay Then
Result := CompareVarsAlt(ALeft, ARight)
Else
Result := CompareVars(ALeft, ARight);

End;
//

Var

v1, v2 : TManagedType;

begin

CompareVarsAlt(v1, v2);
SameVars(v1, v2);
v1 := Default(TManagedType);

end.


Можете экспериментировать меняя декларацию псевдонима TManagedType. Я проверил все управляемые типы Delphi: String, Interface, Dynamic array, Variant. Проблема воспроизводится на всех типах, кроме варианта. Также проблема воспроизводится на типе Record с полем управляемого типа. Для примера приведу код генерируемый для параметров типа Dynamic array:



---------------------------------------------- Delphi XE Update 1 (15.0.3953.35171)
inline_bug.dpr.56: CompareVarsAlt(v1, v2);
004050D2 8B15789B4000 mov edx,[$00409b78]
004050D8 A1749B4000 mov eax,[$00409b74]
004050DD E84EF2FFFF call Func
inline_bug.dpr.57: SameVars(v1, v2);
004050E2 8B15789B4000 mov edx,[$00409b78]
004050E8 A1749B4000 mov eax,[$00409b74]
004050ED E83EF2FFFF call Func
inline_bug.dpr.58: v1 := Default(TManagedType);
004050F2 B8749B4000 mov eax,$00409b74
004050F7 8B15FC424000 mov edx,[$004042fc]
004050FD E8E2E9FFFF call @DynArrayClear
---------------------------------------------- Delphi XE5 Update 2 (19.0.14356.6604)
inline_bug.dpr.56: CompareVarsAlt(v1, v2);
004050F0 8D45EC lea eax,[ebp-$14]
004050F3 8B159C9B4000 mov edx,[$00409b9c]
004050F9 8B0D74444000 mov ecx,[$00404474]
004050FF E898E9FFFF call @DynArrayAsg
00405104 8D45E8 lea eax,[ebp-$18]
00405107 8B15A09B4000 mov edx,[$00409ba0]
0040510D 8B0D74444000 mov ecx,[$00404474]
00405113 E884E9FFFF call @DynArrayAsg
00405118 33C0 xor eax,eax
0040511A 55 push ebp
0040511B 685E514000 push $0040515e
00405120 64FF30 push dword ptr fs:[eax]
00405123 648920 mov fs:[eax],esp
00405126 8B55E8 mov edx,[ebp-$18]
00405129 8B45EC mov eax,[ebp-$14]
0040512C E877F3FFFF call Func
00405131 8845DF mov [ebp-$21],al
00405134 33C0 xor eax,eax
00405136 5A pop edx
00405137 59 pop ecx
00405138 59 pop ecx
00405139 648910 mov fs:[eax],edx
0040513C 6865514000 push $00405165
00405141 8D45EC lea eax,[ebp-$14]
00405144 8B1574444000 mov edx,[$00404474]
0040514A E811E9FFFF call @DynArrayClear
0040514F 8D45E8 lea eax,[ebp-$18]
00405152 8B1574444000 mov edx,[$00404474]
00405158 E803E9FFFF call @DynArrayClear
0040515D C3 ret
0040515E E9EDDFFFFF jmp @HandleFinally
00405163 EBDC jmp $00405141
inline_bug.dpr.57: SameVars(v1, v2);
00405165 8D45E4 lea eax,[ebp-$1c]
00405168 8B1574444000 mov edx,[$00404474]
0040516E E8EDE8FFFF call @DynArrayClear
00405173 8D45E0 lea eax,[ebp-$20]
00405176 8B1574444000 mov edx,[$00404474]
0040517C E8DFE8FFFF call @DynArrayClear
00405181 33C0 xor eax,eax
00405183 55 push ebp
00405184 6835524000 push $00405235
00405189 64FF30 push dword ptr fs:[eax]
0040518C 648920 mov fs:[eax],esp
0040518F 8D45E4 lea eax,[ebp-$1c]
00405192 8B159C9B4000 mov edx,[$00409b9c]
00405198 8B0D74444000 mov ecx,[$00404474]
0040519E E8F9E8FFFF call @DynArrayAsg
004051A3 8D45E0 lea eax,[ebp-$20]
004051A6 8B15A09B4000 mov edx,[$00409ba0]
004051AC 8B0D74444000 mov ecx,[$00404474]
004051B2 E8E5E8FFFF call @DynArrayAsg
004051B7 33C0 xor eax,eax
004051B9 55 push ebp
004051BA 68FD514000 push $004051fd
004051BF 64FF30 push dword ptr fs:[eax]
004051C2 648920 mov fs:[eax],esp
004051C5 8B55E0 mov edx,[ebp-$20]
004051C8 8B45E4 mov eax,[ebp-$1c]
004051CB E8D8F2FFFF call Func
004051D0 8845DD mov [ebp-$23],al
004051D3 33C0 xor eax,eax
004051D5 5A pop edx
004051D6 59 pop ecx
004051D7 59 pop ecx
004051D8 648910 mov fs:[eax],edx
004051DB 6804524000 push $00405204
004051E0 8D45E4 lea eax,[ebp-$1c]
004051E3 8B1574444000 mov edx,[$00404474]
004051E9 E872E8FFFF call @DynArrayClear
004051EE 8D45E0 lea eax,[ebp-$20]
004051F1 8B1574444000 mov edx,[$00404474]
004051F7 E864E8FFFF call @DynArrayClear
004051FC C3 ret
004051FD E94EDFFFFF jmp @HandleFinally
00405202 EBDC jmp $004051e0
00405204 0FB645DD movzx eax,[ebp-$23]
00405208 8845DE mov [ebp-$22],al
0040520B 33C0 xor eax,eax
0040520D 5A pop edx
0040520E 59 pop ecx
0040520F 59 pop ecx
00405210 648910 mov fs:[eax],edx
00405213 683C524000 push $0040523c
00405218 8D45E4 lea eax,[ebp-$1c]
0040521B 8B1574444000 mov edx,[$00404474]
00405221 E83AE8FFFF call @DynArrayClear
00405226 8D45E0 lea eax,[ebp-$20]
00405229 8B1574444000 mov edx,[$00404474]
0040522F E82CE8FFFF call @DynArrayClear
00405234 C3 ret
00405235 E916DFFFFF jmp @HandleFinally
0040523A EBDC jmp $00405218
inline_bug.dpr.58: v1 := Default(TManagedType);
0040523C B89C9B4000 mov eax,$00409b9c
00405241 8B1574444000 mov edx,[$00404474]
00405247 E814E8FFFF call @DynArrayClear


Напомню, за лечение бага вы можете проголосовать в QC#121566

Комментариев нет: