Search the Community
Showing results for tags 'compiler'.
Found 5 results
-
Are there any (known) changes to the compiler regarding string handling from Delphi 10.2 (or 11.0)to 11.2? I don't have code, because I can't reproduce it yet, it's more of a feeling, that something is wrong. We do a lot of serial communication. Parts of the code are rather old, but survived man Delphi version changes. Some of the code may be pre-Unicode but got modernized before my time and thus before source control, so I can't check the history. We read the ansichars that come via the serial connection and put them into chars and them into strings and work from there. I think that's not ideal because strings are unicode (nowadays) but so far it worked fine. Recently we switched from Delphi 10.2 to 11.2 (with a short stint in 11.0, but I'm only 80% sure the error wasn't there). And now it only works like 99.9% of the time. (With our test systems everything works, but our customers have more "traffic). The error is, that we get symbols we can't explain in positions where they don't belong. It looks like chars get converted to other hex values. At the moment I'm just poking around, because the error is rare enough and we don't have a trace yet. But perhaps someone knows of a possible change to string/char handling with the most recent compiler versions.
-
Rethinking Delphi’s management of floating point control registers
David Heffernan posted a topic in RTL and Delphi Object Pascal
Rethinking Delphi Floating Point Control Register Management.pdf -
Discussion started with: This is valid point, I must concede. We need to have an option to reference count just for explicitly designated object types and variables. And a first-class one, without need to build an interface wrapper. Which means not some crappy wrappers like shared_ptr, no, lets introduce compiler magic and (non-breaking) language changes. like FObject: auto TObject; // compiler, just manage the lifetime automacally type TMyRefObject = class auto (TObject) // all instances are automatic var manualRef := unsafe(RefCountedObject); // Compiler, I understand the risk, just give me raw pointer var autoInline := auto TObject.Create;// compiler, manage it automatically
- 52 replies
-
- arc
- memory management
-
(and 3 more)
Tagged with:
-
Dear all, I'm being stupid and I can't figure why in the following code the `TTestObj` is destroyed before its owner. Can you please help? Full code is available here and is also posted at the end of this post. Basically, I have an interface `IWorkItem` which owns record `TOmniValue` which owns interface `IAutoDestroyObject`. The code creates an instance of `IWorkItem` and then calls: procedure Test(const workItem: IWorkItem); begin workItem.Result.AsOwnedObject := TTestObj.Create; end; This sets the `IAutoDestroyObject` field of the nested `TOmniValue` record. When the `Test` function exits (during the procedure finalization code) this `TTestObj` gets destroyed, and I can't figure out why. program ObjectDestroyedTooSoon; {$APPTYPE CONSOLE} {$R *.res} uses Winapi.Windows, System.SysUtils; type TTestObj = class public destructor Destroy; override; end; IAutoDestroyObject = interface ['{30CF4CCF-9383-41C0-BBA3-E24F7C4EFF71}'] function GetObj: TObject; property Obj: TObject read GetObj; end; TAutoDestroyObject = class(TInterfacedObject, IAutoDestroyObject) strict private FObject: TObject; protected function GetObj: TObject; public constructor Create(obj: TObject); destructor Destroy; override; property Obj: TObject read GetObj; end; TOmniValue = record private FOwnedObject: IAutoDestroyObject; function GetAsOwnedObject: TObject; procedure SetAsOwnedObject(const Value: TObject); public property AsOwnedObject: TObject read GetAsOwnedObject write SetAsOwnedObject; end; IWorkItem = interface ['{7C583FC8-90DD-46A5-81B9-81B911AA1CBE}'] function GetResult: TOmniValue; procedure SetResult(const Value: TOmniValue); property Result: TOmniValue read GetResult write SetResult; end; TWorkItem = class(TInterfacedObject, IWorkItem) strict private FResult: TOmniValue; strict protected function GetResult: TOmniValue; procedure SetResult(const Value: TOmniValue); public destructor Destroy; override; property Result: TOmniValue read GetResult write SetResult; end; { TTestObj } destructor TTestObj.Destroy; begin Writeln('TTestObj destroyed'); inherited; end; { TWorkItem } destructor TWorkItem.Destroy; begin Writeln('TWorkItem destroyed'); inherited; end; function TWorkItem.GetResult: TOmniValue; begin Result := FResult; end; procedure TWorkItem.SetResult(const Value: TOmniValue); begin FResult := Value; end; { TOmniValue } function TOmniValue.GetAsOwnedObject: TObject; begin Result := FOwnedObject.Obj; end; procedure TOmniValue.SetAsOwnedObject(const Value: TObject); begin FOwnedObject := TAutoDestroyObject.Create(Value); end; { TAutoDestroyObject } constructor TAutoDestroyObject.Create(obj: TObject); begin inherited Create; FObject := obj; end; destructor TAutoDestroyObject.Destroy; begin FreeAndNil(FObject); inherited; end; function TAutoDestroyObject.GetObj: TObject; begin Result := FObject; end; { main } procedure Test(const workItem: IWorkItem); begin workItem.Result.AsOwnedObject := TTestObj.Create; end; var workItem: IWorkItem; begin try workItem := TWorkItem.Create; Test(workItem); Writeln('After Test'); workItem := nil; Writeln('workItem destroyed'); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
-
JMP to expernal methods <> inlined call to external method, bug or correct design?
Johan Bontes posted a topic in RTL and Delphi Object Pascal
I have the following code (Delphi Berlin): interface type TSliver = record public private case integer of 8: (Data8: int64); end; TSlice = record private FData: array [0..63] of byte; end; TSliverHelper = record helper for TSliver class function NS(const North, South: TSlice; out Changed: TSliverChanges): TSliver; static; inline; end; {$L 'C:\mydir\AVXGenerate.o'} //imported assembly generated by lazarus. procedure AVXGENERATE_TSLIVERHELPER_NS; external name 'AVXGENERATE_$$_TSLIVERHELPER_NS'; //no parameters for simplicity. implementation class function TSliverHelper.NS(const North, South: TSlice; out Changed: TSliverChanges): TSliver; {inline;} //RCX =North: PSlice //RDX =South: PSlice //R8 = Changed: PSliverChanges ((scUnchanged=0, scChanged=1, scInvalid=3)); //RAX = Result: TSliver (as Int64) begin AVXGENERATE_TSLIVERHELPER_NS; end; //asm // jmp AVXGENERATE_TSLIVERHELPER_NS; //end; The asm method works correctly, the inlined method does not. If we look at the generated code it's easy to see why this happens. a:= TSliver.NSTest(N,S,statusA); //a = -1 UnitTests.pas.877: b:= TSliver.NS(N,S, statusB); 00000000009A77CE 488D8C2480000000 lea rcx,[rsp+$0080] 00000000009A77D6 488D542440 lea rdx,[rsp+$40] 00000000009A77DB 4C8D44242E lea r8,[rsp+$2e] 00000000009A77E0 E82B5E0100 call TSliverHelper.NS 00000000009A77E5 4889442430 mov [rsp+$30],rax //b = 7 why? //Let's see what's happening in the inlined method. class function TSliverHelper.NS(const [ref] N,S: TBigRec; out status: TEnumRec): UInt64_Rec; Unit2.pas.4360: begin 00000000009BD610 55 push rbp 00000000009BD611 4883EC30 sub rsp,$30 00000000009BD615 488BEC mov rbp,rsp Unit2.pas.4361: AVXGENERATE_TSLIVERHELPER_NS; 00000000009BD618 E833350000 call AVXGENERATE_TSLIVERHELPER_NS //external asm procedure with no declared params. Unit2.pas.4362: end; //At this point RAX = result = -1, all OK 00000000009BD61D 488B4528 mov rax,[rbp+$28] //Oops, RAX gets overwritten, why? <<<<??????????????????????? 00000000009BD621 488D6530 lea rsp,[rbp+$30] 00000000009BD625 5D pop rbp 00000000009BD626 C3 ret Why does the compiler insert an assignment to RAX? I have not instructed it to do anything of the sort. Compiling this code also does not issue a warning that Result might be unassigned. Why does the compiler do this? (I know I can fix this by declaring the external proc as a function, but that's beside the point). EDIT When we redefine the external proc as a function and change the inline method as shown below, correct code gets generated. It also gives some insight what is going on: Unit2.pas.4360: begin 00000000009BD610 55 push rbp 00000000009BD611 4883EC30 sub rsp,$30 00000000009BD615 488BEC mov rbp,rsp Unit2.pas.4361: Result:= AVXGENERATE_TSLIVERHELPER_NS; 00000000009BD618 E833350000 call AVXGENERATE_TSLIVERHELPER_NS 00000000009BD61D 48894528 mov [rbp+$28],rax //pointless stack trashing Unit2.pas.4362: end; 00000000009BD621 488B4528 mov rax,[rbp+$28] //the exit code expects Result to be in the stackframe. 00000000009BD625 488D6530 lea rsp,[rbp+$30] 00000000009BD629 5D pop rbp 00000000009BD62A C3 ret The compiler is just copy pasting its exit code, regardless of the actual code in the body. Note that I've compiled the code with no stackframes