FPPS4/spirv/srNode.pas

715 lines
15 KiB
Plaintext

unit srNode;
{$mode objfpc}{$H+}
interface
uses
ginodes;
type
TsrNode=class;
PPsrNode=^TsrNode;
TDependenceNode=class
pLeft,pRight:TDependenceNode;
//
key:TsrNode;
//
fread_count :DWORD;
fwrite_count:DWORD;
//
class function c(n1,n2:PPsrNode):Integer; static;
//
property pNode:TsrNode read key write key;
property pPrev:TDependenceNode read pLeft write pLeft;
property pNext:TDependenceNode read pRight write pRight;
end;
TDependenceNodeList=specialize TNodeListClass<TDependenceNode>;
TDependenceNodeTree=specialize TNodeTreeClass<TDependenceNode>;
PPrepTypeNode=^TPrepTypeNode;
TPrepTypeNode=record
dnode:TsrNode;
rtype:Integer;
end;
TsrNodeType=class of TsrNode;
TCustomEmit=class;
TsrNode=class
private
fread_count :DWORD;
fwrite_count:DWORD;
FOrder :Ptruint;
FDependence :TDependenceNodeTree;
FEmit :TCustomEmit;
public
function Order:Ptruint;
property Emit:TCustomEmit read FEmit;
//
function NewDependence:TDependenceNode;
procedure FreeDependence(D:TDependenceNode);
function FirstDependence:TDependenceNode;
function NextDependence(D:TDependenceNode):TDependenceNode;
//
Procedure add_read(src:TsrNode); virtual;
Procedure rem_read(src:TsrNode); virtual;
//
Procedure add_write(src:TsrNode); virtual;
Procedure rem_write(src:TsrNode); virtual;
//
Procedure _mark_read(src:TsrNode); virtual;
Procedure _mark_unread(src:TsrNode); virtual;
//
Procedure _zero_read; virtual;
Procedure _zero_unread; virtual;
//
Procedure _mark_write(src:TsrNode); virtual;
Procedure _mark_unwrite(src:TsrNode); virtual;
//
Procedure _SetWriter(w,line:TsrNode); virtual;
Procedure _ResetWriter(w:TsrNode); virtual;
Function _is_used:Boolean virtual;
Function _GetPline:TsrNode; virtual;
Function _GetPtype:TsrNode; virtual;
Function _GetStorageClass:DWORD; virtual;
function _GetStorageName:RawByteString; virtual;
function _GetPrintName:RawByteString; virtual;
function _GetPrintData:RawByteString; virtual;
function _Down:TsrNode; virtual;
function _Next:TsrNode; virtual;
function _Prev:TsrNode; virtual;
function _Parent:TsrNode; virtual;
function _First:TsrNode; virtual;
function _Last:TsrNode; virtual;
Procedure _PrepType(node:PPrepTypeNode); virtual;
//
function _GetIndexCount:DWORD; virtual;
//
function _GetRef:Pointer; virtual;
//
function _GetData(data:Pointer):Ptruint; virtual;
//
function ntype:TsrNodeType;
property read_count :DWORD read fread_count;
property write_count:DWORD read fwrite_count;
function IsType(t:TsrNodeType):Boolean;
generic function AsType<T>:T;
Procedure mark_read (src:TsrNode);
Procedure mark_unread (src:TsrNode);
Procedure mark_write (src:TsrNode);
Procedure mark_unwrite(src:TsrNode);
Procedure SetWriter(w,line:TsrNode);
Procedure ResetWriter(w:TsrNode);
function IsUsed:Boolean;
Function pType:TsrNode;
Function GetStorageClass:DWORD;
function GetStorageName:RawByteString;
function GetPrintName:RawByteString;
function GetPrintData:RawByteString;
function Next:TsrNode;
function Prev:TsrNode;
function Parent:TsrNode;
function First:TsrNode;
function Last:TsrNode;
procedure PrepType(rtype:Integer);
function GetIndexCount:DWORD;
function GetRef:Pointer;
function GetData(data:Pointer):Ptruint;
end;
TCustomEmit=class
private
FOrder:Ptruint;
FDependenceCache:TDependenceNodeList;
public
//
Function Alloc(Size:ptruint):Pointer; virtual abstract;
generic Function New<T>:T;
Function GetDmem(P:Pointer) :Pointer; virtual abstract;
Function GetExecutionModel :Word; virtual abstract;
Function GetConfig :Pointer; virtual abstract;
Function GetCodeHeap :Pointer; virtual abstract;
Function GetLiteralList :Pointer; virtual abstract;
Function GetTypeList :Pointer; virtual abstract;
Function GetConstList :Pointer; virtual abstract;
Function GetRegsStory :Pointer; virtual abstract;
Function GetCapabilityList :Pointer; virtual abstract;
Function GetHeaderList :TsrNode; virtual abstract;
Function GetDecorateList :TsrNode; virtual abstract;
Function GetDebugInfoList :TsrNode; virtual abstract;
Function GetVariableList :Pointer; virtual abstract;
Function GetInputList :Pointer; virtual abstract;
Function GetOutputList :Pointer; virtual abstract;
Function GetDataLayoutList :Pointer; virtual abstract;
Function GetVertLayoutList :Pointer; virtual abstract;
Function GetFragLayoutList :Pointer; virtual abstract;
Function GetBufferList :Pointer; virtual abstract;
Function GetUniformList :Pointer; virtual abstract;
Function GetBitcastList :Pointer; virtual abstract;
Function GetCacheOpList :Pointer; virtual abstract;
Function GetFuncList :Pointer; virtual abstract;
Function GetCursor :Pointer; virtual abstract;
function curr_line :TsrNode; virtual abstract;
function init_line :TsrNode; virtual abstract;
function NewRefNode :TsrNode; virtual abstract;
function OpCast (pLine, dst,src:TsrNode):TsrNode; virtual abstract;
function OpLoad (pLine,dtype,dst,src:TsrNode):TsrNode; virtual abstract;
function OpStore (pLine, dst,src:TsrNode):TsrNode; virtual abstract;
Function PostLink(pLine, dst:TsrNode):TsrNode; virtual abstract;
procedure emit_spi; virtual abstract;
end;
function CompareNodes(buf1,buf2:PPsrNode;count:PtrUint):Integer;
implementation
class function TDependenceNode.c(n1,n2:PPsrNode):Integer;
begin
Result:=ord(ptruint(n1^)>ptruint(n2^))-ord(ptruint(n1^)<ptruint(n2^));
end;
function TsrNode.Order:Ptruint;
begin
Result:=0;
if (Self<>nil) then
begin
Result:=FOrder;
end;
end;
function TsrNode.NewDependence:TDependenceNode;
begin
if (Self=nil) then Exit(nil);
Result:=FEmit.FDependenceCache.Pop_tail;
if (Result=nil) then
begin
Result:=FEmit.specialize New<TDependenceNode>;
end;
end;
procedure TsrNode.FreeDependence(D:TDependenceNode);
begin
if (Self=nil) then Exit;
if (D=nil) then Exit;
D.pNode:=nil;
FEmit.FDependenceCache.Push_head(D);
end;
function TsrNode.FirstDependence:TDependenceNode;
begin
Result:=FDependence.Min;
end;
function TsrNode.NextDependence(D:TDependenceNode):TDependenceNode;
begin
Result:=FDependence.Next(D);
end;
Procedure TsrNode.add_read(src:TsrNode);
Var
D:TDependenceNode;
begin
D:=FDependence.Find(@src);
if (D=nil) then
begin
D:=NewDependence;
//
D.pNode:=src;
FDependence.Insert(D);
end;
Inc(D.fread_count);
Inc(fread_count);
end;
Procedure TsrNode.rem_read(src:TsrNode);
Var
D:TDependenceNode;
begin
Assert(fread_count<>0,'zero read deref:'+ntype.ClassName);
//
D:=FDependence.Find(@src);
if (D<>nil) then
begin
Assert(D.fread_count<>0,'zero read deref:'+ntype.ClassName);
//
Dec(D.fread_count);
//
if (D.fread_count=0) and (D.fwrite_count=0) then
begin
FDependence.Delete(D);
//
FreeDependence(D);
end;
//
Dec(fread_count);
end else
begin
Assert(false,'unknow read deref:'+ntype.ClassName);
end;
end;
Procedure TsrNode.add_write(src:TsrNode);
Var
D:TDependenceNode;
begin
D:=FDependence.Find(@src);
if (D=nil) then
begin
D:=NewDependence;
//
D.pNode:=src;
FDependence.Insert(D);
end;
Inc(D.fwrite_count);
Inc(fwrite_count);
end;
Procedure TsrNode.rem_write(src:TsrNode);
Var
D:TDependenceNode;
begin
Assert(fwrite_count<>0,'zero write deref:'+ntype.ClassName);
//
D:=FDependence.Find(@src);
if (D<>nil) then
begin
Assert(D.fwrite_count<>0,'zero write deref:'+ntype.ClassName);
//
Dec(D.fwrite_count);
//
if (D.fread_count=0) and (D.fwrite_count=0) then
begin
FDependence.Delete(D);
//
FreeDependence(D);
end;
//
Dec(fwrite_count);
end else
begin
Assert(false,'unknow write deref:'+ntype.ClassName);
end;
end;
Procedure TsrNode._mark_read(src:TsrNode);
var
node:TsrNode;
prv:Boolean;
begin
node:=Self;
repeat
//Assert(node^.fntype<>nil);
prv:=node.IsUsed;
node.add_read(src);
if (prv=node.IsUsed) then Exit;
node._zero_read;
src :=node;
node:=node._Down;
until (node=nil);
end;
Procedure TsrNode._mark_unread(src:TsrNode);
var
node:TsrNode;
prv:Boolean;
begin
node:=Self;
repeat
//Assert(node^.fntype<>nil);
prv:=node.IsUsed;
node.rem_read(src);
if (prv=node.IsUsed) then Exit;
node._zero_unread;
src :=node;
node:=node._Down;
until (node=nil);
end;
Procedure TsrNode._zero_read;
begin
//
end;
Procedure TsrNode._zero_unread;
begin
//
end;
Procedure TsrNode._mark_write(src:TsrNode);
var
node:TsrNode;
prv:Boolean;
begin
node:=Self;
repeat
//Assert(node^.fntype<>nil);
prv:=node.IsUsed;
node.add_write(src);
if (prv=node.IsUsed) then Exit;
node._zero_read;
src :=node;
node:=node._Down;
until (node=nil);
end;
Procedure TsrNode._mark_unwrite(src:TsrNode);
var
node:TsrNode;
prv:Boolean;
begin
node:=Self;
repeat
//Assert(node^.fntype<>nil);
prv:=node.IsUsed;
node.rem_write(src);
if (prv=node.IsUsed) then Exit;
node._zero_unread;
src :=node;
node:=node._Down;
until (node=nil);
end;
Procedure TsrNode._SetWriter(w,line:TsrNode);
begin
w.mark_read(Self);
end;
Procedure TsrNode._ResetWriter(w:TsrNode);
begin
w.mark_unread(Self);
end;
function TsrNode._is_used:Boolean;
begin
Result:=(read_count<>0) or (write_count<>0);
end;
Function TsrNode._GetPline:TsrNode;
begin
Result:=nil;
end;
function TsrNode._GetPtype:TsrNode;
begin
Result:=nil;
end;
function TsrNode._GetStorageClass:DWORD;
begin
Result:=6;
end;
function TsrNode._GetStorageName:RawByteString;
begin
Result:='';
end;
function TsrNode._GetPrintName:RawByteString;
begin
Result:='';
end;
function TsrNode._GetPrintData:RawByteString;
begin
Result:='';
end;
function TsrNode._Down:TsrNode;
begin
Result:=nil;
end;
function TsrNode._Next:TsrNode;
begin
Result:=nil;
end;
function TsrNode._Prev:TsrNode;
begin
Result:=nil;
end;
function TsrNode._Parent:TsrNode;
begin
Result:=nil;
end;
function TsrNode._First:TsrNode;
begin
Result:=nil;
end;
function TsrNode._Last:TsrNode;
begin
Result:=nil;
end;
Procedure TsrNode._PrepType(node:PPrepTypeNode);
begin
node^.dnode:=nil;
end;
function TsrNode._GetIndexCount:DWORD;
begin
Result:=0;
end;
function TsrNode._GetRef:Pointer;
begin
Result:=nil;
end;
function TsrNode._GetData(data:Pointer):Ptruint;
begin
Result:=0;
end;
//
function TsrNode.ntype:TsrNodeType;
begin
Result:=TsrNodeType(ClassType);
end;
function TsrNode.IsType(t:TsrNodeType):Boolean;
begin
Result:=False;
if (Self=nil) then Exit;
Result:=InheritsFrom(t);
end;
generic function TsrNode.AsType<T>:T;
begin
Result:=nil;
if (Self=nil) then Exit;
if not InheritsFrom(T) then Exit;
Result:=T(Self);
end;
Procedure TsrNode.mark_read(src:TsrNode);
begin
if (Self=nil) then Exit;
//Assert(fntype<>nil);
_mark_read(src);
end;
Procedure TsrNode.mark_unread(src:TsrNode);
begin
if (Self=nil) then Exit;
//Assert(fntype<>nil);
_mark_unread(src);
end;
Procedure TsrNode.mark_write(src:TsrNode);
begin
if (Self=nil) then Exit;
//Assert(fntype<>nil);
_mark_write(src);
end;
Procedure TsrNode.mark_unwrite(src:TsrNode);
begin
if (Self=nil) then Exit;
//Assert(fntype<>nil);
_mark_unwrite(src);
end;
Procedure TsrNode.SetWriter(w,line:TsrNode);
begin
if (Self=nil) then Exit;
//Assert(fntype<>nil);
_SetWriter(w,line);
end;
Procedure TsrNode.ResetWriter(w:TsrNode);
begin
if (Self=nil) then Exit;
//Assert(fntype<>nil);
_ResetWriter(w);
end;
function TsrNode.IsUsed:Boolean;
begin
Result:=False;
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_is_used;
end;
Function TsrNode.pType:TsrNode;
begin
Result:=nil;
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_GetPtype;
end;
Function TsrNode.GetStorageClass:DWORD;
begin
Result:=6;
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_GetStorageClass;
end;
function TsrNode.GetStorageName:RawByteString;
begin
Result:='';
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_GetStorageName;
end;
function TsrNode.GetPrintName:RawByteString;
begin
Result:='';
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_GetPrintName;
end;
function TsrNode.GetPrintData:RawByteString;
begin
Result:='';
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_GetPrintData;
end;
function TsrNode.Next:TsrNode;
begin
Result:=nil;
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_Next;
end;
function TsrNode.Prev:TsrNode;
begin
Result:=nil;
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_Prev;
end;
function TsrNode.Parent:TsrNode;
begin
Result:=nil;
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_Parent;
end;
function TsrNode.First:TsrNode;
begin
Result:=nil;
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_First;
end;
function TsrNode.Last:TsrNode;
begin
Result:=nil;
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_Last;
end;
procedure TsrNode.PrepType(rtype:Integer);
var
node:TPrepTypeNode;
begin
node:=Default(TPrepTypeNode);
node.dnode:=Self;
node.rtype:=rtype;
While (node.dnode<>nil) do
begin
//Assert(node.dnode^.fntype<>nil);
node.dnode._PrepType(@node);
end;
end;
function TsrNode.GetIndexCount:DWORD;
begin
Result:=0;
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_GetIndexCount;
end;
function TsrNode.GetRef:Pointer;
begin
Result:=nil;
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_GetRef;
end;
function TsrNode.GetData(data:Pointer):Ptruint;
begin
Result:=0;
if (Self=nil) then Exit;
//Assert(fntype<>nil);
Result:=_GetData(data);
end;
//
generic Function TCustomEmit.New<T>:T;
begin
Result:=nil;
if (Self=nil) then Exit;
//
Result:=T(Alloc(TObject(T).InstanceSize));
TObject(T).InitInstance(Result);
//
if TObject(T).InheritsFrom(TsrNode) then
begin
Inc(FOrder);
//
TsrNode(Result).FOrder:=FOrder;
TsrNode(Result).FEmit :=Self;
end;
end;
function CompareNodes(buf1,buf2:PPsrNode;count:PtrUint):Integer;
begin
Result:=0;
While (count<>0) do
begin
Result:=Integer(buf1^.Order>buf2^.Order)-Integer(buf1^.Order<buf2^.Order);
if (Result<>0) then Exit;
Inc(buf1);
Inc(buf2);
Dec(count);
end;
end;
end.