Files
gtk/gsk/spirv.js
Benjamin Otte 38a255d132 gskspv: Deal with ImageOperands
ImageOperands are followed by an optional list of arguments for those
arguments.
2017-10-30 02:58:03 +01:00

758 lines
24 KiB
JavaScript

function usage()
{
print ("usage: gjs spirv.js enums|functions SPIRV_GRAMMAR_FILE");
}
if (ARGV.length != 2)
{
usage();
throw new SyntaxError ("Script needs 2 arguments but got " + ARGV.length);
}
var command = ARGV[0];
var extinst = "";
if (ARGV[0].indexOf("-") > 0)
{
extinst = ARGV[0].substr (0, ARGV[0].indexOf("-"));
command = ARGV[0].substr (extinst.length + 1);
}
var contents = imports.gi.Gio.File.new_for_path(ARGV[1]).load_contents(null);
var spirv = JSON.parse(contents[1]);
if (!String.prototype.format) {
String.prototype.format = function() {
var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined'
? args[number]
: match
;
});
};
}
function all_lower(s)
{
let result = "";
let needs_underscore = false;
let had_caps = false;
for (let i = 0; i < s.length; i++)
{
if (s[i] >= 'a' && s[i] <= 'z')
{
needs_underscore = true;
had_caps = false;
result += s[i];
}
else if (s[i] >= "A" && s[i] <= "Z")
{
if (needs_underscore)
result += "_";
else if (s[i+1] && s[i+1] >= "a" && s[i+1] <= "z" && had_caps)
result += "_";
needs_underscore = false;
had_caps = true;
result += s[i].toLowerCase();
}
else if (s[i] >= '0' && s[i] <= '9')
{
needs_underscore = true
had_caps = false;
result += s[i]
}
else
{
needs_underscore = false
had_caps = false;
result += "_";
}
}
return result;
}
function all_upper(s)
{
return all_lower(s).toUpperCase();
}
function sanitize_name (name)
{
name = name.substr(1);
return all_lower(name.substr(0, name.indexOf("'")));
}
var SpecialTypes = {
"OpVariable": { "result_type": "IdResultPointerType" },
"OpImageTexelPointer": { "result_type": "IdResultPointerType" },
"OpAccessChain": { "result_type": "IdResultPointerType" },
"OpInBoundsAccessChain": { "result_type": "IdResultPointerType" },
"OpConvertUToPtr": { "result_type": "IdResultPointerType" },
"OpPtrCastToGeneric": { "result_type": "IdResultPointerType" },
"OpGenericCastToPtr": { "result_type": "IdResultPointerType" },
"OpGenericCastToPtrExplicit": { "result_type": "IdResultPointerType" },
"OpFunctionParameter": { "result_type": "IdRef" },
"OpLabel": { "result": "IdRef" },
"OpImage": { "result_type": "IdRef" }
};
var ExtraOperands = {
"OpDecorate": [ { "kind" : "LiteralContextDependentNumber", "name" : "'Value'" } ],
"OpMemberDecorate": [ { "kind" : "LiteralContextDependentNumber", "name" : "'Value'" } ]
};
/* maps opcodes to section in file they appear in */
var Sections = {
"OpNop": "",
"OpUndef": "",
"OpSourceContinued": "",
"OpSource": "debug",
"OpSourceExtension": "debug",
"OpName": "debug",
"OpMemberName": "debug",
"OpString": "",
"OpLine": "",
"OpExtension": "header",
"OpExtInstImport": "header",
"OpExtInst": "",
"OpMemoryModel": "header",
"OpEntryPoint": "header",
"OpExecutionMode": "header",
"OpCapability": "header",
"OpTypeVoid": "define",
"OpTypeBool": "define",
"OpTypeInt": "define",
"OpTypeFloat": "define",
"OpTypeVector": "define",
"OpTypeMatrix": "define",
"OpTypeImage": "define",
"OpTypeSampler": "define",
"OpTypeSampledImage": "define",
"OpTypeArray": "define",
"OpTypeRuntimeArray": "define",
"OpTypeStruct": "define",
"OpTypeOpaque": "define",
"OpTypePointer": "define",
"OpTypeFunction": "define",
"OpTypeEvent": "define",
"OpTypeDeviceEvent": "define",
"OpTypeReserveId": "define",
"OpTypeQueue": "define",
"OpTypePipe": "define",
"OpTypeForwardPointer": "define",
"OpConstantTrue": "define",
"OpConstantFalse": "define",
"OpConstant": "define",
"OpConstantComposite": "define",
"OpConstantSampler": "define",
"OpConstantNull": "define",
"OpSpecConstantTrue": "define",
"OpSpecConstantFalse": "define",
"OpSpecConstant": "define",
"OpSpecConstantComposite": "define",
"OpSpecConstantOp": "define",
"OpFunction": "declare",
"OpFunctionParameter": "declare",
"OpFunctionEnd": "code",
"OpFunctionCall": "code",
"OpVariable": "",
"OpImageTexelPointer": "code",
"OpLoad": "code",
"OpStore": "code",
"OpCopyMemory": "code",
"OpCopyMemorySized": "code",
"OpAccessChain": "code",
"OpInBoundsAccessChain": "code",
"OpPtrAccessChain": "code",
"OpArrayLength": "code",
"OpGenericPtrMemSemantics": "",
"OpInBoundsPtrAccessChain": "code",
"OpDecorate": "decorate",
"OpMemberDecorate": "decorate",
"OpDecorationGroup": "decorate",
"OpGroupDecorate": "decorate",
"OpGroupMemberDecorate": "decorate",
"OpVectorExtractDynamic": "code",
"OpVectorInsertDynamic": "code",
"OpVectorShuffle": "code",
"OpCompositeConstruct": "code",
"OpCompositeExtract": "code",
"OpCompositeInsert": "code",
"OpCopyObject": "",
"OpTranspose": "code",
"OpSampledImage": "",
"OpImageSampleImplicitLod": "code",
"OpImageSampleExplicitLod": "code",
"OpImageSampleDrefImplicitLod": "code",
"OpImageSampleDrefExplicitLod": "code",
"OpImageSampleProjImplicitLod": "code",
"OpImageSampleProjExplicitLod": "code",
"OpImageSampleProjDrefImplicitLod": "code",
"OpImageSampleProjDrefExplicitLod": "code",
"OpImageFetch": "code",
"OpImageGather": "code",
"OpImageDrefGather": "code",
"OpImageRead": "code",
"OpImageWrite": "code",
"OpImage": "code",
"OpImageQueryFormat": "code",
"OpImageQueryOrder": "code",
"OpImageQuerySizeLod": "code",
"OpImageQuerySize": "code",
"OpImageQueryLod": "code",
"OpImageQueryLevels": "code",
"OpImageQuerySamples": "code",
"OpConvertFToU": "code",
"OpConvertFToS": "code",
"OpConvertSToF": "code",
"OpConvertUToF": "code",
"OpUConvert": "code",
"OpSConvert": "code",
"OpFConvert": "code",
"OpQuantizeToF16": "code",
"OpConvertPtrToU": "code",
"OpSatConvertSToU": "code",
"OpSatConvertUToS": "code",
"OpConvertUToPtr": "code",
"OpPtrCastToGeneric": "code",
"OpGenericCastToPtr": "code",
"OpGenericCastToPtrExplicit": "code",
"OpBitcast": "code",
"OpSNegate": "code",
"OpFNegate": "code",
"OpIAdd": "code",
"OpFAdd": "code",
"OpISub": "code",
"OpFSub": "code",
"OpIMul": "code",
"OpFMul": "code",
"OpUDiv": "code",
"OpSDiv": "code",
"OpFDiv": "code",
"OpUMod": "code",
"OpSRem": "code",
"OpSMod": "code",
"OpFRem": "code",
"OpFMod": "code",
"OpVectorTimesScalar": "code",
"OpMatrixTimesScalar": "code",
"OpVectorTimesMatrix": "code",
"OpMatrixTimesVector": "code",
"OpMatrixTimesMatrix": "code",
"OpOuterProduct": "code",
"OpDot": "code",
"OpIAddCarry": "code",
"OpISubBorrow": "code",
"OpUMulExtended": "code",
"OpSMulExtended": "code",
"OpAny": "code",
"OpAll": "code",
"OpIsNan": "code",
"OpIsInf": "code",
"OpIsFinite": "code",
"OpIsNormal": "code",
"OpSignBitSet": "code",
"OpLessOrGreater": "code",
"OpOrdered": "code",
"OpUnordered": "code",
"OpLogicalEqual": "code",
"OpLogicalNotEqual": "code",
"OpLogicalOr": "code",
"OpLogicalAnd": "code",
"OpLogicalNot": "code",
"OpSelect": "code",
"OpIEqual": "code",
"OpINotEqual": "code",
"OpUGreaterThan": "code",
"OpSGreaterThan": "code",
"OpUGreaterThanEqual": "code",
"OpSGreaterThanEqual": "code",
"OpULessThan": "code",
"OpSLessThan": "code",
"OpULessThanEqual": "code",
"OpSLessThanEqual": "code",
"OpFOrdEqual": "code",
"OpFUnordEqual": "code",
"OpFOrdNotEqual": "code",
"OpFUnordNotEqual": "code",
"OpFOrdLessThan": "code",
"OpFUnordLessThan": "code",
"OpFOrdGreaterThan": "code",
"OpFUnordGreaterThan": "code",
"OpFOrdLessThanEqual": "code",
"OpFUnordLessThanEqual": "code",
"OpFOrdGreaterThanEqual": "code",
"OpFUnordGreaterThanEqual": "code",
"OpShiftRightLogical": "code",
"OpShiftRightArithmetic": "code",
"OpShiftLeftLogical": "code",
"OpBitwiseOr": "code",
"OpBitwiseXor": "code",
"OpBitwiseAnd": "code",
"OpNot": "code",
"OpBitFieldInsert": "code",
"OpBitFieldSExtract": "code",
"OpBitFieldUExtract": "code",
"OpBitReverse": "code",
"OpBitCount": "code",
"OpDPdx": "code",
"OpDPdy": "code",
"OpFwidth": "code",
"OpDPdxFine": "code",
"OpDPdyFine": "code",
"OpFwidthFine": "code",
"OpDPdxCoarse": "code",
"OpDPdyCoarse": "code",
"OpFwidthCoarse": "code",
"OpEmitVertex": "code",
"OpEndPrimitive": "code",
"OpEmitStreamVertex": "code",
"OpEndStreamPrimitive": "code",
"OpControlBarrier": "code",
"OpMemoryBarrier": "code",
"OpAtomicLoad": "code",
"OpAtomicStore": "code",
"OpAtomicExchange": "code",
"OpAtomicCompareExchange": "code",
"OpAtomicCompareExchangeWeak": "code",
"OpAtomicIIncrement": "code",
"OpAtomicIDecrement": "code",
"OpAtomicIAdd": "code",
"OpAtomicISub": "code",
"OpAtomicSMin": "code",
"OpAtomicUMin": "code",
"OpAtomicSMax": "code",
"OpAtomicUMax": "code",
"OpAtomicAnd": "code",
"OpAtomicOr": "code",
"OpAtomicXor": "code",
"OpPhi": "code",
"OpLoopMerge": "code",
"OpSelectionMerge": "code",
"OpLabel": "",
"OpBranch": "code",
"OpBranchConditional": "code",
"OpSwitch": "code",
"OpKill": "code",
"OpReturn": "code",
"OpReturnValue": "code",
"OpUnreachable": "",
"OpLifetimeStart": "",
"OpLifetimeStop": "",
"OpGroupAsyncCopy": "",
"OpGroupWaitEvents": "",
"OpGroupAll": "",
"OpGroupAny": "",
"OpGroupBroadcast": "",
"OpGroupIAdd": "",
"OpGroupFAdd": "",
"OpGroupFMin": "",
"OpGroupUMin": "",
"OpGroupSMin": "",
"OpGroupFMax": "",
"OpGroupUMax": "",
"OpGroupSMax": "",
"OpReadPipe": "",
"OpWritePipe": "",
"OpReservedReadPipe": "",
"OpReservedWritePipe": "",
"OpReserveReadPipePackets": "",
"OpReserveWritePipePackets": "",
"OpCommitReadPipe": "",
"OpCommitWritePipe": "",
"OpIsValidReserveId": "",
"OpGetNumPipePackets": "",
"OpGetMaxPipePackets": "",
"OpGroupReserveReadPipePackets": "",
"OpGroupReserveWritePipePackets": "",
"OpGroupCommitReadPipe": "",
"OpGroupCommitWritePipe": "",
"OpEnqueueMarker": "",
"OpEnqueueKernel": "",
"OpGetKernelNDrangeSubGroupCount": "",
"OpGetKernelNDrangeMaxSubGroupSize": "",
"OpGetKernelWorkGroupSize": "",
"OpGetKernelPreferredWorkGroupSizeMultiple": "",
"OpRetainEvent": "",
"OpReleaseEvent": "",
"OpCreateUserEvent": "",
"OpIsValidEvent": "",
"OpSetUserEventStatus": "",
"OpCaptureEventProfilingInfo": "",
"OpGetDefaultQueue": "",
"OpBuildNDRange": "",
"OpImageSparseSampleImplicitLod": "",
"OpImageSparseSampleExplicitLod": "",
"OpImageSparseSampleDrefImplicitLod": "",
"OpImageSparseSampleDrefExplicitLod": "",
"OpImageSparseSampleProjImplicitLod": "",
"OpImageSparseSampleProjExplicitLod": "",
"OpImageSparseSampleProjDrefImplicitLod": "",
"OpImageSparseSampleProjDrefExplicitLod": "",
"OpImageSparseFetch": "",
"OpImageSparseGather": "",
"OpImageSparseDrefGather": "",
"OpImageSparseTexelsResident": "",
"OpNoLine": "",
"OpAtomicFlagTestAndSet": "",
"OpAtomicFlagClear": "",
"OpImageSparseRead": "",
"OpSubgroupBallotKHR": "",
"OpSubgroupFirstInvocationKHR": "",
"OpSubgroupAllKHR": "",
"OpSubgroupAnyKHR": "",
"OpSubgroupAllEqualKHR": "",
"OpSubgroupReadInvocationKHR": "",
"OpGroupIAddNonUniformAMD": "",
"OpGroupFAddNonUniformAMD": "",
"OpGroupFMinNonUniformAMD": "",
"OpGroupUMinNonUniformAMD": "",
"OpGroupSMinNonUniformAMD": "",
"OpGroupFMaxNonUniformAMD": "",
"OpGroupUMaxNonUniformAMD": "",
"OpGroupSMaxNonUniformAMD": "",
"OpFragmentMaskFetchAMD": "",
"OpFragmentFetchAMD": ""
};
var Operands = {
"IdMemorySemantics": { ctype: "guint32 {0}",
optional_unset: "0",
append_many: "g_array_append_vals ({0}, {1}, {2})",
append_one: "g_array_append_val ({0}, {1})" },
"IdRef": { ctype: "guint32 {0}",
optional_unset: "0",
append_many: "g_array_append_vals ({0}, {1}, {2})",
append_one: "g_array_append_val ({0}, {1})" },
"IdResult": { ctype: "guint32 {0}",
optional_unset: "0",
declare_local: "guint32 {0}_id = gsk_spv_writer_make_id (writer);",
append_one: "g_array_append_val ({0}, {1}_id)" },
"IdResultType": { ctype: "GskSlType *{0}",
optional_unset: "NULL",
declare_local: "guint32 {0}_id = gsk_spv_writer_get_id_for_type (writer, {0});",
append_one: "g_array_append_val ({0}, {1}_id)" },
"IdResultPointerType" : { ctype: "GskSlType *{0}, GskSpvStorageClass {0}_storage",
optional_unset: "NULL",
declare_local: "guint32 {0}_id = gsk_spv_writer_get_id_for_pointer_type (writer, {0}, {0}_storage);",
append_one: "g_array_append_val ({0}, {1}_id)" },
"IdScope": { ctype: "guint32 {0}",
optional_unset: "0",
append_many: "g_array_append_vals ({0}, {1}, {2})",
append_one: "g_array_append_val ({0}, {1})" },
"LiteralContextDependentNumber": { ctype: "guint32 {0}",
is_many: true,
append_many: "g_array_append_vals ({0}, {1}, {2})" },
"LiteralExtInstInteger": { ctype: "guint32 {0}",
append_many: "g_array_append_vals ({0}, {1}, {2})",
append_one: "g_array_append_val ({0}, {1})" },
"LiteralInteger": { ctype: "guint32 {0}",
append_many: "g_array_append_vals ({0}, {1}, {2})",
append_one: "g_array_append_val ({0}, {1})" },
"LiteralString": { ctype: "const char *{0}",
optional_unset: "NULL",
append_one: "append_string ({0}, {1})" },
"LiteralSpecConstantOpInteger": { ctype: "guint32 {0}",
is_many: true,
append_many: "g_array_append_vals ({0}, {1}, {2})" },
"PairIdRefLiteralInteger": { ctype: "guint32 {0}[2]",
append_many: "g_array_append_vals ({0}, {1}, 2 * {2})",
append_one: "g_array_append_vals ({0}, {1}, 2)" },
"PairIdRefIdRef": { ctype: "guint32 {0}[2]",
append_many: "g_array_append_vals ({0}, {1}, 2 * {2})",
append_one: "g_array_append_vals ({0}, {1}, 2)" },
"PairLiteralIntegerIdRef": { ctype: "guint32 {0}[2]",
append_many: "g_array_append_vals ({0}, {1}, 2 * {2})",
append_one: "g_array_append_vals ({0}, {1}, 2)" },
"ImageOperands" : { ctype: "GskSpvImageOperands {0}, guint32 *{0}_args, gsize n_{0}_args",
optional_unset: "0",
append_one: "G_STMT_START{ g_array_append_val ({0}, (guint32) { {1} }); g_array_append_vals ({0}, {1}_args, n_{1}_args); }G_STMT_END" }
};
for (let kind in spirv.operand_kinds)
{
kind = spirv.operand_kinds[kind];
if ((kind.category == "BitEnum" ||
kind.category == "ValueEnum") &&
!Operands[kind.kind])
{
Operands[kind.kind] = { ctype: "GskSpv" + kind.kind + " {0}",
append_one: "g_array_append_val ({0}, (guint32) { {1} })" };
if (kind.category == "BitEnum")
Operands[kind.kind].optional_unset = "0";
if (kind.kind == "AccessQualifier")
Operands[kind.kind].optional_unset = "-1";
}
}
function fix_operand (ins, o)
{
if (o.name)
{
if (o.name == "The name of the opaque type.")
o.varname = "name"
else
o.varname = sanitize_name (o.name);
}
else
{
if (o.kind == "IdResultType")
o.varname = "result_type"
else if (o.kind == "IdResult")
o.varname = "result"
else if (Operands[o.kind])
o.varname = all_lower (o.kind);
}
if (!o.varname)
throw new TypeError (o.name + " of type " + o.kind + " has no variable name");
let operand;
if (SpecialTypes[ins.opname] &&
SpecialTypes[ins.opname][o.varname])
o.kind = SpecialTypes[ins.opname][o.varname];
operand = Operands[o.kind];
if (o.varname == "default")
o.varname += "_";
if (o.kind == "IdResult")
ins.result = true;
o.ctype = operand.ctype;
if (operand.append_one)
o.append_one = operand.append_one;
if (operand.append_many)
o.append_many = operand.append_many;
if (operand.declare_local)
o.declare_local = operand.declare_local;
if (operand.is_many)
{
if (o.quantifier)
throw new SyntaxError ("Can't deal with lists of " + o.kind);
else
o.quantifier = "*";
}
if (!o.quantifier)
o.quantifier = "";
if (o.quantifier == "?")
{
o.varname = "opt_" + o.varname;
if (operand.optional_unset)
o.unset = operand.optional_unset;
}
if (o.quantifier == "*")
{
if (o.varname[o.varname.length - 1] == "1")
o.varname = o.varname.substr(0, o.varname.length - 2);
if (o.varname[o.varname.length - 1] != "s")
o.varname += "s";
}
}
for (let i in spirv.instructions)
{
let ins = spirv.instructions[i];
ins.result = false;
ins.enum_value = "GSK_SPV_OP_" + (extinst ? all_upper(extinst) + "_" + all_upper (ins.opname) : all_upper (ins.opname.substr(2)));
if (!ins.operands)
ins.operands = [];
if (ExtraOperands[ins.opname])
ins.operands = ins.operands.concat (ExtraOperands[ins.opname]);
if (extinst)
{
ins.operands.unshift (
{ "kind" : "IdResultType" },
{ "kind" : "IdResult" }
);
}
for (let o in ins.operands)
{
o = ins.operands[o];
fix_operand (ins, o);
}
if (extinst)
{
ins.section = "code";
ins.section_enum = "GSK_SPV_WRITER_SECTION_CODE";
}
else if (Sections[ins.opname])
{
ins.section = Sections[ins.opname];
ins.section_enum = "GSK_SPV_WRITER_SECTION_" + ins.section.toUpperCase();
}
if (!extinst)
ins.opname = ins.opname.substr(2);
}
function header()
{
print ("/* GTK - The GIMP Toolkit");
print (" * ");
print (" * Copyright © 2017 Benjamin Otte <otte@gnome.org>");
print (" *");
print (" * This library is free software; you can redistribute it and/or");
print (" * modify it under the terms of the GNU Lesser General Public");
print (" * License as published by the Free Software Foundation; either");
print (" * version 2 of the License, or (at your option) any later version.");
print (" *");
print (" * This library is distributed in the hope that it will be useful,");
print (" * but WITHOUT ANY WARRANTY; without even the implied warranty of");
print (" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU");
print (" * Lesser General Public License for more details.");
print (" *");
print (" * You should have received a copy of the GNU Lesser General Public");
print (" * License along with this library. If not, see <http://www.gnu.org/licenses/>.");
print (" */");
print ("");
print ("/*");
print (" * !!! THIS FILE WAS AUTOGENERATED !!!");
print (" * ");
print (" * This file was created using the command");
print (" * gjs spirv.js " + ARGV.join (" "));
print (" * Apply any changes to those files and then regenerate using above command.");
print (" */");
print ();
}
if (command == "enums")
{
header ();
print ("#ifndef __GSK_SPV_" + (extinst ? all_upper (extinst) + "_" : "") + "ENUMS_H__");
print ("#define __GSK_SPV_" + (extinst ? all_upper (extinst) + "_" : "") + "ENUMS_H__");
print ();
for (let kind in spirv.operand_kinds)
{
kind = spirv.operand_kinds[kind];
if (kind.category == "BitEnum" ||
kind.category == "ValueEnum")
{
print ("typedef enum {");
for (let i = 0; i < kind.enumerants.length; i++)
{
let e = kind.enumerants[i];
//print (Object.keys(e));
print (" GSK_SPV_" + all_upper(kind.kind) + "_" + all_upper (e.enumerant) + " = " + e.value + (i + 1 < kind.enumerants.length ? "," : ""));
}
print ("} GskSpv" + kind.kind + ";");
print ();
}
}
print ("typedef enum {");
for (let i =0; i < spirv.instructions.length; i++)
{
let ins = spirv.instructions[i];
print (" " + ins.enum_value + " = " + ins.opcode + (i + 1 < spirv.instructions.length ? "," : ""));
}
print ("} GskSpvOpcode" + extinst + ";");
print ();
print ("#endif /* __GSK_SPV_" + (extinst ? all_upper (extinst) + "_" : "") + "ENUMS_H__ */");
}
else if (command == "functions")
{
header ();
print ("#include <string.h>");
print ();
print ("#ifndef __GSK_SPV_SEEN_AUTOGENERATED_FUNCTIONS__");
print ("#define __GSK_SPV_SEEN_AUTOGENERATED_FUNCTIONS__");
print ("static inline void");
print ("append_string (GArray *bytes,");
print (" const char *str)");
print ("{");
print (" gsize len = strlen (str);");
print (" guint size = bytes->len;");
print (" g_array_set_size (bytes, size + len / 4 + 1);");
print (" memcpy (&g_array_index (bytes, guint32, size), str, len);");
print ("}");
print ("#endif /* __GSK_SPV_SEEN_AUTOGENERATED_FUNCTIONS__ */");
print ();
for (let i in spirv.instructions)
{
let ins = spirv.instructions[i];
let prefix = "gsk_spv_writer_" + all_lower(ins.opname) + " (";
let len = prefix.length;
if (ins.result)
print ("static inline guint32");
else
print ("static inline void");
if (ins.operands.length > 1 ||
ins.operands.length == 1 && !ins.result)
{
let seen_result = !ins.result;
print (prefix + "GskSpvWriter *writer,");
if (!ins.section)
print (Array(len+1).join(" ") + "GskSpvWriterSection section,");
for (let i = 0; i < ins.operands.length; i++)
{
let o = ins.operands[i];
if (o.kind == "IdResult")
{
seen_result = true;
continue;
}
if (o.quantifier == "*")
{
print (Array(len+1).join(" ") + o.ctype.format ("*" + o.varname) + ",");
print (Array(len+1).join(" ") + "gsize n_" + o.varname + (i + 2 - seen_result < ins.operands.length ? "," : ")"));
}
else
{
print (Array(len+1).join(" ") + o.ctype.format (o.varname) + (i + 2 - seen_result < ins.operands.length ? "," : ")"));
}
}
}
else
{
if (ins.section)
print ("gsk_spv_writer_" + all_lower(ins.opname) + " (GskSpvWriter *writer)");
else
{
print ("gsk_spv_writer_" + all_lower(ins.opname) + " (GskSpvWriter *writer,");
print (Array(len+1).join(" ") + "GskSpvWriterSection section)");
}
}
print ("{");
print (" GArray *bytes = gsk_spv_writer_get_bytes (writer, " + (ins.section_enum ? ins.section_enum : "section" ) + ");");
for (let i = 0; i < ins.operands.length; i++)
{
let o = ins.operands[i];
if (o.declare_local)
print (" " + o.declare_local.format (o.varname));
}
print (" guint start_index = bytes->len;");
print ("");
print (" g_array_append_val (bytes, (guint32) { 0 });");
for (let i = 0; i < ins.operands.length; i++)
{
let o = ins.operands[i];
let indent = " ";
if (o.unset)
{
print (indent + "if (" + o.varname + " != " + o.unset + ")");
indent += " ";
}
if (o.quantifier == "*")
print (indent + o.append_many.format ("bytes", o.varname, "n_" + o.varname) + ";");
else
print (indent + o.append_one.format ("bytes", o.varname) + ";");
if (i == 1 && extinst)
{
print (" g_array_append_val (bytes, (guint32) { gsk_spv_writer_get_id_for_extended_instructions (writer) });");
print (" g_array_append_val (bytes, (guint32) { " + ins.enum_value + " });");
}
}
print (" g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | " + (extinst ? "GSK_SPV_OP_EXT_INST" : ins.enum_value) + ";");
if (ins.result)
{
print ("");
print (" return result_id;");
}
print ("}");
print ("");
}
}
else
{
usage ()
}