mirror of https://github.com/red-prig/fpPS4.git
773 lines
15 KiB
Plaintext
773 lines
15 KiB
Plaintext
unit emit_print;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
sysutils,
|
|
spirv,
|
|
srNodes,
|
|
srTypes,
|
|
srConst,
|
|
srReg,
|
|
srLayout,
|
|
srVariable,
|
|
srOp,
|
|
srOpUtils,
|
|
srCap,
|
|
srRefId,
|
|
Half16,
|
|
SprvEmit;
|
|
|
|
type
|
|
TSprvEmit_print=object(TSprvEmit)
|
|
procedure Print;
|
|
procedure PrintCaps;
|
|
procedure PrintOpList(node:PspirvOp);
|
|
procedure PrintHeaderInfo;
|
|
procedure PrintTypes;
|
|
procedure PrintConst(node:PsrConst);
|
|
procedure PrintConst;
|
|
procedure PrintVariable;
|
|
procedure PrintFunc;
|
|
procedure PrintOp(node:PSpirvOp;print_offset:Boolean);
|
|
procedure PrintOpBlock(pBlock:PsrOpBlock);
|
|
end;
|
|
|
|
implementation
|
|
|
|
procedure TSprvEmit_print.Print;
|
|
begin
|
|
PrintCaps;
|
|
Writeln;
|
|
PrintHeaderInfo;
|
|
Writeln;
|
|
PrintTypes;
|
|
Writeln;
|
|
PrintConst;
|
|
Writeln;
|
|
PrintVariable;
|
|
PrintFunc;
|
|
end;
|
|
|
|
procedure PrintRefId(P:PsrRefId);
|
|
begin
|
|
Assert(P<>nil ,'PrintRefId$1');
|
|
Assert(P^.Alloc,'PrintRefId$2');
|
|
Write('%',P^.ID);
|
|
end;
|
|
|
|
procedure PrintConstId(P:PsrConst);
|
|
var
|
|
s:Single;
|
|
i:Int64;
|
|
u:QWORD;
|
|
begin
|
|
Assert(P<>nil ,'PrintConstId$1');
|
|
Assert(P^.ID.Alloc,'PrintConstId$2');
|
|
|
|
Case P^.key.dtype of
|
|
dtBool:
|
|
begin
|
|
Case P^.AsBool of
|
|
true :Write('%true');
|
|
False:Write('%false');
|
|
end;
|
|
end;
|
|
|
|
dtHalf16:
|
|
begin
|
|
s:=Single(P^.AsHalf16);
|
|
i:=Trunc(s);
|
|
if (s=i) then
|
|
begin
|
|
Case i of
|
|
0..99:Write('%ch',i);
|
|
else
|
|
Write('%c',P^.ID.ID);
|
|
end;
|
|
end else
|
|
begin
|
|
Write('%c',P^.ID.ID);
|
|
end;
|
|
end;
|
|
|
|
dtFloat32:
|
|
begin
|
|
s:=P^.AsFloat32;
|
|
i:=Trunc(s);
|
|
if (s=i) then
|
|
begin
|
|
Case i of
|
|
0..99:Write('%cf',i);
|
|
-9..-1:Write('%cfm',abs(i));
|
|
else
|
|
Write('%c',P^.ID.ID);
|
|
end;
|
|
end else
|
|
begin
|
|
Write('%c',P^.ID.ID);
|
|
end;
|
|
end;
|
|
|
|
dtInt32 :
|
|
begin
|
|
i:=P^.AsInt;
|
|
Case i of
|
|
0..99:Write('%ci',i);
|
|
-9..-1:Write('%cim',abs(i));
|
|
else
|
|
Write('%c',P^.ID.ID);
|
|
end;
|
|
end;
|
|
|
|
dtUint32:
|
|
begin
|
|
u:=P^.AsUint;
|
|
Case u of
|
|
0..99:Write('%cu',u);
|
|
else
|
|
Write('%c',P^.ID.ID);
|
|
end;
|
|
end;
|
|
|
|
else
|
|
Write('%c',P^.ID.ID);
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure PrintVar(P:PsrVariable);
|
|
Var
|
|
n:RawByteString;
|
|
begin
|
|
Assert(P<>nil ,'PrintVar$1');
|
|
Assert(P^.ID.Alloc,'PrintVar$2');
|
|
if (P^.pSource.pData<>nil) then
|
|
begin
|
|
n:=P^.GetName;
|
|
if (n<>'') then
|
|
begin
|
|
Write('%',n);
|
|
end else
|
|
begin
|
|
Write('%v',P^.ID.ID);
|
|
end;
|
|
end else
|
|
begin
|
|
Write('%v',P^.ID.ID);
|
|
end;
|
|
end;
|
|
|
|
function type_get_base_name(dtype:TsrDataType):RawByteString;
|
|
begin
|
|
Result:='';
|
|
case dtype of
|
|
|
|
dtBool :Result:='bool';
|
|
|
|
dtFloat32 :Result:='float';
|
|
dtHalf16 :Result:='half';
|
|
|
|
dtInt8 :Result:='int8';
|
|
dtUint8 :Result:='uint8';
|
|
|
|
dtInt16 :Result:='int16';
|
|
dtUint16 :Result:='uint16';
|
|
|
|
dtInt32 :Result:='int';
|
|
dtUint32 :Result:='uint';
|
|
|
|
dtInt64 :Result:='int64';
|
|
dtUint64 :Result:='uint64';
|
|
|
|
//Composite types
|
|
dtVec2b :Result:='bvec2';
|
|
dtVec3b :Result:='bvec3';
|
|
dtVec4b :Result:='bvec4';
|
|
|
|
dtStruct2u :Result:='rec2u';
|
|
|
|
dtVec2u8 :Result:='u8vec2';
|
|
dtVec4u8 :Result:='u8vec4';
|
|
|
|
dtVec2i8 :Result:='i8vec2';
|
|
dtVec4i8 :Result:='i8vec4';
|
|
|
|
dtVec2u16 :Result:='u16vec2';
|
|
dtVec4u16 :Result:='u16vec4';
|
|
|
|
dtVec2i16 :Result:='i16vec2';
|
|
dtVec4i16 :Result:='i16vec4';
|
|
|
|
dtVec2u :Result:='uvec2';
|
|
dtVec3u :Result:='uvec3';
|
|
dtVec4u :Result:='uvec4';
|
|
|
|
dtVec2i :Result:='ivec2';
|
|
dtVec3i :Result:='ivec3';
|
|
dtVec4i :Result:='ivec4';
|
|
|
|
dtVec2f :Result:='vec2';
|
|
dtVec3f :Result:='vec3';
|
|
dtVec4f :Result:='vec4';
|
|
|
|
dtVec2h :Result:='hvec2';
|
|
dtVec4h :Result:='hvec4';
|
|
|
|
dtTypeVoid :Result:='void';
|
|
|
|
dtTypeSampler:Result:='samp';
|
|
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
function type_get_base_name(node:PsrType):RawByteString;
|
|
var
|
|
n:PsrType;
|
|
begin
|
|
Result:='';
|
|
case node^.dtype of
|
|
{dtTypeImage:
|
|
begin
|
|
if DWORD(node^.key.ext.image)=DWORD(ExtImgBuf) then
|
|
begin
|
|
Result:='buf';
|
|
end else
|
|
if DWORD(node^.key.ext.image)=DWORD(ExtImage2D) then
|
|
begin
|
|
Result:='img2D';
|
|
end;
|
|
end;}
|
|
dtTypeSampledImage:
|
|
begin
|
|
if (node^.key.count<>1) then Exit;
|
|
n:=node^.GetCompItem(0);
|
|
Result:=type_get_base_name(n);
|
|
if (Result='') then Exit;
|
|
Result:='sm'+Result;
|
|
end;
|
|
dtTypeArray:
|
|
begin
|
|
n:=node^.GetCompItem(0);
|
|
Result:=type_get_base_name(n);
|
|
if (Result='') then Exit;
|
|
Result:='ar'+IntToStr(node^.key.ext.array_count)+Result;
|
|
end;
|
|
dtTypeRuntimeArray:
|
|
begin
|
|
n:=node^.GetCompItem(0);
|
|
Result:=type_get_base_name(n);
|
|
if (Result='') then Exit;
|
|
Result:='ra'+Result;
|
|
end;
|
|
dtTypeStruct:
|
|
begin
|
|
if (node^.key.count<>1) then Exit;
|
|
n:=node^.GetCompItem(0);
|
|
Result:=type_get_base_name(n);
|
|
if (Result='') then Exit;
|
|
Result:='st'+Result;
|
|
end;
|
|
dtTypeFunction:
|
|
begin
|
|
if (node^.key.count<>1) then Exit;
|
|
n:=node^.GetCompItem(0);
|
|
Result:=type_get_base_name(n);
|
|
if (Result='') then Exit;
|
|
Result:='fn'+Result;
|
|
end;
|
|
else
|
|
Result:=type_get_base_name(node^.dtype);
|
|
end;
|
|
end;
|
|
|
|
procedure PrintTypeId(node:PsrType);
|
|
var
|
|
s:RawByteString;
|
|
n:PsrType;
|
|
begin
|
|
case node^.dtype of
|
|
dtTypePointer:
|
|
begin
|
|
n:=node^.GetCompItem(0);
|
|
S:=type_get_base_name(n);
|
|
if (S='') then
|
|
PrintRefId(@node^.ID)
|
|
else
|
|
begin
|
|
S:='p'+S;
|
|
Case node^.key.ext.storage_class of
|
|
StorageClass.UniformConstant :S:=S+'_uc';
|
|
StorageClass.Input :S:=S+'_in';
|
|
StorageClass.Uniform :S:=S+'_uf';
|
|
StorageClass.Output :S:=S+'_ot';
|
|
StorageClass.Workgroup :S:=S+'_wg';
|
|
StorageClass.CrossWorkgroup :S:=S+'_cw';
|
|
StorageClass.Private_ :S:=S+'_pv';
|
|
StorageClass.Function_ :S:=S+'_fc';
|
|
StorageClass.PushConstant :S:=S+'_pc';
|
|
StorageClass.Image :S:=S+'_im';
|
|
StorageClass.StorageBuffer :S:=S+'_sb';
|
|
else
|
|
S:='';
|
|
end;
|
|
if (S='') then
|
|
PrintRefId(@node^.ID)
|
|
else
|
|
Write('%',S);
|
|
end;
|
|
end;
|
|
else
|
|
begin
|
|
S:=type_get_base_name(node);
|
|
if (S='') then
|
|
PrintRefId(@node^.ID)
|
|
else
|
|
Write('%',S);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure PrintChain(P:PsrChain);
|
|
begin
|
|
Assert(P<>nil ,'PrintChain$1');
|
|
Assert(P^.ID.Alloc,'PrintChain$2');
|
|
Write('%ac',P^.ID.ID);
|
|
end;
|
|
|
|
procedure PrintReg(P:PsrRegNode);
|
|
begin
|
|
Assert(P<>nil,'PrintReg$1');
|
|
Case P^.pWriter.ntype of
|
|
ntConst:
|
|
begin
|
|
PrintConstId(P^.pWriter.pData);
|
|
end;
|
|
ntOp:
|
|
begin
|
|
if (not P^.ID.Alloc) then Assert(false,'PrintReg$2');
|
|
Write('%r',P^.ID.ID);
|
|
//Write('(',P^.read_count,')');
|
|
end;
|
|
else
|
|
Assert(false,'PrintReg$3');
|
|
end;
|
|
end;
|
|
|
|
procedure TSprvEmit_print.PrintCaps;
|
|
var
|
|
node:PSpirvCap;
|
|
begin
|
|
node:=FSpirvCaps.First;
|
|
While (node<>nil) do
|
|
begin
|
|
Writeln(Op.GetStr(Op.OpCapability),' ',Capability.GetStr(node^.ID));
|
|
node:=FSpirvCaps.Next(node);
|
|
end;
|
|
end;
|
|
|
|
procedure TSprvEmit_print.PrintOpList(node:PspirvOp);
|
|
begin
|
|
While (node<>nil) do
|
|
begin
|
|
PrintOp(node,false);
|
|
node:=node^.pNext;
|
|
end;
|
|
end;
|
|
|
|
procedure TSprvEmit_print.PrintHeaderInfo;
|
|
begin
|
|
PrintOpList(FHeader.pHead);
|
|
Writeln;
|
|
PrintOpList(FDebugInfo.pHead);
|
|
if (FDebugInfo.pHead<>nil) then Writeln;
|
|
PrintOpList(FDecorates.pHead);
|
|
end;
|
|
|
|
function Dim_GetStr(w:Word):RawByteString;
|
|
begin
|
|
Result:='';
|
|
Case w of
|
|
Dim.Dim1D :Result:='1D';
|
|
Dim.Dim2D :Result:='2D';
|
|
Dim.Dim3D :Result:='3D';
|
|
Dim.Cube :Result:='Cube';
|
|
Dim.Rect :Result:='Rect';
|
|
Dim.Buffer :Result:='Buffer';
|
|
Dim.SubpassData:Result:='SubpassData';
|
|
else
|
|
Assert(False,'Dim_GetStr');
|
|
end;
|
|
end;
|
|
|
|
procedure TSprvEmit_print.PrintTypes;
|
|
var
|
|
node:PsrType;
|
|
pConst:PsrConst;
|
|
i:dword;
|
|
ie:Boolean;
|
|
begin
|
|
node:=FSpirvTypes.FList.pHead;
|
|
While (node<>nil) do
|
|
begin
|
|
ie:=True;
|
|
|
|
pConst:=nil;
|
|
case node^.dtype of
|
|
dtTypeArray:
|
|
begin
|
|
//find a const
|
|
pConst:=FConsts.Fetchi(dtUInt32,node^.key.ext.array_count);
|
|
PrintConst(pConst);
|
|
end;
|
|
else;
|
|
end;
|
|
|
|
PrintTypeId(node);
|
|
Write(' = ');
|
|
|
|
Write(Op.GetStr(node^.key.OpId));
|
|
|
|
case node^.key.OpId of
|
|
|
|
Op.OpTypeFloat:
|
|
begin
|
|
Write(' ',node^.key.ext.float_size);
|
|
end;
|
|
|
|
Op.OpTypeInt:
|
|
begin
|
|
Write(' ',node^.key.ext.int_size);
|
|
Write(' ',node^.key.ext.int_sign);
|
|
end;
|
|
|
|
Op.OpTypeVector:
|
|
begin
|
|
ie:=False;
|
|
Write(' ');
|
|
PrintTypeId(node^.GetCompItem(0));
|
|
Write(' ',node^.key.ext.array_count);
|
|
end;
|
|
|
|
Op.OpTypePointer:
|
|
begin
|
|
Write(' ',StorageClass.GetStr(node^.key.ext.Storage_Class));
|
|
end;
|
|
|
|
Op.OpTypeArray:
|
|
begin
|
|
ie:=False;
|
|
Write(' ');
|
|
PrintTypeId(node^.GetCompItem(0));
|
|
Write(' ');
|
|
PrintConstId(pConst);
|
|
end;
|
|
|
|
Op.OpTypeRuntimeArray:
|
|
begin
|
|
ie:=False;
|
|
Write(' ');
|
|
PrintTypeId(node^.GetCompItem(0));
|
|
end;
|
|
|
|
Op.OpTypeImage:
|
|
begin
|
|
ie:=False;
|
|
Write(' ');
|
|
PrintTypeId(node^.GetCompItem(0));
|
|
With node^.key.ext.image do
|
|
Write(' ',
|
|
Dim_GetStr(Dim),' ',
|
|
Depth,' ',
|
|
Arrayed,' ',
|
|
MS,' ',
|
|
Sampled,' ',
|
|
Spirv.ImageFormat.GetStr(Format));
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
if ie then
|
|
if (node^.key.count<>0) then
|
|
begin
|
|
For i:=0 to node^.key.count-1 do
|
|
begin
|
|
Write(' ');
|
|
PrintTypeId(node^.GetCompItem(i));
|
|
end;
|
|
end;
|
|
|
|
Writeln;
|
|
|
|
node:=node^.pNext;
|
|
end;
|
|
end;
|
|
|
|
const
|
|
DefaultFormatSettings : TFormatSettings = (
|
|
CurrencyFormat: 1;
|
|
NegCurrFormat: 5;
|
|
ThousandSeparator: ',';
|
|
DecimalSeparator: '.';
|
|
CurrencyDecimals: 2;
|
|
DateSeparator: '-';
|
|
TimeSeparator: ':';
|
|
ListSeparator: ',';
|
|
CurrencyString: '$';
|
|
ShortDateFormat: 'd/m/y';
|
|
LongDateFormat: 'dd" "mmmm" "yyyy';
|
|
TimeAMString: 'AM';
|
|
TimePMString: 'PM';
|
|
ShortTimeFormat: 'hh:nn';
|
|
LongTimeFormat: 'hh:nn:ss';
|
|
ShortMonthNames: ('Jan','Feb','Mar','Apr','May','Jun',
|
|
'Jul','Aug','Sep','Oct','Nov','Dec');
|
|
LongMonthNames: ('January','February','March','April','May','June',
|
|
'July','August','September','October','November','December');
|
|
ShortDayNames: ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
|
|
LongDayNames: ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
|
|
TwoDigitYearCenturyWindow: 50;
|
|
);
|
|
|
|
procedure TSprvEmit_print.PrintConst(node:PsrConst);
|
|
var
|
|
i:dword;
|
|
begin
|
|
PrintConstId(node);
|
|
Write(' = ');
|
|
|
|
if (node^.key.count=0) then
|
|
begin
|
|
if (node^.key.dtype=dtBool) then
|
|
begin
|
|
Case node^.AsBool of
|
|
True :Write(Op.GetStr(Op.OpConstantTrue));
|
|
False:Write(Op.GetStr(Op.OpConstantFalse));
|
|
end;
|
|
Write(' ');
|
|
PrintTypeId(node^.pType);
|
|
end else
|
|
begin
|
|
Write(Op.GetStr(Op.OpConstant));
|
|
Write(' ');
|
|
PrintTypeId(node^.pType);
|
|
Write(' ');
|
|
case node^.key.dtype of
|
|
dtFloat32:Write(FloatToStr(node^.AsFloat32,DefaultFormatSettings));
|
|
dtHalf16 :Write(FloatToStr(Single(node^.AsHalf16),DefaultFormatSettings));
|
|
dtInt32 :Write(node^.AsInt);
|
|
dtUint32 :Write(node^.AsUint);
|
|
dtInt64 :Write(node^.AsInt64);
|
|
dtUint64 :Write(node^.AsUint64);
|
|
else
|
|
Assert(false,'PrintConst');
|
|
end;
|
|
end;
|
|
end else
|
|
begin
|
|
Write(Op.GetStr(Op.OpConstantComposite));
|
|
Write(' ');
|
|
PrintTypeId(node^.pType);
|
|
For i:=0 to node^.key.count-1 do
|
|
begin
|
|
Write(' ');
|
|
PrintConstId(node^.GetCompItem(i));
|
|
end;
|
|
end;
|
|
|
|
Writeln;
|
|
end;
|
|
|
|
procedure TSprvEmit_print.PrintConst;
|
|
var
|
|
node:PsrConst;
|
|
begin
|
|
node:=FConsts.FList.pHead;
|
|
While (node<>nil) do
|
|
begin
|
|
|
|
//if not node^.is_first then
|
|
//begin
|
|
if (node^.key.dtype=dtUnknow) then
|
|
begin
|
|
Write('; ');
|
|
PrintConstId(node);
|
|
Writeln(' = dtUnknow: read_count=',node^.read_count,' value=',node^.Data);
|
|
end else
|
|
//Assert(node^.dtype<>dtUnknow);
|
|
PrintConst(node);
|
|
//end;
|
|
|
|
node:=node^.pNext;
|
|
end;
|
|
end;
|
|
|
|
procedure TSprvEmit_print.PrintVariable;
|
|
var
|
|
node:PsrVariable;
|
|
begin
|
|
node:=FVariables.pHead;
|
|
While (node<>nil) do
|
|
begin
|
|
if (node^.pType<>nil) then
|
|
begin
|
|
PrintVar(node);
|
|
Write(' = ',Op.GetStr(Op.OpVariable),' ');
|
|
PrintTypeId(node^.pType);
|
|
Writeln(' ',StorageClass.GetStr(node^.GetStorageClass));
|
|
end;
|
|
node:=node^.pNext;
|
|
end;
|
|
end;
|
|
|
|
procedure PrintFuncId(P:PSpirvFunc);
|
|
begin
|
|
Assert(P<>nil,'PrintFuncId');
|
|
if (P^.name<>'') then
|
|
begin
|
|
Write('%',P^.name);
|
|
end else
|
|
begin
|
|
PrintRefId(@P^.ID);
|
|
end;
|
|
end;
|
|
|
|
procedure PrintOpParamSingle(const Param:TOpParamSingle);
|
|
begin
|
|
Assert(Param.pData<>nil,'PrintOpParamSingle$1');
|
|
Case Param.ntype of
|
|
ntFunc :PrintFuncId(Param.pData);
|
|
ntRefId:PrintRefId(Param.pData);
|
|
ntType :PrintTypeId(Param.pData);
|
|
ntReg :PrintReg(Param.pData);
|
|
ntVar :PrintVar(Param.pData);
|
|
ntChain:PrintChain(Param.pData);
|
|
ntConst:PrintConstId(Param.pData);
|
|
else
|
|
Assert(false,'PrintOpParamSingle$2');
|
|
end;
|
|
end;
|
|
|
|
procedure PrintOpParamNode(node:POpParamNode);
|
|
begin
|
|
Case node^.ntype of
|
|
ntLiteral:
|
|
begin
|
|
if StrLen(@node^.name)=0 then
|
|
begin
|
|
Write(node^.Value);
|
|
end else
|
|
begin
|
|
Write(PChar(@node^.name));
|
|
end;
|
|
end;
|
|
ntString:
|
|
begin
|
|
Write('"',PChar(@node^.name),'"');
|
|
end;
|
|
else
|
|
begin
|
|
PrintOpParamSingle(node^.AsParam);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TSprvEmit_print.PrintFunc;
|
|
var
|
|
pFunc:PSpirvFunc;
|
|
begin
|
|
pFunc:=FSpirvFuncs.FList.pHead;
|
|
While (pFunc<>nil) do
|
|
begin
|
|
Writeln;
|
|
PrintOpBlock(@pFunc^.FTop);
|
|
pFunc:=pFunc^.pNext;
|
|
end;
|
|
end;
|
|
|
|
procedure TSprvEmit_print.PrintOp(node:PSpirvOp;print_offset:Boolean);
|
|
var
|
|
Param:POpParamNode;
|
|
Info:Op.TOpInfo;
|
|
begin
|
|
if (node=nil) then Exit;
|
|
|
|
Info:=Op.GetInfo(node^.OpId);
|
|
|
|
if Info.result then //dst
|
|
begin
|
|
Assert(node^.dst.ntype<>ntUnknow,'PrintOp$1');
|
|
Assert(node^.dst.pData<>nil,'PrintOp$2');
|
|
PrintOpParamSingle(node^.dst);
|
|
Write(' = ');
|
|
Write(Op.GetStr(node^.OpId));
|
|
end else
|
|
begin //no dst
|
|
Write(Op.GetStr(node^.OpId));
|
|
if (node^.dst.ntype<>ntUnknow) then
|
|
begin
|
|
Assert(node^.dst.pData<>nil,'PrintOp$3');
|
|
Write(' ');
|
|
PrintOpParamSingle(node^.dst);
|
|
end;
|
|
end;
|
|
|
|
if Info.rstype then //dst type
|
|
begin
|
|
Assert(node^.dst_type<>nil,'PrintOp$4');
|
|
Write(' ');
|
|
PrintTypeId(node^.dst_type);
|
|
end;
|
|
|
|
Param:=node^.pParam.pHead;
|
|
While (Param<>nil) do
|
|
begin
|
|
Write(' ');
|
|
PrintOpParamNode(Param);
|
|
Param:=Param^.pNext;
|
|
end;
|
|
|
|
if (node^.OpId=Op.OpLabel) then
|
|
begin
|
|
print_offset:=true;
|
|
end;
|
|
|
|
Case print_offset of
|
|
True :Writeln(' ;0x',HexStr(Node^.Adr.Offdw*4,4));
|
|
False:Writeln;
|
|
end;
|
|
end;
|
|
|
|
procedure TSprvEmit_print.PrintOpBlock(pBlock:PsrOpBlock);
|
|
var
|
|
node:PSpirvOp;
|
|
begin
|
|
if (pBlock=nil) then Exit;
|
|
node:=pBlock^.pHead;
|
|
While (node<>nil) do
|
|
begin
|
|
|
|
if (node^.OpId=OpBlock) then
|
|
begin
|
|
if (node^.dst.ntype=ntBlock) then
|
|
begin
|
|
PrintOpBlock(node^.dst.pData);
|
|
end;
|
|
end else
|
|
begin
|
|
Write(Space(pBlock^.FLevel));
|
|
PrintOp(node,false);
|
|
end;
|
|
|
|
node:=node^.pNext;
|
|
end;
|
|
end;
|
|
|
|
|
|
end.
|
|
|