fix(codegen): WriteLn(Double/Single) crashed QBE with type mismatch
EmitWrite had no tyDouble/tySingle case; floats fell through to _SysWriteInt with a d-typed temp, which QBE rejected as an invalid argument type. Add _SysWriteDouble and _SysWriteSingle RTL stubs in rtl.platform.pas and rtl.platform.posix.pas (using the existing _DoubleToStr/_SingleToStr functions from blaise_float.pas). EmitWrite now dispatches to these stubs so WriteLn(someDouble) and WriteLn(someSingle) compile and run correctly without requiring DoubleToStr at the call site. Two new e2e tests (TestRun_WriteLn_Double_Direct, TestRun_WriteLn_Single_Direct) verify direct float output; 2375 tests pass.
This commit is contained in:
parent
613f326fa1
commit
f4baabb9ce
|
|
@ -6711,6 +6711,12 @@ begin
|
|||
ArgTemp := EmitExpr(ArgExpr);
|
||||
if IsString then
|
||||
EmitLine(Format(' call $_SysWriteStr(w %s, l %s)', [FdLit, ArgTemp]))
|
||||
else if (ArgExpr.ResolvedType <> nil) and
|
||||
(ArgExpr.ResolvedType.Kind = tyDouble) then
|
||||
EmitLine(Format(' call $_SysWriteDouble(w %s, d %s)', [FdLit, ArgTemp]))
|
||||
else if (ArgExpr.ResolvedType <> nil) and
|
||||
(ArgExpr.ResolvedType.Kind = tySingle) then
|
||||
EmitLine(Format(' call $_SysWriteSingle(w %s, s %s)', [FdLit, ArgTemp]))
|
||||
else if (ArgExpr.ResolvedType <> nil) and
|
||||
(ArgExpr.ResolvedType.Kind = tyUInt64) then
|
||||
EmitLine(Format(' call $_SysWriteUInt64(w %s, l %s)', [FdLit, ArgTemp]))
|
||||
|
|
|
|||
|
|
@ -148,6 +148,10 @@ type
|
|||
{ Real division `/` with Integer operands yields a float }
|
||||
procedure TestRun_RealDiv_IntegerOperands_RoundTrunc;
|
||||
procedure TestRun_RealDiv_TenOverFour_Half;
|
||||
|
||||
{ WriteLn(Double) / WriteLn(Single) — direct float output without DoubleToStr }
|
||||
procedure TestRun_WriteLn_Double_Direct;
|
||||
procedure TestRun_WriteLn_Single_Direct;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
|
@ -1441,6 +1445,44 @@ begin
|
|||
AssertEquals('10/4', '2.5', Trim(Output));
|
||||
end;
|
||||
|
||||
{ ------------------------------------------------------------------ }
|
||||
{ WriteLn(Double) / WriteLn(Single) direct float output }
|
||||
{ ------------------------------------------------------------------ }
|
||||
|
||||
procedure TE2EMathTests.TestRun_WriteLn_Double_Direct;
|
||||
var Output: string; RCode: Integer;
|
||||
begin
|
||||
if not ToolchainAvailable then begin Ignore('toolchain unavailable'); Exit; end;
|
||||
AssertTrue('compile+run', CompileAndRun(
|
||||
'''
|
||||
program P;
|
||||
var D: Double;
|
||||
begin
|
||||
D := 3.14;
|
||||
WriteLn(D)
|
||||
end.
|
||||
''', Output, RCode));
|
||||
AssertEquals('exit code', 0, RCode);
|
||||
AssertEquals('WriteLn(Double)', '3.14', Trim(Output));
|
||||
end;
|
||||
|
||||
procedure TE2EMathTests.TestRun_WriteLn_Single_Direct;
|
||||
var Output: string; RCode: Integer;
|
||||
begin
|
||||
if not ToolchainAvailable then begin Ignore('toolchain unavailable'); Exit; end;
|
||||
AssertTrue('compile+run', CompileAndRun(
|
||||
'''
|
||||
program P;
|
||||
var S: Single;
|
||||
begin
|
||||
S := 1.5;
|
||||
WriteLn(S)
|
||||
end.
|
||||
''', Output, RCode));
|
||||
AssertEquals('exit code', 0, RCode);
|
||||
AssertEquals('WriteLn(Single)', '1.5', Trim(Output));
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterTest(TE2EMathTests);
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ type
|
|||
procedure SysWriteInt(Fd: Integer; N: Integer); virtual; abstract;
|
||||
procedure SysWriteInt64(Fd: Integer; N: Int64); virtual; abstract;
|
||||
procedure SysWriteUInt64(Fd: Integer; N: UInt64); virtual; abstract;
|
||||
procedure SysWriteDouble(Fd: Integer; V: Double); virtual; abstract;
|
||||
procedure SysWriteSingle(Fd: Integer; V: Single); virtual; abstract;
|
||||
procedure SysWriteNewline(Fd: Integer); virtual; abstract;
|
||||
|
||||
{ File-descriptor primitives — used by streams }
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ type
|
|||
procedure SysWriteInt(Fd: Integer; N: Integer); override;
|
||||
procedure SysWriteInt64(Fd: Integer; N: Int64); override;
|
||||
procedure SysWriteUInt64(Fd: Integer; N: UInt64); override;
|
||||
procedure SysWriteDouble(Fd: Integer; V: Double); override;
|
||||
procedure SysWriteSingle(Fd: Integer; V: Single); override;
|
||||
procedure SysWriteNewline(Fd: Integer); override;
|
||||
|
||||
{ File-descriptor primitives }
|
||||
|
|
@ -157,6 +159,8 @@ procedure _BlaiseFreeMem(Ptr: Pointer); external name '_BlaiseFreeMem';
|
|||
function _IntToStr(N: Integer): Pointer; external name '_IntToStr';
|
||||
function _Int64ToStr(N: Int64): Pointer; external name '_Int64ToStr';
|
||||
function _UInt64ToStr(N: UInt64): Pointer; external name '_UInt64ToStr';
|
||||
function _DoubleToStr(V: Double): Pointer; external name '_DoubleToStr';
|
||||
function _SingleToStr(V: Single): Pointer; external name '_SingleToStr';
|
||||
procedure _StringAddRef(Ptr: Pointer); external name '_StringAddRef';
|
||||
procedure _StringRelease(Ptr: Pointer); external name '_StringRelease';
|
||||
|
||||
|
|
@ -237,6 +241,8 @@ procedure _SysWriteStr(Fd: Integer; S: Pointer);
|
|||
procedure _SysWriteInt(Fd: Integer; N: Integer);
|
||||
procedure _SysWriteInt64(Fd: Integer; N: Int64);
|
||||
procedure _SysWriteUInt64(Fd: Integer; N: UInt64);
|
||||
procedure _SysWriteDouble(Fd: Integer; V: Double);
|
||||
procedure _SysWriteSingle(Fd: Integer; V: Single);
|
||||
procedure _SysWriteNewline(Fd: Integer);
|
||||
|
||||
{ File-descriptor primitives }
|
||||
|
|
@ -768,6 +774,34 @@ begin
|
|||
_StringRelease(S);
|
||||
end;
|
||||
|
||||
procedure TRtlPlatformPosix.SysWriteDouble(Fd: Integer; V: Double);
|
||||
var
|
||||
S: Pointer;
|
||||
LPtr: ^Integer;
|
||||
Len: Integer;
|
||||
begin
|
||||
S := _DoubleToStr(V);
|
||||
_StringAddRef(S);
|
||||
LPtr := S - 8;
|
||||
Len := LPtr^;
|
||||
WriteAllToFd(Fd, PChar(S), Len);
|
||||
_StringRelease(S);
|
||||
end;
|
||||
|
||||
procedure TRtlPlatformPosix.SysWriteSingle(Fd: Integer; V: Single);
|
||||
var
|
||||
S: Pointer;
|
||||
LPtr: ^Integer;
|
||||
Len: Integer;
|
||||
begin
|
||||
S := _SingleToStr(V);
|
||||
_StringAddRef(S);
|
||||
LPtr := S - 8;
|
||||
Len := LPtr^;
|
||||
WriteAllToFd(Fd, PChar(S), Len);
|
||||
_StringRelease(S);
|
||||
end;
|
||||
|
||||
{ ================================================================== }
|
||||
{ TRtlPlatformPosix — File-descriptor primitives }
|
||||
{ ================================================================== }
|
||||
|
|
@ -1233,6 +1267,16 @@ begin
|
|||
GRtlPlatform.SysWriteUInt64(Fd, N);
|
||||
end;
|
||||
|
||||
procedure _SysWriteDouble(Fd: Integer; V: Double);
|
||||
begin
|
||||
GRtlPlatform.SysWriteDouble(Fd, V);
|
||||
end;
|
||||
|
||||
procedure _SysWriteSingle(Fd: Integer; V: Single);
|
||||
begin
|
||||
GRtlPlatform.SysWriteSingle(Fd, V);
|
||||
end;
|
||||
|
||||
procedure _SysWriteNewline(Fd: Integer);
|
||||
begin
|
||||
GRtlPlatform.SysWriteNewline(Fd);
|
||||
|
|
|
|||
Loading…
Reference in a new issue