mirror of https://github.com/red-prig/fpPS4.git
203 lines
3.9 KiB
Plaintext
203 lines
3.9 KiB
Plaintext
unit srBitcast;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
ginodes,
|
|
srNode,
|
|
srType,
|
|
srConst,
|
|
srReg;
|
|
|
|
type
|
|
PsrBitcastKey=^TsrBitcastKey;
|
|
TsrBitcastKey=packed record
|
|
dtype:TsrDataType;
|
|
src:TsrRegNode;
|
|
end;
|
|
|
|
TsrBitcast=class
|
|
pLeft,pRight:TsrBitcast;
|
|
//----
|
|
key:TsrBitcastKey;
|
|
dst:TsrRegNode;
|
|
class function c(n1,n2:PsrBitcastKey):Integer; static;
|
|
end;
|
|
|
|
PsrBitcastList=^TsrBitcastList;
|
|
TsrBitcastList=object
|
|
type
|
|
TNodeTree=specialize TNodeTreeClass<TsrBitcast>;
|
|
var
|
|
FTree:TNodeTree;
|
|
rSlot:TsrRegSlot;
|
|
procedure Init(Emit:TCustomEmit); inline;
|
|
function _Find(dtype:TsrDataType;src:TsrRegNode):TsrBitcast;
|
|
function Find(dtype:TsrDataType;src:TsrRegNode):TsrRegNode;
|
|
Procedure Save(dtype:TsrDataType;src,dst:TsrRegNode);
|
|
function CastConst(dtype:TsrDataType;src:TsrRegNode):TsrRegNode;
|
|
function FetchRead(dtype:TsrDataType;src:TsrRegNode):TsrRegNode;
|
|
function FetchDstr(dtype:TsrDataType;src:TsrRegNode):TsrRegNode;
|
|
function FetchCast(dtype:TsrDataType;src:TsrRegNode):TsrRegNode;
|
|
end;
|
|
|
|
implementation
|
|
|
|
class function TsrBitcast.c(n1,n2:PsrBitcastKey):Integer;
|
|
begin
|
|
//first dtype
|
|
Result:=ord(n1^.dtype>n2^.dtype)-ord(n1^.dtype<n2^.dtype);
|
|
if (Result<>0) then Exit;
|
|
//second src (not need order sort)
|
|
Result:=ord(ptruint(n1^.src)>ptruint(n2^.src))-ord(ptruint(n1^.src)<ptruint(n2^.src));
|
|
end;
|
|
|
|
procedure TsrBitcastList.Init(Emit:TCustomEmit); inline;
|
|
begin
|
|
rSlot.Init(Emit,'BCAST',cNone);
|
|
end;
|
|
|
|
function TsrBitcastList._Find(dtype:TsrDataType;src:TsrRegNode):TsrBitcast;
|
|
var
|
|
key:TsrBitcastKey;
|
|
begin
|
|
key:=Default(TsrBitcastKey);
|
|
key.dtype:=dtype;
|
|
key.src:=src;
|
|
Result:=FTree.Find(@key);
|
|
end;
|
|
|
|
function TsrBitcastList.Find(dtype:TsrDataType;src:TsrRegNode):TsrRegNode;
|
|
var
|
|
node:TsrBitcast;
|
|
begin
|
|
Result:=nil;
|
|
node:=_Find(dtype,src);
|
|
if (node<>nil) then
|
|
begin
|
|
Result:=node.dst;
|
|
end;
|
|
end;
|
|
|
|
Procedure TsrBitcastList.Save(dtype:TsrDataType;src,dst:TsrRegNode);
|
|
var
|
|
node:TsrBitcast;
|
|
begin
|
|
node:=rSlot.Emit.specialize New<TsrBitcast>;
|
|
node.key:=Default(TsrBitcastKey);
|
|
node.key.dtype:=dtype;
|
|
node.key.src:=src;
|
|
node.dst:=dst;
|
|
FTree.Insert(node);
|
|
end;
|
|
|
|
function TsrBitcastList.CastConst(dtype:TsrDataType;src:TsrRegNode):TsrRegNode;
|
|
var
|
|
pConstList:PsrConstList;
|
|
pConst:TsrConst;
|
|
begin
|
|
pConst:=src.AsConst;
|
|
|
|
pConstList:=rSlot.Emit.GetConstList;
|
|
pConst:=pConstList^.Bitcast(dtype,pConst);
|
|
|
|
Result:=rSlot.New(dtype);
|
|
Result.pWriter:=pConst;
|
|
Result.CustomLine:=src.CustomLine;
|
|
end;
|
|
|
|
function TsrBitcastList.FetchRead(dtype:TsrDataType;src:TsrRegNode):TsrRegNode;
|
|
var
|
|
dst:TsrRegNode;
|
|
begin
|
|
Result:=src;
|
|
if (src=nil) then Exit;
|
|
if (dtype=dtUnknow) or (dtype=src.dtype) then Exit;
|
|
|
|
Assert(TryBitcastType(src.dtype,dtype));
|
|
|
|
if src.is_const then
|
|
begin
|
|
//only from consts, first
|
|
dst:=Find(dtype,src);
|
|
if (dst<>nil) then Exit(dst);
|
|
//
|
|
dst:=CastConst(dtype,src);
|
|
//
|
|
Save(dtype,src,dst);
|
|
end else
|
|
begin
|
|
dst:=rSlot.New(dtype);
|
|
dst.pWriter:=src;
|
|
end;
|
|
|
|
Result:=dst;
|
|
end;
|
|
|
|
function TsrBitcastList.FetchDstr(dtype:TsrDataType;src:TsrRegNode):TsrRegNode;
|
|
var
|
|
dst:TsrRegNode;
|
|
begin
|
|
Result:=src;
|
|
if (src=nil) then Exit;
|
|
if (dtype=dtUnknow) or (dtype=src.dtype) then Exit;
|
|
|
|
Assert(TryBitcastType(src.dtype,dtype));
|
|
|
|
dst:=rSlot.New(dtype);
|
|
dst.pWriter:=src.pWriter;
|
|
|
|
src.pWriter:=dst;
|
|
|
|
Result:=dst;
|
|
end;
|
|
|
|
//post process
|
|
function TsrBitcastList.FetchCast(dtype:TsrDataType;src:TsrRegNode):TsrRegNode;
|
|
var
|
|
dst:TsrRegNode;
|
|
prv:TsrRegNode;
|
|
begin
|
|
Result:=src;
|
|
|
|
if (src=nil) then Exit;
|
|
if (dtype=dtUnknow) or (dtype=src.dtype) then Exit;
|
|
|
|
dst:=nil;
|
|
|
|
Assert(TryBitcastType(src.dtype,dtype));
|
|
|
|
//
|
|
dst:=Find(dtype,src);
|
|
if (dst<>nil) then Exit(dst);
|
|
|
|
prv:=RegDown(src);
|
|
|
|
if prv.is_const then
|
|
begin
|
|
dst:=CastConst(dtype,prv);
|
|
end else
|
|
begin
|
|
if TryBitcastType(src.dtype,dtype) then
|
|
begin
|
|
dst:=rSlot.New(dtype);
|
|
|
|
rSlot.Emit.OpCast(prv.pLine,dst,src);
|
|
end else
|
|
begin
|
|
Writeln('bitcast:',src.dtype,'<>',dtype);
|
|
Assert(false,'bitcast');
|
|
end;
|
|
end;
|
|
|
|
//
|
|
Save(dtype,src,dst);
|
|
|
|
Result:=dst;
|
|
end;
|
|
|
|
end.
|
|
|