mirror of https://github.com/red-prig/fpPS4.git
715 lines
15 KiB
Plaintext
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.
|
|
|