fpPS4/spirv/emit_post.pas

1002 lines
20 KiB
ObjectPascal
Raw Normal View History

2022-05-31 07:17:14 +00:00
unit emit_post;
{$mode objfpc}{$H+}
interface
uses
sysutils,
spirv,
2022-09-05 13:30:24 +00:00
srNode,
srType,
2022-05-31 07:17:14 +00:00
srTypes,
srConst,
srReg,
srVariable,
srLayout,
srBuffer,
2022-09-05 13:30:24 +00:00
srBitcast,
srPrivate,
2022-05-31 07:17:14 +00:00
srOp,
srOpUtils,
2022-09-05 13:30:24 +00:00
emit_fetch;
2022-05-31 07:17:14 +00:00
type
TPostCb=function(node:PSpirvOp):Integer of object;
TRegsCb=function(pLine:PspirvOp;var node:PsrRegNode):Integer of object;
2022-09-05 13:30:24 +00:00
TSprvEmit_post=class(TEmitFetch)
function PostStage:Integer;
2022-05-31 07:17:14 +00:00
function RegFindCond(pLine:PspirvOp;var node:PsrRegNode):Integer;
2022-09-05 13:30:24 +00:00
function RegCollapse(pLine:PspirvOp;var node:PsrRegNode):Integer;
function RegVResolve(pLine:PspirvOp;var node:PsrRegNode):Integer;
function RegWResolve(pLine:PspirvOp;var node:PsrRegNode):Integer;
2022-05-31 07:17:14 +00:00
function RegTypecast(pLine:PspirvOp;var node:PsrRegNode):Integer;
function RegSTStrict(pLine:PspirvOp;var node:PsrRegNode):Integer;
function RegVTStrict(pLine:PspirvOp;var node:PsrRegNode):Integer;
2022-09-05 13:30:24 +00:00
//function NodeOpSameOp(node:PSpirvOp):Integer;
2022-05-31 07:17:14 +00:00
function NodeOpStrict(node:PSpirvOp):Integer;
function OnOpStep1(node:PSpirvOp):Integer; //backward
function OnOpStep2(node:PSpirvOp):Integer; //forward
function OnOpStep3(node:PSpirvOp):Integer; //forward
function OnOpStep4(node:PSpirvOp):Integer; //forward
function OnOpStep5(node:PSpirvOp):Integer; //backward
2022-09-05 13:30:24 +00:00
function OnOpStep6(node:PSpirvOp):Integer; //backward
function OnOpStep7(node:PSpirvOp):Integer; //backward
2022-05-31 07:17:14 +00:00
function PostFuncAnalize:Integer;
2022-09-05 13:30:24 +00:00
function OnChainUpdate(node:PsrChain):Integer;
2022-05-31 07:17:14 +00:00
2022-09-07 18:06:19 +00:00
function PostDataLayoutAnalize1:Integer;
function PostDataLayoutAnalize2:Integer;
2022-05-31 07:17:14 +00:00
function FetchField(var pChain:PsrChain;dtype:TsrDataType):PsrField;
function OnChainField(node:PsrChain):Integer;
function OnChainAlloc(node:PsrChain):Integer;
procedure OnFieldType(node:PsrField);
function PostConstAnalize:Integer;
function PostVariableAnalize:Integer;
2022-09-05 13:30:24 +00:00
function PostTypeAnalize:Integer;
2022-05-31 07:17:14 +00:00
end;
function EnumLineRegs(cb:TRegsCb;pLine:PSpirvOp):Integer;
function EnumBlockOpForward(cb:TPostCb;pBlock:PsrOpBlock):Integer;
function EnumBlockOpBackward(cb:TPostCb;pBlock:PsrOpBlock):Integer;
implementation
uses
emit_post_op;
2022-09-05 13:30:24 +00:00
function TSprvEmit_post.PostStage:Integer;
2022-05-31 07:17:14 +00:00
begin
Result:=0;
2022-11-05 14:48:13 +00:00
InputList.Test;
2022-05-31 07:17:14 +00:00
Result:=Result+PostFuncAnalize;
Result:=Result+PostVariableAnalize;
2022-09-05 13:30:24 +00:00
Result:=Result+PostConstAnalize;
Result:=Result+PostTypeAnalize;
2022-05-31 07:17:14 +00:00
end;
function EnumLineRegs(cb:TRegsCb;pLine:PSpirvOp):Integer;
var
node:POpParamNode;
2022-09-05 13:30:24 +00:00
pReg:PsrRegNode;
2022-05-31 07:17:14 +00:00
begin
Result:=0;
if (cb=nil) or (pLine=nil) then Exit;
2022-09-05 13:30:24 +00:00
node:=pLine^.ParamFirst;
2022-05-31 07:17:14 +00:00
While (node<>nil) do
begin
2022-09-05 13:30:24 +00:00
if node^.Value^.IsType(ntReg) then
begin
pReg:=node^.AsReg;
Result:=Result+cb(pLine,pReg);
node^.Value:=pReg;
2022-05-31 07:17:14 +00:00
end;
2022-09-05 13:30:24 +00:00
node:=node^.Next;
2022-05-31 07:17:14 +00:00
end;
end;
function EnumBlockOpForward(cb:TPostCb;pBlock:PsrOpBlock):Integer;
var
2022-09-05 13:30:24 +00:00
node,prev:PSpirvOp;
2022-05-31 07:17:14 +00:00
begin
Result:=0;
if (pBlock=nil) or (cb=nil) then Exit;
2022-09-05 13:30:24 +00:00
node:=pBlock^.First;
While (node<>nil) do
begin
prev:=node;
node:=flow_down_next_up(node);
if prev^.IsType(ntOp) then
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
Result:=Result+cb(prev);
2022-05-31 07:17:14 +00:00
end;
2022-09-05 13:30:24 +00:00
end;
2022-05-31 07:17:14 +00:00
end;
function EnumBlockOpBackward(cb:TPostCb;pBlock:PsrOpBlock):Integer;
var
2022-09-05 13:30:24 +00:00
node,prev:PSpirvOp;
2022-05-31 07:17:14 +00:00
begin
Result:=0;
if (pBlock=nil) or (cb=nil) then Exit;
2022-09-05 13:30:24 +00:00
node:=pBlock^.Last;
While (node<>nil) do
begin
prev:=node;
node:=flow_down_prev_up(node);
if prev^.IsType(ntOp) then
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
Result:=Result+cb(prev);
2022-05-31 07:17:14 +00:00
end;
2022-09-05 13:30:24 +00:00
end;
2022-05-31 07:17:14 +00:00
end;
function TSprvEmit_post.RegFindCond(pLine:PspirvOp;var node:PsrRegNode):Integer;
var
pBlock:PsrOpBlock;
tmp:PsrOpBlock;
src:PsrRegNode;
p:PspirvOp;
n:Boolean;
begin
Result:=0;
if (node=nil) then Exit;
2022-09-05 13:30:24 +00:00
pBlock:=pLine^.Parent;
2022-05-31 07:17:14 +00:00
src:=RegDown(node);
n:=false;
repeat
if src^.is_const then Exit;
tmp:=pBlock^.FindUpCond(src);
if (tmp<>nil) then
begin
if (tmp=pBlock) and (pLine^.OpId=Op.OpBranchConditional) then Exit;
2022-09-05 13:30:24 +00:00
node:=NewReg_b(n xor tmp^.Cond.FVal,@pLine);
2022-05-31 07:17:14 +00:00
Exit(1);
end;
2022-09-05 13:30:24 +00:00
p:=src^.pWriter^.AsType(ntOp);
2022-05-31 07:17:14 +00:00
if (p=nil) then Exit;
Case p^.OpId of
Op.OpLogicalNot:;
Op.OpNot:;
else
Exit;
end;
2022-09-05 13:30:24 +00:00
src:=p^.ParamFirst^.AsReg;
2022-05-31 07:17:14 +00:00
if (src=nil) then Exit;
src:=RegDown(src);
n:=not n;
until false;
end;
function TSprvEmit_post.RegCollapse(pLine:PspirvOp;var node:PsrRegNode):Integer;
var
2022-09-05 13:30:24 +00:00
old:PsrRegNode;
2022-05-31 07:17:14 +00:00
begin
Result:=0;
if (node=nil) then Exit;
2022-09-05 13:30:24 +00:00
if (node^.dtype=dtUnknow) then Exit;
2022-05-31 07:17:14 +00:00
old:=node;
2022-09-05 13:30:24 +00:00
node:=RegDown(old);
2022-05-31 07:17:14 +00:00
if (old<>node) then //is change?
begin
if (node^.dtype=dtUnknow) or CompareType(node^.dtype,old^.dtype) then
begin
Inc(Result);
end else
begin //save to another step
2022-09-05 13:30:24 +00:00
old^.pWriter:=node;
node:=old;
2022-05-31 07:17:14 +00:00
end;
end;
end;
2022-09-05 13:30:24 +00:00
function TSprvEmit_post.RegVResolve(pLine:PspirvOp;var node:PsrRegNode):Integer;
2022-05-31 07:17:14 +00:00
var
2022-09-05 13:30:24 +00:00
old:PsrRegNode;
2022-05-31 07:17:14 +00:00
begin
Result:=0;
if (node=nil) then Exit;
2022-09-05 13:30:24 +00:00
2022-05-31 07:17:14 +00:00
old:=node;
2022-09-05 13:30:24 +00:00
2022-11-05 14:48:13 +00:00
node:=RegDown(old);
if node^.pWriter^.IsType(ntVolatile) then
begin
//create load/store
//use forward only
node:=PrivateList.PrepVolatile(pLine,node);
Inc(Result);
end;
2022-05-31 07:17:14 +00:00
if (old<>node) then //is change?
begin
2022-07-01 12:53:39 +00:00
if (node^.dtype=dtUnknow) or (node^.dtype=old^.dtype) then
2022-05-31 07:17:14 +00:00
begin
Inc(Result);
end else
2022-09-05 13:30:24 +00:00
begin //save to another step
old^.pWriter:=node;
node:=old;
2022-05-31 07:17:14 +00:00
end;
end;
end;
2022-09-05 13:30:24 +00:00
function GetDepType(src:PsrRegNode):TsrDataType;
2022-05-31 07:17:14 +00:00
var
2022-09-05 13:30:24 +00:00
node:PRegDNode;
pReg:PsrRegNode;
pLine:PspirvOp;
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
Function CmpType(var ret:TsrDataType;dtype:TsrDataType):Boolean;
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
Result:=False;
if (dtype=dtUnknow) then Exit;
if (ret=dtUnknow) then
begin
ret:=dtype;
end else
begin
if (ret<>dtype) then
begin
ret:=dtUnknow;
Result:=True; //Exit
end;
end;
2022-05-31 07:17:14 +00:00
end;
begin
2022-09-05 13:30:24 +00:00
Result:=dtUnknow;
node:=src^.FirstDep;
While (node<>nil) do
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
if node^.pNode^.IsType(ntReg) then
begin
pReg:=node^.pNode^.AsType(ntReg);
if (pReg<>nil) then
begin
if CmpType(Result,pReg^.dtype) then Exit;
end;
end else
if node^.pNode^.IsType(ntOp) then
begin
pLine:=node^.pNode^.AsType(ntOp);
Case pLine^.OpId of
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
Op.OpStore:
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
//ignore?
2022-05-31 07:17:14 +00:00
end;
2022-09-05 13:30:24 +00:00
else
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
if CmpType(Result,src^.dtype) then Exit;
2022-05-31 07:17:14 +00:00
end;
2022-09-05 13:30:24 +00:00
end;
2022-05-31 07:17:14 +00:00
end;
2022-09-05 13:30:24 +00:00
node:=node^.pNext;
2022-05-31 07:17:14 +00:00
end;
end;
2022-09-05 13:30:24 +00:00
function ResolveWeak(new:PsrRegNode):Integer;
2022-05-31 07:17:14 +00:00
var
2022-09-05 13:30:24 +00:00
dtype:TsrDataType;
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
Result:=0;
While (new<>nil) do
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
if new^.Weak then
begin
dtype:=GetDepType(new);
if (dtype<>dtUnknow) then
begin
if (new^.dtype<>dtype) then
begin
new^.dtype:=dtype;
new^.Weak :=False;
Inc(Result);
end else
begin
new^.Weak :=False;
end;
end;
end;
new:=new^.AsReg; //next
2022-05-31 07:17:14 +00:00
end;
end;
2022-09-05 13:30:24 +00:00
function TSprvEmit_post.RegWResolve(pLine:PspirvOp;var node:PsrRegNode):Integer;
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
Result:=0;
2022-05-31 07:17:14 +00:00
if (node=nil) then Exit;
2022-09-05 13:30:24 +00:00
Result:=Result+ResolveWeak(node);
end;
function TSprvEmit_post.RegTypecast(pLine:PspirvOp;var node:PsrRegNode):Integer;
var
old:PsrRegNode;
begin
Result:=0;
if (node=nil) then Exit;
old:=node;
node:=RegDown(old);
if (old<>node) then //is change?
begin
if (node^.dtype=dtUnknow) or (node^.dtype=old^.dtype) then
begin
Inc(Result);
end else
begin //bitcast
node:=BitcastList.FetchCast(old^.dtype,node);
Inc(Result);
end;
2022-05-31 07:17:14 +00:00
end;
end;
2022-09-05 13:30:24 +00:00
function TSprvEmit_post.RegSTStrict(pLine:PspirvOp;var node:PsrRegNode):Integer;
2022-05-31 07:17:14 +00:00
var
2022-09-05 13:30:24 +00:00
dtype:TsrDataType;
dst:PsrRegNode;
2022-05-31 07:17:14 +00:00
begin
Result:=0;
2022-09-05 13:30:24 +00:00
if (node^.dtype=dtBool) then Exit;
dst:=pLine^.pDst^.AsType(ntReg);
if (dst=nil) then Exit;
dtype:=dst^.dtype;
if (dtype<>node^.dtype) then
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
node:=BitcastList.FetchCast(dtype,node); //strict type
2022-05-31 07:17:14 +00:00
Inc(Result);
end;
2022-09-05 13:30:24 +00:00
end;
function TSprvEmit_post.RegVTStrict(pLine:PspirvOp;var node:PsrRegNode):Integer;
var
dtype:TsrDataType;
dst:PsrRegNode;
begin
Result:=0;
dst:=pLine^.pDst^.AsType(ntReg);
if (dst=nil) then Exit;
dtype:=dst^.dtype.Child;
if (dtype<>node^.dtype) then
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
node:=BitcastList.FetchCast(dtype,node); //strict type
2022-05-31 07:17:14 +00:00
Inc(Result);
end;
end;
2022-09-05 13:30:24 +00:00
{
2022-05-31 07:17:14 +00:00
function TSprvEmit_post.NodeOpSameOp(node:PSpirvOp):Integer;
var
tmp:PspirvOp;
dst,src:PsrRegNode;
begin
Result:=0;
if (node^.dst.ntype<>ntReg) then Exit; //is reg
Case node^.OpId of
Op.OpLoad:;
Op.OpCompositeConstruct:;
OpMakeExp:;
OpMakeVec:;
OpPackOfs:;
else
Exit;
end;
tmp:=FindUpSameOp(node^.pPrev,node);
if (tmp=nil) then Exit;
src:=tmp^.dst.AsReg;
dst:=node^.dst.AsReg;
if (src=nil) or (dst=nil) then Exit;
2022-07-15 10:12:45 +00:00
dst^.SetReg(src);
2022-05-31 07:17:14 +00:00
node^.OpId:=OpLinks; //mark remove
node^.dst:=Default(TOpParamSingle);
Result:=1;
end;
2022-09-05 13:30:24 +00:00
}
2022-05-31 07:17:14 +00:00
function TSprvEmit_post.NodeOpStrict(node:PSpirvOp):Integer;
begin
Result:=0;
2022-09-05 13:30:24 +00:00
if not node^.pDst^.IsType(ntReg) then Exit; //is reg
2022-05-31 07:17:14 +00:00
Case node^.OpId of
2022-09-05 13:30:24 +00:00
Op.OpBitFieldUExtract ,
Op.OpSelect :Result:=EnumLineRegs(@RegSTStrict,node);
Op.OpIAddCarry ,
Op.OpISubBorrow ,
2023-04-05 15:23:38 +00:00
Op.OpUMulExtended ,
Op.OpSMulExtended ,
2022-09-05 13:30:24 +00:00
Op.OpCompositeConstruct:Result:=EnumLineRegs(@RegVTStrict,node);
2022-05-31 07:17:14 +00:00
else;
end;
end;
function TSprvEmit_post.OnOpStep1(node:PSpirvOp):Integer; //backward
begin
Result:=0;
2022-09-05 13:30:24 +00:00
if node^.is_cleared then Exit;
if node^.can_clear then
begin
if node^.Clear then Inc(Result);
end else
begin
//Result:=Result+NodeOpSameOp(node);
Result:=Result+EnumLineRegs(@RegCollapse,node);
Result:=Result+EnumLineRegs(@RegFindCond,node);
2022-05-31 07:17:14 +00:00
end;
end;
function TSprvEmit_post.OnOpStep2(node:PSpirvOp):Integer; //forward
begin
Result:=0;
2022-09-05 13:30:24 +00:00
if node^.is_cleared then Exit;
if node^.can_clear then
begin
if node^.Clear then Inc(Result);
end else
begin
Result:=Result+TEmitPostOp(TObject(Self)).PostForward1(node);
2022-05-31 07:17:14 +00:00
end;
end;
function TSprvEmit_post.OnOpStep3(node:PSpirvOp):Integer; //forward
begin
Result:=0;
2022-09-05 13:30:24 +00:00
if node^.is_cleared then Exit;
if node^.can_clear then
begin
if node^.Clear then Inc(Result);
end else
begin
Result:=Result+TEmitPostOp(TObject(Self)).PostForward2(node);
2022-05-31 07:17:14 +00:00
end;
end;
function TSprvEmit_post.OnOpStep4(node:PSpirvOp):Integer; //forward
begin
Result:=0;
2022-09-05 13:30:24 +00:00
if node^.is_cleared then Exit;
if node^.can_clear then
begin
if node^.Clear then Inc(Result);
end else
begin
Result:=Result+EnumLineRegs(@RegVResolve,node);
2022-05-31 07:17:14 +00:00
end;
end;
function TSprvEmit_post.OnOpStep5(node:PSpirvOp):Integer; //backward
begin
Result:=0;
2022-09-05 13:30:24 +00:00
if node^.is_cleared then Exit;
if node^.can_clear then
begin
if node^.Clear then Inc(Result);
end else
begin
Result:=Result+EnumLineRegs(@RegWResolve,node);
end;
end;
function TSprvEmit_post.OnOpStep6(node:PSpirvOp):Integer; //backward
begin
Result:=0;
if node^.is_cleared then Exit;
if node^.can_clear then
begin
if node^.Clear then Inc(Result);
end else
begin
Result:=Result+EnumLineRegs(@RegTypecast,node);
Result:=Result+NodeOpStrict(node);
Result:=Result+EnumLineRegs(@RegFindCond,node);
end;
end;
function TSprvEmit_post.OnOpStep7(node:PSpirvOp):Integer; //backward
begin
Result:=0;
if node^.is_cleared then
begin
Assert(node^.read_count=0);
node^.Remove;
Inc(Result);
end else
if node^.can_clear then
begin
node^.Clear;
node^.Remove;
Inc(Result);
2022-05-31 07:17:14 +00:00
end;
end;
function TSprvEmit_post.PostFuncAnalize:Integer;
var
pFunc:PSpirvFunc;
data_layout:Boolean;
2022-09-05 13:30:24 +00:00
i,r4:Integer;
2022-05-31 07:17:14 +00:00
begin
Result:=0;
data_layout:=false;
//backward analize
2022-09-05 13:30:24 +00:00
pFunc:=FuncList.FList.pTail;
2022-05-31 07:17:14 +00:00
While (pFunc<>nil) do
begin
2022-09-05 13:30:24 +00:00
data_layout:=(Main=pFunc);
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
repeat //OnOpStep5
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
repeat //OnOpStep3
repeat //OnOpStep2
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
repeat //OnOpStep1
2022-09-07 18:06:19 +00:00
i:=EnumBlockOpBackward(@OnOpStep1,pFunc^.pTop); //OnOpStep1 Reg Collapse
2022-09-05 13:30:24 +00:00
if (i=0) then Break;
Result:=Result+i;
until false;
2022-09-07 18:06:19 +00:00
i:=EnumBlockOpForward(@OnOpStep2,pFunc^.pTop); //OnOpStep2 PostForward1
2022-05-31 07:17:14 +00:00
if (i=0) then Break;
Result:=Result+i;
until false;
2022-09-07 18:06:19 +00:00
i:=EnumBlockOpForward(@OnOpStep3,pFunc^.pTop); //OnOpStep3 PostForward2
2022-05-31 07:17:14 +00:00
if (i=0) then Break;
Result:=Result+i;
until false;
2022-09-05 13:30:24 +00:00
if data_layout then
begin
2022-09-07 18:06:19 +00:00
Result:=Result+PostDataLayoutAnalize1;
2022-09-05 13:30:24 +00:00
data_layout:=false;
end;
2022-09-07 18:06:19 +00:00
repeat //OnOpStep4 Volatile Reslove
2022-09-05 13:30:24 +00:00
i:=EnumBlockOpForward(@OnOpStep4,pFunc^.pTop);
if (i=0) then Break;
Result:=Result+i;
until false;
r4:=0;
2022-09-07 18:06:19 +00:00
repeat //OnOpStep5 Weak Reslove
2022-09-05 13:30:24 +00:00
i:=EnumBlockOpBackward(@OnOpStep5,pFunc^.pTop);
if (i=0) then Break;
r4:=r4+i;
until false;
if (r4=0) then Break;
Result:=Result+r4;
2022-05-31 07:17:14 +00:00
until false;
2022-09-07 18:06:19 +00:00
PrivateList.RemoveAllStore;
data_layout:=(Main=pFunc);
if data_layout then
begin
Result:=Result+PostDataLayoutAnalize2;
end;
2022-09-05 13:30:24 +00:00
//UpdateRegType OpLoad/OpStore
DataLayoutList.EnumChain(@OnChainUpdate);
PrivateList.Post;
2022-05-31 07:17:14 +00:00
2022-09-07 18:06:19 +00:00
repeat //OnOpStep6 Typecast
2022-09-05 13:30:24 +00:00
i:=EnumBlockOpBackward(@OnOpStep6,pFunc^.pTop);
2022-05-31 07:17:14 +00:00
if (i=0) then Break;
Result:=Result+i;
until false;
2022-09-07 18:06:19 +00:00
Result:=Result+EnumBlockOpBackward(@OnOpStep7,pFunc^.pTop); //OnOpStep7 Remove Lines
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
pFunc:=pFunc^.Prev;
2022-05-31 07:17:14 +00:00
end;
end;
2022-09-05 13:30:24 +00:00
function TSprvEmit_post.OnChainUpdate(node:PsrChain):Integer;
2022-05-31 07:17:14 +00:00
begin
Result:=0;
2022-09-05 13:30:24 +00:00
node^.UpdateRegType;
2022-05-31 07:17:14 +00:00
end;
2022-09-07 18:06:19 +00:00
function TSprvEmit_post.PostDataLayoutAnalize1:Integer;
2022-05-31 07:17:14 +00:00
begin
Result:=0;
2022-09-05 13:30:24 +00:00
DataLayoutList.AllocID;
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
Result:=Result+DataLayoutList.EnumChain(@OnChainField);
2022-09-07 18:06:19 +00:00
end;
function TSprvEmit_post.PostDataLayoutAnalize2:Integer;
begin
Result:=0;
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
BufferList.ApplyBufferType;
BufferList.AlignOffset;
BufferList.FillSpace;
BufferList.AllocID;
BufferList.EnumAllField(@OnFieldType);
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
Result:=Result+DataLayoutList.EnumChain(@OnChainAlloc);
2022-05-31 07:17:14 +00:00
end;
function TSprvEmit_post.FetchField(var pChain:PsrChain;dtype:TsrDataType):PsrField;
var
buf:PsrBuffer;
F:TFieldFetchValue;
2022-09-05 13:30:24 +00:00
_offset,_stride:PtrUint;
_count:PtrUint;
//ext:TsrChainExt;
//pNew:PsrChain;
2022-05-31 07:17:14 +00:00
fset_index:Boolean;
begin
_count:=0;
_stride:=0;
2022-09-05 13:30:24 +00:00
if (pChain^.pIndex<>nil) then
2022-05-31 07:17:14 +00:00
begin
//RuntimeArray
2022-11-05 14:48:13 +00:00
//Writeln('RA:',HexStr(pChain^.parent),':',pChain^.offset);
2022-09-05 13:30:24 +00:00
buf:=BufferList.Fetch(pChain^.parent,0);
2022-05-31 07:17:14 +00:00
repeat
2022-09-05 13:30:24 +00:00
_offset:=pChain^.offset;
F:=buf^.FTop.FetchRuntimeArray(_offset,pChain^.stride);
2022-05-31 07:17:14 +00:00
repeat
Case F.fValue of
frNotFit :Break;
frIdent :Exit(F.pField);
frVectorAsValue:Exit(F.pField);
frValueInVector:_offset:=_offset-F.pField^.offset;
frValueInArray :_offset:=_offset-F.pField^.offset;
end;
2022-09-05 13:30:24 +00:00
F:=F.pField^.FetchValue(_offset,pChain^.size,dtype);
2022-05-31 07:17:14 +00:00
until (F.fValue<>frNotFit);
if (F.fValue<>frNotFit) then Break;
2022-09-05 13:30:24 +00:00
buf:=BufferList.NextAlias(buf);
2022-05-31 07:17:14 +00:00
until false;
end else
begin
//Value/Vector
2022-11-05 14:48:13 +00:00
//Writeln('VV:',HexStr(pChain^.parent),':',pChain^.offset);
2022-09-05 13:30:24 +00:00
buf:=BufferList.Fetch(pChain^.parent,0);
2022-05-31 07:17:14 +00:00
fset_index:=False;
repeat
2022-09-05 13:30:24 +00:00
_offset:=pChain^.offset;
2022-05-31 07:17:14 +00:00
F.pField:=@buf^.FTop;
repeat
2022-09-05 13:30:24 +00:00
F:=F.pField^.FetchValue(_offset,pChain^.size,dtype);
2022-05-31 07:17:14 +00:00
Case F.fValue of
frNotFit :Break;
frIdent,
frVectorAsValue:
begin
if fset_index then
begin
2022-09-05 13:30:24 +00:00
Break;
{
2022-05-31 07:17:14 +00:00
Assert(pChain^.key.ext.pIndex=nil);
ext:=Default(TsrChainExt);
2022-09-05 13:30:24 +00:00
ext.pIndex:=NewReg_i(dtUint32,_count);
2022-05-31 07:17:14 +00:00
ext.stride:=_stride;
2022-09-05 13:30:24 +00:00
pNew:=pChain^.FParent^.Fetch(_offset,pChain^.key.size,@ext);
2022-05-31 07:17:14 +00:00
pNew^.read_count :=pChain^.read_count ;
pNew^.write_count:=pChain^.write_count;
pNew^.rSlot :=pChain^.rSlot ;
pChain^.read_count :=0;
pChain^.write_count:=0;
pChain^.rSlot :=Default(TsrRegSlot);
pChain:=pNew;
2022-09-05 13:30:24 +00:00
}
2022-05-31 07:17:14 +00:00
end;
Exit(F.pField);
end;
frValueInVector:_offset:=_offset-F.pField^.offset;
frValueInArray :
begin
Assert(not fset_index);
_offset:=_offset-F.pField^.offset;
_stride:=F.pField^.stride;
_count :=_offset div _stride;
_offset:=_offset mod _stride;
fset_index:=true;
end;
end;
until (F.fValue<>frNotFit);
if (F.fValue<>frNotFit) then Break;
2022-09-05 13:30:24 +00:00
buf:=BufferList.NextAlias(buf);
2022-05-31 07:17:14 +00:00
fset_index:=False;
until false;
end;
Result:=F.pField;
end;
function TSprvEmit_post.OnChainField(node:PsrChain):Integer;
var
pField:PsrField;
dtype:TsrDataType;
begin
Result:=1;
2022-09-05 13:30:24 +00:00
dtype:=node^.dtype;
2022-05-31 07:17:14 +00:00
//Writeln('OnChainsField:',dtype,':',node^.key.offset);
pField:=FetchField(node,dtype);
2022-09-05 13:30:24 +00:00
Assert(pField<>nil);
2022-05-31 07:17:14 +00:00
node^.pField:=pField;
if (pField^.dtype<>dtype) then
begin
2022-09-05 13:30:24 +00:00
node^.dtype:=pField^.dtype;
2022-05-31 07:17:14 +00:00
end;
2022-09-07 18:06:19 +00:00
//pField^.pBuffer^.TakeChain(node);
node^.pBuffer:=pField^.pBuffer;
2022-05-31 07:17:14 +00:00
end;
procedure TSprvEmit_post.OnFieldType(node:PsrField);
var
count:PtrUint;
2022-09-05 13:30:24 +00:00
items:PPsrType;
2022-05-31 07:17:14 +00:00
sType,pType:PsrType;
2022-09-05 13:30:24 +00:00
2022-05-31 07:17:14 +00:00
child:PsrField;
begin
if (node^.pType<>nil) then Exit;
if (node^.dtype in [dtTypeStruct,dtTypeArray,dtTypeRuntimeArray]) then
begin
if node^.IsStructNotUsed then
begin
child:=node^.First;
Assert(child<>nil);
Assert(child^.pType<>nil);
sType:=child^.pType;
end else
begin
count:=node^.FCount;
Assert(count<>0);
2022-09-05 13:30:24 +00:00
items:=Alloc(SizeOf(Pointer)*count);
2022-05-31 07:17:14 +00:00
count:=0;
child:=node^.First;
While (child<>nil) do
begin
Assert(child^.pType<>nil);
2022-09-05 13:30:24 +00:00
items[count]:=child^.pType;
2022-05-31 07:17:14 +00:00
Inc(count);
child:=node^.Next(child);
end;
2022-09-05 13:30:24 +00:00
if node^.IsTop then
begin
sType:=TypeList.InsertStruct(count,items,False,node^.GetSize); //unique
end else
begin
sType:=TypeList.FetchStruct (count,items,False,node^.GetSize);
end;
2022-05-31 07:17:14 +00:00
end;
Case node^.dtype of
dtTypeArray:
begin
2022-09-05 13:30:24 +00:00
count:=node^.GetSize div node^.stride;
pType:=TypeList.FetchArray(sType,count);
2022-05-31 07:17:14 +00:00
end;
dtTypeRuntimeArray:
begin
2022-09-05 13:30:24 +00:00
pType:=TypeList.FetchRuntimeArray(sType);
2022-05-31 07:17:14 +00:00
end;
else
begin
pType:=sType;
end;
end;
2022-11-15 12:54:47 +00:00
node^.sType:=sType;
2022-05-31 07:17:14 +00:00
node^.pType:=pType;
2022-09-05 13:30:24 +00:00
if node^.IsTop then
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
//Alloc Type Var
node^.pBuffer^.pType:=pType;
2022-05-31 07:17:14 +00:00
end;
end else
begin
2022-11-15 12:54:47 +00:00
node^.sType:=nil;
2022-09-05 13:30:24 +00:00
node^.pType:=TypeList.Fetch(node^.dtype);
2022-05-31 07:17:14 +00:00
end;
end;
function TSprvEmit_post.OnChainAlloc(node:PsrChain):Integer;
var
pLine:PspirvOp;
pIndex:PsrRegNode;
pReg:PsrRegNode;
pField:PsrField;
Parent:PsrField;
src:PsrVariable;
pParam:POpParamNode;
//dtype:TsrDataType;
begin
Result:=1;
2022-09-05 13:30:24 +00:00
pIndex:=RegDown(node^.pIndex);
2022-05-31 07:17:14 +00:00
if (pIndex=nil) or (pIndex^.is_const) then
begin
pLine:=init_line;
end else
begin
2022-09-05 13:30:24 +00:00
pLine:=node^.FirstLine;
2022-05-31 07:17:14 +00:00
Assert(pLine<>nil);
2022-09-05 13:30:24 +00:00
pLine:=pLine^.Prev;
2022-05-31 07:17:14 +00:00
Assert(pLine<>nil);
end;
pField:=node^.pField;
Assert(pField<>nil);
src:=pField^.pBuffer^.pVar;
Assert(src<>nil);
2022-09-05 13:30:24 +00:00
pLine:=OpAccessChain(pLine,pField^.pType,node,src);
2022-05-31 07:17:14 +00:00
//dtype:=node^.GetRegType;
//if (pField^.dtype<>dtype) then
//begin
// Writeln(pField^.dtype,'<>',dtype);
// Assert(false,'TODO');
//end;
2022-09-05 13:30:24 +00:00
pParam:=pLine^.ParamLast;
2022-05-31 07:17:14 +00:00
repeat
2022-09-05 13:30:24 +00:00
Parent:=pField^.pParent;
2022-05-31 07:17:14 +00:00
if (Parent<>nil) then
Case Parent^.dtype of
dtTypeStruct:
begin
2022-09-05 13:30:24 +00:00
pReg:=NewReg_i(dtUint32,pField^.FID,@pLine);
pLine^.AddParamAfter(pParam,pReg);
2022-05-31 07:17:14 +00:00
end;
dtTypeArray,
dtTypeRuntimeArray:
begin
if not Parent^.IsStructNotUsed then
begin
2022-09-05 13:30:24 +00:00
pReg:=NewReg_i(dtUint32,pField^.FID,@pLine);
pLine^.AddParamAfter(pParam,pReg);
2022-05-31 07:17:14 +00:00
end;
Assert(pIndex<>nil);
2022-09-05 13:30:24 +00:00
pLine^.AddParamAfter(pParam,pIndex);
2022-05-31 07:17:14 +00:00
end;
else
2022-09-05 13:30:24 +00:00
if Parent^.dtype.isVector then
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
pReg:=NewReg_i(dtUint32,pField^.FID,@pLine);
pLine^.AddParamAfter(pParam,pReg);
2022-05-31 07:17:14 +00:00
end;
end;
pField:=Parent;
until (pField=nil);
end;
function TSprvEmit_post.PostConstAnalize:Integer;
var
node:PsrConst;
begin
Result:=0;
2022-09-05 13:30:24 +00:00
node:=ConstList.FList.pTail;
2022-05-31 07:17:14 +00:00
While (node<>nil) do
begin
2022-09-05 13:30:24 +00:00
if (not node^.IsUsed) then
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
ConstList.FList.Remove(node); //remove?
2022-05-31 07:17:14 +00:00
Inc(Result);
end;
2022-09-05 13:30:24 +00:00
node:=node^.Prev;
2022-05-31 07:17:14 +00:00
end;
end;
function TSprvEmit_post.PostVariableAnalize:Integer;
var
node:PsrVariable;
begin
Result:=0;
2022-09-05 13:30:24 +00:00
node:=VariableList.FList.pTail;
2022-05-31 07:17:14 +00:00
While (node<>nil) do
begin
2022-09-05 13:30:24 +00:00
if (not node^.IsUsed) then
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
VariableList.FList.Remove(node); //remove?
2022-05-31 07:17:14 +00:00
Inc(Result);
end else
begin
2022-09-05 13:30:24 +00:00
node^.UpdateType(Self);
2022-05-31 07:17:14 +00:00
end;
2022-09-05 13:30:24 +00:00
node:=node^.Prev;
2022-05-31 07:17:14 +00:00
end;
end;
2022-09-05 13:30:24 +00:00
function TSprvEmit_post.PostTypeAnalize:Integer;
2022-05-31 07:17:14 +00:00
var
node:PsrType;
begin
Result:=0;
2022-09-05 13:30:24 +00:00
node:=TypeList.FList.pTail;
2022-05-31 07:17:14 +00:00
While (node<>nil) do
begin
2022-09-05 13:30:24 +00:00
if (not node^.IsUsed) then
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
TypeList.FList.Remove(node); //remove?
2022-05-31 07:17:14 +00:00
Inc(Result);
end;
2022-09-05 13:30:24 +00:00
node:=node^.Prev;
2022-05-31 07:17:14 +00:00
end;
end;
end.