mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-11-27 00:20:36 +00:00
153 lines
2.9 KiB
ObjectPascal
153 lines
2.9 KiB
ObjectPascal
unit srBitcast;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
sysutils,
|
|
srNodes,
|
|
srTypes,
|
|
srConst,
|
|
srReg;
|
|
|
|
type
|
|
PsrBitcast=^TsrBitcast;
|
|
TsrBitcast=object
|
|
pLeft,pRight:PsrBitcast;
|
|
//----
|
|
key:packed record
|
|
dtype:TsrDataType;
|
|
src:PsrRegNode;
|
|
end;
|
|
dst:PsrRegNode;
|
|
function c(n1,n2:PsrBitcast):Integer; static;
|
|
end;
|
|
|
|
TsrBitcastList=object
|
|
type
|
|
TNodeFetch=specialize TNodeFetch<PsrBitcast,TsrBitcast>;
|
|
var
|
|
pRoot:Pointer;
|
|
FNTree:TNodeFetch;
|
|
function Find(dtype:TsrDataType;src:PsrRegNode):PsrBitcast;
|
|
function FetchRead(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
|
function FetchDst(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
|
function FetchCast(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
SprvEmit,
|
|
emit_op;
|
|
|
|
function TsrBitcast.c(n1,n2:PsrBitcast):Integer;
|
|
begin
|
|
Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrBitcast.key));
|
|
end;
|
|
|
|
function TsrBitcastList.Find(dtype:TsrDataType;src:PsrRegNode):PsrBitcast;
|
|
var
|
|
node:TsrBitcast;
|
|
begin
|
|
node:=Default(TsrBitcast);
|
|
node.key.dtype:=dtype;
|
|
node.key.src:=src;
|
|
Result:=FNTree.Find(@node);
|
|
end;
|
|
|
|
function TsrBitcastList.FetchRead(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
|
var
|
|
dst:PsrRegNode;
|
|
begin
|
|
Result:=src;
|
|
if (src=nil) then Exit;
|
|
if (dtype=dtUnknow) or (dtype=src^.dtype) then
|
|
begin
|
|
src^.mark_read;
|
|
Exit;
|
|
end;
|
|
|
|
src^.mark_read;
|
|
dst:=PSprvEmit(pRoot)^.NewReg(dtype);
|
|
dst^.pLine:=src^.pLine;
|
|
dst^.pWriter.SetParam(ntReg,src);
|
|
|
|
dst^.mark_read;
|
|
Result:=dst;
|
|
end;
|
|
|
|
function TsrBitcastList.FetchDst(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
|
begin
|
|
Result:=src;
|
|
if (src=nil) then Exit;
|
|
if (dtype=dtUnknow) or (dtype=src^.dtype) then Exit;
|
|
|
|
Result:=PSprvEmit(pRoot)^.NewReg(dtype);
|
|
Result^.pLine:=src^.pLine;
|
|
Result^.mark_read;
|
|
|
|
Result^.pWriter:=src^.pWriter;
|
|
src^.pWriter.SetParam(ntReg,Result);
|
|
end;
|
|
|
|
function TsrBitcastList.FetchCast(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
|
var
|
|
node:PsrBitcast;
|
|
dst:PsrRegNode;
|
|
|
|
begin
|
|
Result:=src;
|
|
if (src=nil) then Exit;
|
|
if (dtype=dtUnknow) or (dtype=src^.dtype) then
|
|
begin
|
|
src^.mark_read;
|
|
Exit;
|
|
end;
|
|
|
|
dst:=nil;
|
|
|
|
node:=Find(dtype,src);
|
|
if (node<>nil) then
|
|
begin
|
|
dst:=node^.dst;
|
|
dst^.mark_read;
|
|
Result:=dst;
|
|
Exit;
|
|
end;
|
|
|
|
if src^.is_const then
|
|
begin
|
|
src^.AsConst^.mark_unread;
|
|
dst:=PSprvEmit(pRoot)^.NewReg(dtype);
|
|
dst^.pLine:=src^.pLine;
|
|
dst^.pWriter.SetParam(ntConst,PSprvEmit(pRoot)^.FConsts.Bitcast(dtype,src^.AsConst));
|
|
end else
|
|
begin
|
|
if TryBitcastType(src^.dtype,dtype) then
|
|
begin
|
|
src^.mark_read;
|
|
dst:=PSprvEmit(pRoot)^.NewReg(dtype);
|
|
dst^.pLine:=src^.pLine;
|
|
PEmitOp(pRoot)^.emit_OpCastExt(src^.pLine,dst,src);
|
|
end else
|
|
begin
|
|
Assert(false,'bitcast');
|
|
end;
|
|
end;
|
|
|
|
node:=PSprvEmit(pRoot)^.Alloc(SizeOf(TsrBitcast));
|
|
node^:=Default(TsrBitcast);
|
|
node^.key.dtype:=dtype;
|
|
node^.key.src:=src;
|
|
node^.dst:=dst;
|
|
FNTree.Insert(node);
|
|
|
|
dst^.mark_read;
|
|
Result:=dst;
|
|
end;
|
|
|
|
end.
|
|
|