FPPS4/spirv/emit_print.pas

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.