FPPS4/spirv/srBitcast.pas

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.