glslang AST -> SPIR-V: Move to new auto-generated official headers, and for the disassembler, mirror the split done between the auto-generation header database and the specification.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@30434 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
1f77cacd69
commit
b40d6ac9e7
@ -124,7 +124,7 @@ enum Entrypoints {
|
|||||||
inline void GetDebugNames(const char** names)
|
inline void GetDebugNames(const char** names)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Count; ++i)
|
for (int i = 0; i < Count; ++i)
|
||||||
names[i] = "unknown";
|
names[i] = "Unknown";
|
||||||
|
|
||||||
names[Round] = "round";
|
names[Round] = "round";
|
||||||
names[RoundEven] = "roundEven";
|
names[RoundEven] = "roundEven";
|
||||||
|
@ -134,15 +134,15 @@ protected:
|
|||||||
spv::ExecutionModel TranslateExecutionModel(EShLanguage stage)
|
spv::ExecutionModel TranslateExecutionModel(EShLanguage stage)
|
||||||
{
|
{
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case EShLangVertex: return spv::ModelVertex;
|
case EShLangVertex: return spv::ExecutionModelVertex;
|
||||||
case EShLangTessControl: return spv::ModelTessellationControl;
|
case EShLangTessControl: return spv::ExecutionModelTessellationControl;
|
||||||
case EShLangTessEvaluation: return spv::ModelTessellationEvaluation;
|
case EShLangTessEvaluation: return spv::ExecutionModelTessellationEvaluation;
|
||||||
case EShLangGeometry: return spv::ModelGeometry;
|
case EShLangGeometry: return spv::ExecutionModelGeometry;
|
||||||
case EShLangFragment: return spv::ModelFragment;
|
case EShLangFragment: return spv::ExecutionModelFragment;
|
||||||
case EShLangCompute: return spv::ModelGLCompute;
|
case EShLangCompute: return spv::ExecutionModelGLCompute;
|
||||||
default:
|
default:
|
||||||
spv::MissingFunctionality("GLSL stage");
|
spv::MissingFunctionality("GLSL stage");
|
||||||
return spv::ModelFragment;
|
return spv::ExecutionModelFragment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,30 +150,30 @@ spv::ExecutionModel TranslateExecutionModel(EShLanguage stage)
|
|||||||
spv::StorageClass TranslateStorageClass(const glslang::TType& type)
|
spv::StorageClass TranslateStorageClass(const glslang::TType& type)
|
||||||
{
|
{
|
||||||
if (type.getQualifier().isPipeInput())
|
if (type.getQualifier().isPipeInput())
|
||||||
return spv::StorageInput;
|
return spv::StorageClassInput;
|
||||||
else if (type.getQualifier().isPipeOutput())
|
else if (type.getQualifier().isPipeOutput())
|
||||||
return spv::StorageOutput;
|
return spv::StorageClassOutput;
|
||||||
else if (type.getQualifier().isUniformOrBuffer()) {
|
else if (type.getQualifier().isUniformOrBuffer()) {
|
||||||
if (type.getBasicType() == glslang::EbtBlock)
|
if (type.getBasicType() == glslang::EbtBlock)
|
||||||
return spv::StorageUniform;
|
return spv::StorageClassUniform;
|
||||||
else
|
else
|
||||||
return spv::StorageConstantUniform;
|
return spv::StorageClassUniformConstant;
|
||||||
// TODO: how are we distuingishing between default and non-default non-writable uniforms? Do default uniforms even exist?
|
// TODO: how are we distuingishing between default and non-default non-writable uniforms? Do default uniforms even exist?
|
||||||
} else {
|
} else {
|
||||||
switch (type.getQualifier().storage) {
|
switch (type.getQualifier().storage) {
|
||||||
case glslang::EvqShared: return spv::StorageWorkgroupLocal; break;
|
case glslang::EvqShared: return spv::StorageClassWorkgroupLocal; break;
|
||||||
case glslang::EvqGlobal: return spv::StoragePrivateGlobal;
|
case glslang::EvqGlobal: return spv::StorageClassPrivateGlobal;
|
||||||
case glslang::EvqConstReadOnly: return spv::StorageFunction;
|
case glslang::EvqConstReadOnly: return spv::StorageClassFunction;
|
||||||
case glslang::EvqTemporary: return spv::StorageFunction;
|
case glslang::EvqTemporary: return spv::StorageClassFunction;
|
||||||
default:
|
default:
|
||||||
spv::MissingFunctionality("unknown glslang storage class");
|
spv::MissingFunctionality("unknown glslang storage class");
|
||||||
return spv::StorageCount;
|
return spv::StorageClassFunction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate glslang sampler type to SPIR-V dimensionality.
|
// Translate glslang sampler type to SPIR-V dimensionality.
|
||||||
spv::Dimensionality TranslateDimensionality(const glslang::TSampler& sampler)
|
spv::Dim TranslateDimensionality(const glslang::TSampler& sampler)
|
||||||
{
|
{
|
||||||
switch (sampler.dim) {
|
switch (sampler.dim) {
|
||||||
case glslang::Esd1D: return spv::Dim1D;
|
case glslang::Esd1D: return spv::Dim1D;
|
||||||
@ -192,10 +192,11 @@ spv::Dimensionality TranslateDimensionality(const glslang::TSampler& sampler)
|
|||||||
spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type)
|
spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type)
|
||||||
{
|
{
|
||||||
switch (type.getQualifier().precision) {
|
switch (type.getQualifier().precision) {
|
||||||
case glslang::EpqLow: return spv::DecPrecisionLow;
|
case glslang::EpqLow: return spv::DecorationPrecisionLow;
|
||||||
case glslang::EpqMedium: return spv::DecPrecisionMedium;
|
case glslang::EpqMedium: return spv::DecorationPrecisionMedium;
|
||||||
case glslang::EpqHigh: return spv::DecPrecisionHigh;
|
case glslang::EpqHigh: return spv::DecorationPrecisionHigh;
|
||||||
default: return spv::DecCount;
|
default:
|
||||||
|
return spv::NoPrecision;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,17 +205,17 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type)
|
|||||||
{
|
{
|
||||||
if (type.getBasicType() == glslang::EbtBlock) {
|
if (type.getBasicType() == glslang::EbtBlock) {
|
||||||
switch (type.getQualifier().storage) {
|
switch (type.getQualifier().storage) {
|
||||||
case glslang::EvqUniform: return spv::DecBlock;
|
case glslang::EvqUniform: return spv::DecorationBlock;
|
||||||
case glslang::EvqBuffer: return spv::DecBufferBlock;
|
case glslang::EvqBuffer: return spv::DecorationBufferBlock;
|
||||||
case glslang::EvqVaryingIn: return spv::DecBlock;
|
case glslang::EvqVaryingIn: return spv::DecorationBlock;
|
||||||
case glslang::EvqVaryingOut: return spv::DecBlock;
|
case glslang::EvqVaryingOut: return spv::DecorationBlock;
|
||||||
default:
|
default:
|
||||||
spv::MissingFunctionality("kind of block");
|
spv::MissingFunctionality("kind of block");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return spv::DecCount;
|
return (spv::Decoration)spv::BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate glslang type to SPIR-V layout decorations.
|
// Translate glslang type to SPIR-V layout decorations.
|
||||||
@ -223,36 +224,36 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type)
|
|||||||
if (type.isMatrix()) {
|
if (type.isMatrix()) {
|
||||||
switch (type.getQualifier().layoutMatrix) {
|
switch (type.getQualifier().layoutMatrix) {
|
||||||
case glslang::ElmRowMajor:
|
case glslang::ElmRowMajor:
|
||||||
return spv::DecRowMajor;
|
return spv::DecorationRowMajor;
|
||||||
default:
|
default:
|
||||||
return spv::DecColMajor;
|
return spv::DecorationColMajor;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (type.getBasicType()) {
|
switch (type.getBasicType()) {
|
||||||
default:
|
default:
|
||||||
return spv::DecCount;
|
return (spv::Decoration)spv::BadValue;
|
||||||
break;
|
break;
|
||||||
case glslang::EbtBlock:
|
case glslang::EbtBlock:
|
||||||
switch (type.getQualifier().storage) {
|
switch (type.getQualifier().storage) {
|
||||||
case glslang::EvqUniform:
|
case glslang::EvqUniform:
|
||||||
case glslang::EvqBuffer:
|
case glslang::EvqBuffer:
|
||||||
switch (type.getQualifier().layoutPacking) {
|
switch (type.getQualifier().layoutPacking) {
|
||||||
case glslang::ElpShared: return spv::DecGLSLShared;
|
case glslang::ElpShared: return spv::DecorationGLSLShared;
|
||||||
case glslang::ElpStd140: return spv::DecGLSLStd140;
|
case glslang::ElpStd140: return spv::DecorationGLSLStd140;
|
||||||
case glslang::ElpStd430: return spv::DecGLSLStd430;
|
case glslang::ElpStd430: return spv::DecorationGLSLStd430;
|
||||||
case glslang::ElpPacked: return spv::DecGLSLPacked;
|
case glslang::ElpPacked: return spv::DecorationGLSLPacked;
|
||||||
default:
|
default:
|
||||||
spv::MissingFunctionality("uniform block layout");
|
spv::MissingFunctionality("uniform block layout");
|
||||||
return spv::DecGLSLShared;
|
return spv::DecorationGLSLShared;
|
||||||
}
|
}
|
||||||
case glslang::EvqVaryingIn:
|
case glslang::EvqVaryingIn:
|
||||||
case glslang::EvqVaryingOut:
|
case glslang::EvqVaryingOut:
|
||||||
if (type.getQualifier().layoutPacking != glslang::ElpNone)
|
if (type.getQualifier().layoutPacking != glslang::ElpNone)
|
||||||
spv::MissingFunctionality("in/out block layout");
|
spv::MissingFunctionality("in/out block layout");
|
||||||
return spv::DecCount;
|
return (spv::Decoration)spv::BadValue;
|
||||||
default:
|
default:
|
||||||
spv::MissingFunctionality("block storage qualification");
|
spv::MissingFunctionality("block storage qualification");
|
||||||
return spv::DecCount;
|
return (spv::Decoration)spv::BadValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,28 +263,28 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type)
|
|||||||
spv::Decoration TranslateInterpolationDecoration(const glslang::TType& type)
|
spv::Decoration TranslateInterpolationDecoration(const glslang::TType& type)
|
||||||
{
|
{
|
||||||
if (type.getQualifier().smooth)
|
if (type.getQualifier().smooth)
|
||||||
return spv::DecSmooth;
|
return spv::DecorationSmooth;
|
||||||
if (type.getQualifier().nopersp)
|
if (type.getQualifier().nopersp)
|
||||||
return spv::DecNoperspective;
|
return spv::DecorationNoperspective;
|
||||||
else if (type.getQualifier().patch)
|
else if (type.getQualifier().patch)
|
||||||
return spv::DecPatch;
|
return spv::DecorationPatch;
|
||||||
else if (type.getQualifier().flat)
|
else if (type.getQualifier().flat)
|
||||||
return spv::DecFlat;
|
return spv::DecorationFlat;
|
||||||
else if (type.getQualifier().centroid)
|
else if (type.getQualifier().centroid)
|
||||||
return spv::DecCentroid;
|
return spv::DecorationCentroid;
|
||||||
else if (type.getQualifier().sample)
|
else if (type.getQualifier().sample)
|
||||||
return spv::DecSample;
|
return spv::DecorationSample;
|
||||||
else
|
else
|
||||||
return spv::DecCount;
|
return (spv::Decoration)spv::BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If glslang type is invaraiant, return SPIR-V invariant decoration.
|
// If glslang type is invaraiant, return SPIR-V invariant decoration.
|
||||||
spv::Decoration TranslateInvariantDecoration(const glslang::TType& type)
|
spv::Decoration TranslateInvariantDecoration(const glslang::TType& type)
|
||||||
{
|
{
|
||||||
if (type.getQualifier().invariant)
|
if (type.getQualifier().invariant)
|
||||||
return spv::DecInvariant;
|
return spv::DecorationInvariant;
|
||||||
else
|
else
|
||||||
return spv::DecCount;
|
return (spv::Decoration)spv::BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify what SPIR-V built-in variable a symbol is.
|
// Identify what SPIR-V built-in variable a symbol is.
|
||||||
@ -312,7 +313,7 @@ spv::BuiltIn TranslateBuiltIn(const glslang::TIntermSymbol* node)
|
|||||||
{
|
{
|
||||||
const glslang::TString& name = node->getName();
|
const glslang::TString& name = node->getName();
|
||||||
if (name.compare(0, 3, "gl_") != 0)
|
if (name.compare(0, 3, "gl_") != 0)
|
||||||
return spv::BuiltInCount;
|
return (spv::BuiltIn)spv::BadValue;
|
||||||
|
|
||||||
switch (node->getQualifier().storage) {
|
switch (node->getQualifier().storage) {
|
||||||
case glslang::EvqPosition: return spv::BuiltInPosition;
|
case glslang::EvqPosition: return spv::BuiltInPosition;
|
||||||
@ -325,7 +326,7 @@ spv::BuiltIn TranslateBuiltIn(const glslang::TIntermSymbol* node)
|
|||||||
case glslang::EvqFace: return spv::BuiltInFrontFacing;
|
case glslang::EvqFace: return spv::BuiltInFrontFacing;
|
||||||
case glslang::EvqFragColor: return spv::BuiltInFragColor;
|
case glslang::EvqFragColor: return spv::BuiltInFragColor;
|
||||||
case glslang::EvqFragDepth: return spv::BuiltInFragDepth;
|
case glslang::EvqFragDepth: return spv::BuiltInFragDepth;
|
||||||
default: return spv::BuiltInCount;
|
default: return (spv::BuiltIn)spv::BadValue;
|
||||||
if (name == "gl_ClipDistance")
|
if (name == "gl_ClipDistance")
|
||||||
return spv::BuiltInClipDistance;
|
return spv::BuiltInClipDistance;
|
||||||
else if (name == "gl_PrimitiveID" || name == "gl_PrimitiveIDIn")
|
else if (name == "gl_PrimitiveID" || name == "gl_PrimitiveIDIn")
|
||||||
@ -380,9 +381,9 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls
|
|||||||
spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage());
|
spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage());
|
||||||
|
|
||||||
builder.clearAccessChain();
|
builder.clearAccessChain();
|
||||||
builder.setSource(spv::LangGLSL, glslangIntermediate->getVersion());
|
builder.setSource(spv::SourceLanguageGLSL, glslangIntermediate->getVersion());
|
||||||
stdBuiltins = builder.import("GLSL.std.450");
|
stdBuiltins = builder.import("GLSL.std.450");
|
||||||
builder.setMemoryModel(spv::AddressingLogical, spv::MemoryGLSL450);
|
builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450);
|
||||||
shaderEntry = builder.makeMain();
|
shaderEntry = builder.makeMain();
|
||||||
builder.addEntryPoint(executionModel, shaderEntry);
|
builder.addEntryPoint(executionModel, shaderEntry);
|
||||||
|
|
||||||
@ -394,7 +395,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls
|
|||||||
// Add the top-level modes for this shader.
|
// Add the top-level modes for this shader.
|
||||||
|
|
||||||
if (glslangIntermediate->getXfbMode())
|
if (glslangIntermediate->getXfbMode())
|
||||||
builder.addExecutionMode(shaderEntry, spv::ExecutionXfb);
|
builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb);
|
||||||
|
|
||||||
spv::ExecutionMode mode;
|
spv::ExecutionMode mode;
|
||||||
switch (glslangIntermediate->getStage()) {
|
switch (glslangIntermediate->getStage()) {
|
||||||
@ -402,17 +403,17 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EShLangTessControl:
|
case EShLangTessControl:
|
||||||
builder.addExecutionMode(shaderEntry, spv::ExecutionOutputVertices, glslangIntermediate->getVertices());
|
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EShLangTessEvaluation:
|
case EShLangTessEvaluation:
|
||||||
switch (glslangIntermediate->getInputPrimitive()) {
|
switch (glslangIntermediate->getInputPrimitive()) {
|
||||||
case glslang::ElgTriangles: mode = spv::ExecutionInputTriangles; break;
|
case glslang::ElgTriangles: mode = spv::ExecutionModeInputTriangles; break;
|
||||||
case glslang::ElgQuads: mode = spv::ExecutionInputQuads; break;
|
case glslang::ElgQuads: mode = spv::ExecutionModeInputQuads; break;
|
||||||
case glslang::ElgIsolines: mode = spv::ExecutionInputIsolines; break;
|
case glslang::ElgIsolines: mode = spv::ExecutionModeInputIsolines; break;
|
||||||
default: mode = spv::ExecutionModeCount; break;
|
default: mode = (spv::ExecutionMode)spv::BadValue; break;
|
||||||
}
|
}
|
||||||
if (mode != spv::ExecutionModeCount)
|
if (mode != spv::BadValue)
|
||||||
builder.addExecutionMode(shaderEntry, mode);
|
builder.addExecutionMode(shaderEntry, mode);
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
@ -423,33 +424,33 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls
|
|||||||
|
|
||||||
case EShLangGeometry:
|
case EShLangGeometry:
|
||||||
switch (glslangIntermediate->getInputPrimitive()) {
|
switch (glslangIntermediate->getInputPrimitive()) {
|
||||||
case glslang::ElgPoints: mode = spv::ExecutionInputPoints; break;
|
case glslang::ElgPoints: mode = spv::ExecutionModeInputPoints; break;
|
||||||
case glslang::ElgLines: mode = spv::ExecutionInputLines; break;
|
case glslang::ElgLines: mode = spv::ExecutionModeInputLines; break;
|
||||||
case glslang::ElgLinesAdjacency: mode = spv::ExecutionInputLinesAdjacency; break;
|
case glslang::ElgLinesAdjacency: mode = spv::ExecutionModeInputLinesAdjacency; break;
|
||||||
case glslang::ElgTriangles: mode = spv::ExecutionInputTriangles; break;
|
case glslang::ElgTriangles: mode = spv::ExecutionModeInputTriangles; break;
|
||||||
case glslang::ElgTrianglesAdjacency: mode = spv::ExecutionInputTrianglesAdjacency; break;
|
case glslang::ElgTrianglesAdjacency: mode = spv::ExecutionModeInputTrianglesAdjacency; break;
|
||||||
default: mode = spv::ExecutionModeCount; break;
|
default: mode = (spv::ExecutionMode)spv::BadValue; break;
|
||||||
}
|
}
|
||||||
if (mode != spv::ExecutionModeCount)
|
if (mode != spv::BadValue)
|
||||||
builder.addExecutionMode(shaderEntry, mode);
|
builder.addExecutionMode(shaderEntry, mode);
|
||||||
builder.addExecutionMode(shaderEntry, spv::ExecutionInvocations, glslangIntermediate->getInvocations());
|
builder.addExecutionMode(shaderEntry, spv::ExecutionModeInvocations, glslangIntermediate->getInvocations());
|
||||||
|
|
||||||
switch (glslangIntermediate->getOutputPrimitive()) {
|
switch (glslangIntermediate->getOutputPrimitive()) {
|
||||||
case glslang::ElgPoints: mode = spv::ExecutionOutputPoints; break;
|
case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break;
|
||||||
case glslang::ElgLineStrip: mode = spv::ExecutionOutputLineStrip; break;
|
case glslang::ElgLineStrip: mode = spv::ExecutionModeOutputLineStrip; break;
|
||||||
case glslang::ElgTriangleStrip: mode = spv::ExecutionOutputTriangleStrip; break;
|
case glslang::ElgTriangleStrip: mode = spv::ExecutionModeOutputTriangleStrip; break;
|
||||||
default: mode = spv::ExecutionModeCount; break;
|
default: mode = (spv::ExecutionMode)spv::BadValue; break;
|
||||||
}
|
}
|
||||||
if (mode != spv::ExecutionModeCount)
|
if (mode != spv::BadValue)
|
||||||
builder.addExecutionMode(shaderEntry, mode);
|
builder.addExecutionMode(shaderEntry, mode);
|
||||||
builder.addExecutionMode(shaderEntry, spv::ExecutionOutputVertices, glslangIntermediate->getVertices());
|
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EShLangFragment:
|
case EShLangFragment:
|
||||||
if (glslangIntermediate->getPixelCenterInteger())
|
if (glslangIntermediate->getPixelCenterInteger())
|
||||||
builder.addExecutionMode(shaderEntry, spv::ExecutionPixelCenterInteger);
|
builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger);
|
||||||
if (glslangIntermediate->getOriginUpperLeft())
|
if (glslangIntermediate->getOriginUpperLeft())
|
||||||
builder.addExecutionMode(shaderEntry, spv::ExecutionOriginUpperLeft);
|
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EShLangCompute:
|
case EShLangCompute:
|
||||||
@ -1075,14 +1076,14 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
|
|||||||
if (node->getBasicType() != glslang::EbtVoid) {
|
if (node->getBasicType() != glslang::EbtVoid) {
|
||||||
// don't handle this as just on-the-fly temporaries, because there will be two names
|
// don't handle this as just on-the-fly temporaries, because there will be two names
|
||||||
// and better to leave SSA to later passes
|
// and better to leave SSA to later passes
|
||||||
result = builder.createVariable(spv::StorageFunction, convertGlslangToSpvType(node->getType()));
|
result = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// emit the condition before doing anything with selection
|
// emit the condition before doing anything with selection
|
||||||
node->getCondition()->traverse(this);
|
node->getCondition()->traverse(this);
|
||||||
|
|
||||||
// make an "if" based on the value created by the condition
|
// make an "if" based on the value created by the condition
|
||||||
spv::Builder::If ifBuilder(builder.accessChainLoad(spv::DecCount), builder);
|
spv::Builder::If ifBuilder(builder.accessChainLoad(spv::NoPrecision), builder);
|
||||||
|
|
||||||
if (node->getTrueBlock()) {
|
if (node->getTrueBlock()) {
|
||||||
// emit the "then" statement
|
// emit the "then" statement
|
||||||
@ -1266,8 +1267,8 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
|
|||||||
if (glslang::IsAnonymous(name))
|
if (glslang::IsAnonymous(name))
|
||||||
name = "";
|
name = "";
|
||||||
|
|
||||||
if (storageClass == spv::StorageCount)
|
if (storageClass == spv::BadValue)
|
||||||
return builder.createVariable(spv::StorageFunction, spvType, name);
|
return builder.createVariable(spv::StorageClassFunction, spvType, name);
|
||||||
else
|
else
|
||||||
return builder.createVariable(storageClass, spvType, name);
|
return builder.createVariable(storageClass, spvType, name);
|
||||||
}
|
}
|
||||||
@ -1366,11 +1367,11 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||||||
addMemberDecoration(spvType, member, TranslateInterpolationDecoration(glslangType));
|
addMemberDecoration(spvType, member, TranslateInterpolationDecoration(glslangType));
|
||||||
addMemberDecoration(spvType, member, TranslateInvariantDecoration(glslangType));
|
addMemberDecoration(spvType, member, TranslateInvariantDecoration(glslangType));
|
||||||
if (glslangType.getQualifier().hasLocation())
|
if (glslangType.getQualifier().hasLocation())
|
||||||
builder.addMemberDecoration(spvType, member, spv::DecLocation, glslangType.getQualifier().layoutLocation);
|
builder.addMemberDecoration(spvType, member, spv::DecorationLocation, glslangType.getQualifier().layoutLocation);
|
||||||
if (glslangType.getQualifier().hasComponent())
|
if (glslangType.getQualifier().hasComponent())
|
||||||
builder.addMemberDecoration(spvType, member, spv::DecComponent, glslangType.getQualifier().layoutComponent);
|
builder.addMemberDecoration(spvType, member, spv::DecorationComponent, glslangType.getQualifier().layoutComponent);
|
||||||
if (glslangType.getQualifier().hasXfbOffset())
|
if (glslangType.getQualifier().hasXfbOffset())
|
||||||
builder.addMemberDecoration(spvType, member, spv::DecOffset, glslangType.getQualifier().layoutXfbOffset);
|
builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangType.getQualifier().layoutXfbOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1378,12 +1379,12 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||||||
addDecoration(spvType, TranslateLayoutDecoration(type));
|
addDecoration(spvType, TranslateLayoutDecoration(type));
|
||||||
addDecoration(spvType, TranslateBlockDecoration(type));
|
addDecoration(spvType, TranslateBlockDecoration(type));
|
||||||
if (type.getQualifier().hasStream())
|
if (type.getQualifier().hasStream())
|
||||||
builder.addDecoration(spvType, spv::DecStream, type.getQualifier().layoutStream);
|
builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream);
|
||||||
if (glslangIntermediate->getXfbMode()) {
|
if (glslangIntermediate->getXfbMode()) {
|
||||||
if (type.getQualifier().hasXfbStride())
|
if (type.getQualifier().hasXfbStride())
|
||||||
builder.addDecoration(spvType, spv::DecStride, type.getQualifier().layoutXfbStride);
|
builder.addDecoration(spvType, spv::DecorationStride, type.getQualifier().layoutXfbStride);
|
||||||
if (type.getQualifier().hasXfbBuffer())
|
if (type.getQualifier().hasXfbBuffer())
|
||||||
builder.addDecoration(spvType, spv::DecXfbBuffer, type.getQualifier().layoutXfbBuffer);
|
builder.addDecoration(spvType, spv::DecorationXfbBuffer, type.getQualifier().layoutXfbBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1448,7 +1449,7 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
|
|||||||
const glslang::TType& paramType = parameters[p]->getAsTyped()->getType();
|
const glslang::TType& paramType = parameters[p]->getAsTyped()->getType();
|
||||||
spv::Id typeId = convertGlslangToSpvType(paramType);
|
spv::Id typeId = convertGlslangToSpvType(paramType);
|
||||||
if (paramType.getQualifier().storage != glslang::EvqConstReadOnly)
|
if (paramType.getQualifier().storage != glslang::EvqConstReadOnly)
|
||||||
typeId = builder.makePointer(spv::StorageFunction, typeId);
|
typeId = builder.makePointer(spv::StorageClassFunction, typeId);
|
||||||
else
|
else
|
||||||
constReadOnlyParameters.insert(parameters[p]->getAsSymbolNode()->getId());
|
constReadOnlyParameters.insert(parameters[p]->getAsSymbolNode()->getId());
|
||||||
paramTypes.push_back(typeId);
|
paramTypes.push_back(typeId);
|
||||||
@ -1674,11 +1675,11 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
|
|||||||
if (qualifiers[a] != glslang::EvqConstReadOnly) {
|
if (qualifiers[a] != glslang::EvqConstReadOnly) {
|
||||||
// need space to hold the copy
|
// need space to hold the copy
|
||||||
const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType();
|
const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType();
|
||||||
arg = builder.createVariable(spv::StorageFunction, convertGlslangToSpvType(paramType), "param");
|
arg = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(paramType), "param");
|
||||||
if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) {
|
if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) {
|
||||||
// need to copy the input into output space
|
// need to copy the input into output space
|
||||||
builder.setAccessChain(lValues[lValueCount]);
|
builder.setAccessChain(lValues[lValueCount]);
|
||||||
spv::Id copy = builder.accessChainLoad(spv::DecCount); // TODO: get precision
|
spv::Id copy = builder.accessChainLoad(spv::NoPrecision); // TODO: get precision
|
||||||
builder.createStore(copy, arg);
|
builder.createStore(copy, arg);
|
||||||
}
|
}
|
||||||
++lValueCount;
|
++lValueCount;
|
||||||
@ -1715,7 +1716,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
|
|||||||
bool isUnsigned = typeProxy == glslang::EbtUint;
|
bool isUnsigned = typeProxy == glslang::EbtUint;
|
||||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
|
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
|
||||||
|
|
||||||
spv::OpCode binOp = spv::OpNop;
|
spv::Op binOp = spv::OpNop;
|
||||||
bool needsPromotion = true;
|
bool needsPromotion = true;
|
||||||
bool comparison = false;
|
bool comparison = false;
|
||||||
|
|
||||||
@ -1943,7 +1944,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
|
|||||||
|
|
||||||
spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand, bool isFloat)
|
spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand, bool isFloat)
|
||||||
{
|
{
|
||||||
spv::OpCode unaryOp = spv::OpNop;
|
spv::Op unaryOp = spv::OpNop;
|
||||||
int libCall = -1;
|
int libCall = -1;
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@ -2158,7 +2159,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
|
|||||||
|
|
||||||
spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Decoration precision, spv::Id destType, spv::Id operand)
|
spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Decoration precision, spv::Id destType, spv::Id operand)
|
||||||
{
|
{
|
||||||
spv::OpCode convOp = spv::OpNop;
|
spv::Op convOp = spv::OpNop;
|
||||||
spv::Id zero;
|
spv::Id zero;
|
||||||
spv::Id one;
|
spv::Id one;
|
||||||
|
|
||||||
@ -2265,7 +2266,7 @@ spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vector
|
|||||||
|
|
||||||
spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, bool isUnsigned)
|
spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, bool isUnsigned)
|
||||||
{
|
{
|
||||||
spv::OpCode opCode = spv::OpNop;
|
spv::Op opCode = spv::OpNop;
|
||||||
int libCall = -1;
|
int libCall = -1;
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@ -2371,19 +2372,19 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op)
|
|||||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsAllMemory);
|
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsAllMemory);
|
||||||
return 0;
|
return 0;
|
||||||
case glslang::EOpMemoryBarrierAtomicCounter:
|
case glslang::EOpMemoryBarrierAtomicCounter:
|
||||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsAtomicCounter);
|
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsAtomicCounterMemoryMask);
|
||||||
return 0;
|
return 0;
|
||||||
case glslang::EOpMemoryBarrierBuffer:
|
case glslang::EOpMemoryBarrierBuffer:
|
||||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsUniform);
|
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsUniformMemoryMask);
|
||||||
return 0;
|
return 0;
|
||||||
case glslang::EOpMemoryBarrierImage:
|
case glslang::EOpMemoryBarrierImage:
|
||||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsImage);
|
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsImageMemoryMask);
|
||||||
return 0;
|
return 0;
|
||||||
case glslang::EOpMemoryBarrierShared:
|
case glslang::EOpMemoryBarrierShared:
|
||||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsWorkgroupLocal);
|
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsWorkgroupLocalMemoryMask);
|
||||||
return 0;
|
return 0;
|
||||||
case glslang::EOpGroupMemoryBarrier:
|
case glslang::EOpGroupMemoryBarrier:
|
||||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsWorkgroupGlobal);
|
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsWorkgroupGlobalMemoryMask);
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
spv::MissingFunctionality("operation with no arguments");
|
spv::MissingFunctionality("operation with no arguments");
|
||||||
@ -2409,53 +2410,53 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
|
|||||||
addDecoration(id, TranslatePrecisionDecoration(symbol->getType()));
|
addDecoration(id, TranslatePrecisionDecoration(symbol->getType()));
|
||||||
addDecoration(id, TranslateInterpolationDecoration(symbol->getType()));
|
addDecoration(id, TranslateInterpolationDecoration(symbol->getType()));
|
||||||
if (symbol->getQualifier().hasLocation())
|
if (symbol->getQualifier().hasLocation())
|
||||||
builder.addDecoration(id, spv::DecLocation, symbol->getQualifier().layoutLocation);
|
builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation);
|
||||||
if (symbol->getQualifier().hasComponent())
|
if (symbol->getQualifier().hasComponent())
|
||||||
builder.addDecoration(id, spv::DecComponent, symbol->getQualifier().layoutComponent);
|
builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent);
|
||||||
if (glslangIntermediate->getXfbMode()) {
|
if (glslangIntermediate->getXfbMode()) {
|
||||||
if (symbol->getQualifier().hasXfbStride())
|
if (symbol->getQualifier().hasXfbStride())
|
||||||
builder.addDecoration(id, spv::DecStride, symbol->getQualifier().layoutXfbStride);
|
builder.addDecoration(id, spv::DecorationStride, symbol->getQualifier().layoutXfbStride);
|
||||||
if (symbol->getQualifier().hasXfbBuffer())
|
if (symbol->getQualifier().hasXfbBuffer())
|
||||||
builder.addDecoration(id, spv::DecXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
|
builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
|
||||||
if (symbol->getQualifier().hasXfbOffset())
|
if (symbol->getQualifier().hasXfbOffset())
|
||||||
builder.addDecoration(id, spv::DecOffset, symbol->getQualifier().layoutXfbOffset);
|
builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addDecoration(id, TranslateInvariantDecoration(symbol->getType()));
|
addDecoration(id, TranslateInvariantDecoration(symbol->getType()));
|
||||||
if (symbol->getQualifier().hasStream())
|
if (symbol->getQualifier().hasStream())
|
||||||
builder.addDecoration(id, spv::DecStream, symbol->getQualifier().layoutStream);
|
builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream);
|
||||||
if (symbol->getQualifier().hasSet())
|
if (symbol->getQualifier().hasSet())
|
||||||
builder.addDecoration(id, spv::DecDescriptorSet, symbol->getQualifier().layoutSet);
|
builder.addDecoration(id, spv::DecorationDescriptorSet, symbol->getQualifier().layoutSet);
|
||||||
if (symbol->getQualifier().hasBinding())
|
if (symbol->getQualifier().hasBinding())
|
||||||
builder.addDecoration(id, spv::DecBinding, symbol->getQualifier().layoutBinding);
|
builder.addDecoration(id, spv::DecorationBinding, symbol->getQualifier().layoutBinding);
|
||||||
if (glslangIntermediate->getXfbMode()) {
|
if (glslangIntermediate->getXfbMode()) {
|
||||||
if (symbol->getQualifier().hasXfbStride())
|
if (symbol->getQualifier().hasXfbStride())
|
||||||
builder.addDecoration(id, spv::DecStride, symbol->getQualifier().layoutXfbStride);
|
builder.addDecoration(id, spv::DecorationStride, symbol->getQualifier().layoutXfbStride);
|
||||||
if (symbol->getQualifier().hasXfbBuffer())
|
if (symbol->getQualifier().hasXfbBuffer())
|
||||||
builder.addDecoration(id, spv::DecXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
|
builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// built-in variable decorations
|
// built-in variable decorations
|
||||||
int num = TranslateBuiltInDecoration(*symbol);
|
int num = TranslateBuiltInDecoration(*symbol);
|
||||||
if (num >= 0)
|
if (num >= 0)
|
||||||
builder.addDecoration(id, spv::DecBuiltIn, num);
|
builder.addDecoration(id, spv::DecorationBuiltIn, num);
|
||||||
|
|
||||||
if (linkageOnly)
|
if (linkageOnly)
|
||||||
builder.addDecoration(id, spv::DecNoStaticUse);
|
builder.addDecoration(id, spv::DecorationNoStaticUse);
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec)
|
void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec)
|
||||||
{
|
{
|
||||||
if (dec != spv::DecCount)
|
if (dec != spv::BadValue)
|
||||||
builder.addDecoration(id, dec);
|
builder.addDecoration(id, dec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::Decoration dec)
|
void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::Decoration dec)
|
||||||
{
|
{
|
||||||
if (dec != spv::DecCount)
|
if (dec != spv::BadValue)
|
||||||
builder.addMemberDecoration(id, (unsigned)member, dec);
|
builder.addMemberDecoration(id, (unsigned)member, dec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,10 +56,10 @@ namespace spv {
|
|||||||
const int SpvBuilderMagic = 0xBB;
|
const int SpvBuilderMagic = 0xBB;
|
||||||
|
|
||||||
Builder::Builder(unsigned int userNumber) :
|
Builder::Builder(unsigned int userNumber) :
|
||||||
source(LangUnknown),
|
source(SourceLanguageUnknown),
|
||||||
sourceVersion(0),
|
sourceVersion(0),
|
||||||
addressModel(AddressingLogical),
|
addressModel(AddressingModelLogical),
|
||||||
memoryModel(MemoryGLSL450),
|
memoryModel(MemoryModelGLSL450),
|
||||||
builderNumber(userNumber << 16 | SpvBuilderMagic),
|
builderNumber(userNumber << 16 | SpvBuilderMagic),
|
||||||
buildPoint(0),
|
buildPoint(0),
|
||||||
uniqueId(0),
|
uniqueId(0),
|
||||||
@ -293,7 +293,7 @@ Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
|
|||||||
return type->getResultId();
|
return type->getResultId();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id Builder::makeSampler(Id sampledType, Dimensionality dim, samplerContent content, bool arrayed, bool shadow, bool ms)
|
Id Builder::makeSampler(Id sampledType, Dim dim, samplerContent content, bool arrayed, bool shadow, bool ms)
|
||||||
{
|
{
|
||||||
// try to find it
|
// try to find it
|
||||||
Instruction* type;
|
Instruction* type;
|
||||||
@ -332,11 +332,11 @@ Id Builder::getDerefTypeId(Id resultId) const
|
|||||||
return module.getInstruction(typeId)->getImmediateOperand(1);
|
return module.getInstruction(typeId)->getImmediateOperand(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
OpCode Builder::getMostBasicTypeClass(Id typeId) const
|
Op Builder::getMostBasicTypeClass(Id typeId) const
|
||||||
{
|
{
|
||||||
Instruction* instr = module.getInstruction(typeId);
|
Instruction* instr = module.getInstruction(typeId);
|
||||||
|
|
||||||
OpCode typeClass = instr->getOpCode();
|
Op typeClass = instr->getOpCode();
|
||||||
switch (typeClass)
|
switch (typeClass)
|
||||||
{
|
{
|
||||||
case OpTypeVoid:
|
case OpTypeVoid:
|
||||||
@ -384,7 +384,7 @@ Id Builder::getScalarTypeId(Id typeId) const
|
|||||||
{
|
{
|
||||||
Instruction* instr = module.getInstruction(typeId);
|
Instruction* instr = module.getInstruction(typeId);
|
||||||
|
|
||||||
OpCode typeClass = instr->getOpCode();
|
Op typeClass = instr->getOpCode();
|
||||||
switch (typeClass)
|
switch (typeClass)
|
||||||
{
|
{
|
||||||
case OpTypeVoid:
|
case OpTypeVoid:
|
||||||
@ -410,7 +410,7 @@ Id Builder::getContainedTypeId(Id typeId, int member) const
|
|||||||
{
|
{
|
||||||
Instruction* instr = module.getInstruction(typeId);
|
Instruction* instr = module.getInstruction(typeId);
|
||||||
|
|
||||||
OpCode typeClass = instr->getOpCode();
|
Op typeClass = instr->getOpCode();
|
||||||
switch (typeClass)
|
switch (typeClass)
|
||||||
{
|
{
|
||||||
case OpTypeVector:
|
case OpTypeVector:
|
||||||
@ -436,7 +436,7 @@ Id Builder::getContainedTypeId(Id typeId) const
|
|||||||
|
|
||||||
// See if a scalar constant of this type has already been created, so it
|
// See if a scalar constant of this type has already been created, so it
|
||||||
// can be reused rather than duplicated. (Required by the specification).
|
// can be reused rather than duplicated. (Required by the specification).
|
||||||
Id Builder::findScalarConstant(OpCode typeClass, Id typeId, unsigned value) const
|
Id Builder::findScalarConstant(Op typeClass, Id typeId, unsigned value) const
|
||||||
{
|
{
|
||||||
Instruction* constant;
|
Instruction* constant;
|
||||||
for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
|
for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
|
||||||
@ -515,7 +515,7 @@ Id Builder::makeDoubleConstant(double d)
|
|||||||
return NoResult;
|
return NoResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
Id Builder::findCompositeConstant(OpCode typeClass, std::vector<Id>& comps) const
|
Id Builder::findCompositeConstant(Op typeClass, std::vector<Id>& comps) const
|
||||||
{
|
{
|
||||||
Instruction* constant;
|
Instruction* constant;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@ -547,7 +547,7 @@ Id Builder::findCompositeConstant(OpCode typeClass, std::vector<Id>& comps) cons
|
|||||||
Id Builder::makeCompositeConstant(Id typeId, std::vector<Id>& members)
|
Id Builder::makeCompositeConstant(Id typeId, std::vector<Id>& members)
|
||||||
{
|
{
|
||||||
assert(typeId);
|
assert(typeId);
|
||||||
OpCode typeClass = getTypeClass(typeId);
|
Op typeClass = getTypeClass(typeId);
|
||||||
|
|
||||||
switch (typeClass) {
|
switch (typeClass) {
|
||||||
case OpTypeVector:
|
case OpTypeVector:
|
||||||
@ -735,7 +735,7 @@ void Builder::leaveFunction(bool main)
|
|||||||
if (function.getReturnType() == makeVoidType())
|
if (function.getReturnType() == makeVoidType())
|
||||||
makeReturn(true);
|
makeReturn(true);
|
||||||
else {
|
else {
|
||||||
Id retStorage = createVariable(StorageFunction, function.getReturnType(), "dummyReturn");
|
Id retStorage = createVariable(StorageClassFunction, function.getReturnType(), "dummyReturn");
|
||||||
Id retValue = createLoad(retStorage);
|
Id retValue = createLoad(retStorage);
|
||||||
makeReturn(true, retValue);
|
makeReturn(true, retValue);
|
||||||
}
|
}
|
||||||
@ -761,18 +761,18 @@ Id Builder::createVariable(StorageClass storageClass, Id type, const char* name)
|
|||||||
inst->addImmediateOperand(storageClass);
|
inst->addImmediateOperand(storageClass);
|
||||||
|
|
||||||
switch (storageClass) {
|
switch (storageClass) {
|
||||||
case StorageConstantUniform:
|
case StorageClassUniformConstant:
|
||||||
case StorageUniform:
|
case StorageClassUniform:
|
||||||
case StorageInput:
|
case StorageClassInput:
|
||||||
case StorageOutput:
|
case StorageClassOutput:
|
||||||
case StorageWorkgroupLocal:
|
case StorageClassWorkgroupLocal:
|
||||||
case StoragePrivateGlobal:
|
case StorageClassPrivateGlobal:
|
||||||
case StorageWorkgroupGlobal:
|
case StorageClassWorkgroupGlobal:
|
||||||
constantsTypesGlobals.push_back(inst);
|
constantsTypesGlobals.push_back(inst);
|
||||||
module.mapInstruction(inst);
|
module.mapInstruction(inst);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case StorageFunction:
|
case StorageClassFunction:
|
||||||
// Validation rules require the declaration in the entry block
|
// Validation rules require the declaration in the entry block
|
||||||
buildPoint->getParent().addLocalVariable(inst);
|
buildPoint->getParent().addLocalVariable(inst);
|
||||||
break;
|
break;
|
||||||
@ -878,14 +878,14 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, std::vecto
|
|||||||
}
|
}
|
||||||
|
|
||||||
// An opcode that has no operands, no result id, and no type
|
// An opcode that has no operands, no result id, and no type
|
||||||
void Builder::createNoResultOp(OpCode opCode)
|
void Builder::createNoResultOp(Op opCode)
|
||||||
{
|
{
|
||||||
Instruction* op = new Instruction(opCode);
|
Instruction* op = new Instruction(opCode);
|
||||||
buildPoint->addInstruction(op);
|
buildPoint->addInstruction(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
// An opcode that has one operand, no result id, and no type
|
// An opcode that has one operand, no result id, and no type
|
||||||
void Builder::createNoResultOp(OpCode opCode, Id operand)
|
void Builder::createNoResultOp(Op opCode, Id operand)
|
||||||
{
|
{
|
||||||
Instruction* op = new Instruction(opCode);
|
Instruction* op = new Instruction(opCode);
|
||||||
op->addIdOperand(operand);
|
op->addIdOperand(operand);
|
||||||
@ -908,7 +908,7 @@ void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemant
|
|||||||
}
|
}
|
||||||
|
|
||||||
// An opcode that has one operands, a result id, and a type
|
// An opcode that has one operands, a result id, and a type
|
||||||
Id Builder::createUnaryOp(OpCode opCode, Id typeId, Id operand)
|
Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
|
||||||
{
|
{
|
||||||
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
||||||
op->addIdOperand(operand);
|
op->addIdOperand(operand);
|
||||||
@ -917,7 +917,7 @@ Id Builder::createUnaryOp(OpCode opCode, Id typeId, Id operand)
|
|||||||
return op->getResultId();
|
return op->getResultId();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id Builder::createBinOp(OpCode opCode, Id typeId, Id left, Id right)
|
Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
|
||||||
{
|
{
|
||||||
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
||||||
op->addIdOperand(left);
|
op->addIdOperand(left);
|
||||||
@ -927,7 +927,7 @@ Id Builder::createBinOp(OpCode opCode, Id typeId, Id left, Id right)
|
|||||||
return op->getResultId();
|
return op->getResultId();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id Builder::createTriOp(OpCode opCode, Id typeId, Id op1, Id op2, Id op3)
|
Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
|
||||||
{
|
{
|
||||||
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
||||||
op->addIdOperand(op1);
|
op->addIdOperand(op1);
|
||||||
@ -938,7 +938,7 @@ Id Builder::createTriOp(OpCode opCode, Id typeId, Id op1, Id op2, Id op3)
|
|||||||
return op->getResultId();
|
return op->getResultId();
|
||||||
}
|
}
|
||||||
|
|
||||||
Id Builder::createTernaryOp(OpCode opCode, Id typeId, Id op1, Id op2, Id op3)
|
Id Builder::createTernaryOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
|
||||||
{
|
{
|
||||||
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
||||||
op->addIdOperand(op1);
|
op->addIdOperand(op1);
|
||||||
@ -1080,7 +1080,7 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool proj, co
|
|||||||
// Set up the instruction
|
// Set up the instruction
|
||||||
//
|
//
|
||||||
|
|
||||||
OpCode opCode;
|
Op opCode;
|
||||||
if (proj && parameters.gradX && parameters.offset)
|
if (proj && parameters.gradX && parameters.offset)
|
||||||
opCode = OpTextureSampleProjGradOffset;
|
opCode = OpTextureSampleProjGradOffset;
|
||||||
else if (proj && parameters.lod && parameters.offset)
|
else if (proj && parameters.lod && parameters.offset)
|
||||||
@ -1118,7 +1118,7 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool proj, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comments in header
|
// Comments in header
|
||||||
Id Builder::createTextureQueryCall(OpCode opCode, const TextureParameters& parameters)
|
Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters)
|
||||||
{
|
{
|
||||||
// Figure out the result type
|
// Figure out the result type
|
||||||
Id resultType;
|
Id resultType;
|
||||||
@ -1190,7 +1190,7 @@ Id Builder::createTextureQueryCall(OpCode opCode, const TextureParameters& param
|
|||||||
// Comments in header
|
// Comments in header
|
||||||
//Id Builder::createBitFieldExtractCall(Decoration precision, Id id, Id offset, Id bits, bool isSigned)
|
//Id Builder::createBitFieldExtractCall(Decoration precision, Id id, Id offset, Id bits, bool isSigned)
|
||||||
//{
|
//{
|
||||||
// OpCode opCode = isSigned ? sBitFieldExtract
|
// Op opCode = isSigned ? sBitFieldExtract
|
||||||
// : uBitFieldExtract;
|
// : uBitFieldExtract;
|
||||||
//
|
//
|
||||||
// if (isScalar(offset) == false || isScalar(bits) == false)
|
// if (isScalar(offset) == false || isScalar(bits) == false)
|
||||||
@ -1210,7 +1210,7 @@ Id Builder::createTextureQueryCall(OpCode opCode, const TextureParameters& param
|
|||||||
// Comments in header
|
// Comments in header
|
||||||
//Id Builder::createBitFieldInsertCall(Decoration precision, Id base, Id insert, Id offset, Id bits)
|
//Id Builder::createBitFieldInsertCall(Decoration precision, Id base, Id insert, Id offset, Id bits)
|
||||||
//{
|
//{
|
||||||
// OpCode opCode = bitFieldInsert;
|
// Op opCode = bitFieldInsert;
|
||||||
//
|
//
|
||||||
// if (isScalar(offset) == false || isScalar(bits) == false)
|
// if (isScalar(offset) == false || isScalar(bits) == false)
|
||||||
// MissingFunctionality("bitFieldInsert operand types");
|
// MissingFunctionality("bitFieldInsert operand types");
|
||||||
@ -1230,7 +1230,7 @@ Id Builder::createTextureQueryCall(OpCode opCode, const TextureParameters& param
|
|||||||
Id Builder::createCompare(Decoration precision, Id value1, Id value2, bool equal)
|
Id Builder::createCompare(Decoration precision, Id value1, Id value2, bool equal)
|
||||||
{
|
{
|
||||||
Instruction* compare = 0;
|
Instruction* compare = 0;
|
||||||
spv::OpCode binOp = spv::OpNop;
|
spv::Op binOp = spv::OpNop;
|
||||||
Id boolType = makeBoolType();
|
Id boolType = makeBoolType();
|
||||||
Id valueType = getTypeId(value1);
|
Id valueType = getTypeId(value1);
|
||||||
|
|
||||||
@ -1242,7 +1242,7 @@ Id Builder::createCompare(Decoration precision, Id value1, Id value2, bool equal
|
|||||||
if (isVectorType(valueType)) {
|
if (isVectorType(valueType)) {
|
||||||
Id boolVectorType = makeVectorType(boolType, getNumTypeComponents(valueType));
|
Id boolVectorType = makeVectorType(boolType, getNumTypeComponents(valueType));
|
||||||
Id boolVector;
|
Id boolVector;
|
||||||
OpCode op;
|
Op op;
|
||||||
if (getMostBasicTypeClass(valueType) == OpTypeFloat)
|
if (getMostBasicTypeClass(valueType) == OpTypeFloat)
|
||||||
op = equal ? OpFOrdEqual : OpFOrdNotEqual;
|
op = equal ? OpFOrdEqual : OpFOrdNotEqual;
|
||||||
else
|
else
|
||||||
@ -1307,9 +1307,9 @@ Id Builder::createCompare(Decoration precision, Id value1, Id value2, bool equal
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comments in header
|
// Comments in header
|
||||||
//Id Builder::createOperation(Decoration precision, OpCode opCode, Id operand)
|
//Id Builder::createOperation(Decoration precision, Op opCode, Id operand)
|
||||||
//{
|
//{
|
||||||
// OpCode* opCode = 0;
|
// Op* opCode = 0;
|
||||||
//
|
//
|
||||||
// // Handle special return types here. Things that don't have same result type as parameter
|
// // Handle special return types here. Things that don't have same result type as parameter
|
||||||
// switch (opCode) {
|
// switch (opCode) {
|
||||||
@ -1362,7 +1362,7 @@ Id Builder::createCompare(Decoration precision, Id value1, Id value2, bool equal
|
|||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
//// Comments in header
|
//// Comments in header
|
||||||
//Id Builder::createOperation(Decoration precision, OpCode opCode, Id operand0, Id operand1)
|
//Id Builder::createOperation(Decoration precision, Op opCode, Id operand0, Id operand1)
|
||||||
//{
|
//{
|
||||||
// Function* opCode = 0;
|
// Function* opCode = 0;
|
||||||
//
|
//
|
||||||
@ -1393,7 +1393,7 @@ Id Builder::createCompare(Decoration precision, Id value1, Id value2, bool equal
|
|||||||
// return instr;
|
// return instr;
|
||||||
//}
|
//}
|
||||||
//
|
//
|
||||||
//Id Builder::createOperation(Decoration precision, OpCode opCode, Id operand0, Id operand1, Id operand2)
|
//Id Builder::createOperation(Decoration precision, Op opCode, Id operand0, Id operand1, Id operand2)
|
||||||
//{
|
//{
|
||||||
// Function* opCode;
|
// Function* opCode;
|
||||||
//
|
//
|
||||||
@ -1608,7 +1608,7 @@ void Builder::If::makeEndIf()
|
|||||||
|
|
||||||
// Go back to the headerBlock and make the flow control split
|
// Go back to the headerBlock and make the flow control split
|
||||||
builder.setBuildPoint(headerBlock);
|
builder.setBuildPoint(headerBlock);
|
||||||
builder.createMerge(OpSelectionMerge, mergeBlock, SelectControlNone);
|
builder.createMerge(OpSelectionMerge, mergeBlock, SelectionControlMaskNone);
|
||||||
if (elseBlock)
|
if (elseBlock)
|
||||||
builder.createConditionalBranch(condition, thenBlock, elseBlock);
|
builder.createConditionalBranch(condition, thenBlock, elseBlock);
|
||||||
else
|
else
|
||||||
@ -1632,7 +1632,7 @@ void Builder::makeSwitch(Id selector, int numSegments, std::vector<int>& caseVal
|
|||||||
Block* mergeBlock = new Block(getUniqueId(), function);
|
Block* mergeBlock = new Block(getUniqueId(), function);
|
||||||
|
|
||||||
// make and insert the switch's selection-merge instruction
|
// make and insert the switch's selection-merge instruction
|
||||||
createMerge(OpSelectionMerge, mergeBlock, SelectControlNone);
|
createMerge(OpSelectionMerge, mergeBlock, SelectionControlMaskNone);
|
||||||
|
|
||||||
// make the switch instruction
|
// make the switch instruction
|
||||||
Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
|
Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
|
||||||
@ -1706,7 +1706,7 @@ void Builder::createLoopHeaderBranch(Id condition)
|
|||||||
Loop loop = loops.top();
|
Loop loop = loops.top();
|
||||||
|
|
||||||
Block* body = new Block(getUniqueId(), *loop.function);
|
Block* body = new Block(getUniqueId(), *loop.function);
|
||||||
createMerge(OpLoopMerge, loop.merge, LoopControlNone);
|
createMerge(OpLoopMerge, loop.merge, LoopControlMaskNone);
|
||||||
createConditionalBranch(condition, body, loop.merge);
|
createConditionalBranch(condition, body, loop.merge);
|
||||||
loop.function->addBlock(body);
|
loop.function->addBlock(body);
|
||||||
setBuildPoint(body);
|
setBuildPoint(body);
|
||||||
@ -1831,7 +1831,7 @@ Id Builder::accessChainLoad(Decoration precision)
|
|||||||
id = createCompositeExtract(accessChain.base, accessChain.resultType, indexes);
|
id = createCompositeExtract(accessChain.base, accessChain.resultType, indexes);
|
||||||
else {
|
else {
|
||||||
// make a new function variable for this r-value
|
// make a new function variable for this r-value
|
||||||
Id lValue = createVariable(StorageFunction, getTypeId(accessChain.base), "indexable");
|
Id lValue = createVariable(StorageClassUniform, getTypeId(accessChain.base), "indexable");
|
||||||
|
|
||||||
// store into it
|
// store into it
|
||||||
createStore(accessChain.base, lValue);
|
createStore(accessChain.base, lValue);
|
||||||
@ -1887,7 +1887,7 @@ void Builder::dump(std::vector<unsigned int>& out) const
|
|||||||
out.push_back(0);
|
out.push_back(0);
|
||||||
|
|
||||||
// First instructions, some created on the spot here:
|
// First instructions, some created on the spot here:
|
||||||
if (source != LangUnknown) {
|
if (source != SourceLanguageUnknown) {
|
||||||
Instruction sourceInst(0, 0, OpSource);
|
Instruction sourceInst(0, 0, OpSource);
|
||||||
sourceInst.addImmediateOperand(source);
|
sourceInst.addImmediateOperand(source);
|
||||||
sourceInst.addImmediateOperand(sourceVersion);
|
sourceInst.addImmediateOperand(sourceVersion);
|
||||||
@ -1979,7 +1979,7 @@ void Builder::createBranch(Block* block)
|
|||||||
block->addPredecessor(buildPoint);
|
block->addPredecessor(buildPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builder::createMerge(OpCode mergeCode, Block* mergeBlock, unsigned int control)
|
void Builder::createMerge(Op mergeCode, Block* mergeBlock, unsigned int control)
|
||||||
{
|
{
|
||||||
Instruction* merge = new Instruction(mergeCode);
|
Instruction* merge = new Instruction(mergeCode);
|
||||||
merge->addIdOperand(mergeBlock->getId());
|
merge->addIdOperand(mergeBlock->getId());
|
||||||
|
@ -106,14 +106,14 @@ public:
|
|||||||
samplerContentImage,
|
samplerContentImage,
|
||||||
samplerContentTextureFilter
|
samplerContentTextureFilter
|
||||||
};
|
};
|
||||||
Id makeSampler(Id sampledType, Dimensionality, samplerContent, bool arrayed, bool shadow, bool ms);
|
Id makeSampler(Id sampledType, Dim, samplerContent, bool arrayed, bool shadow, bool ms);
|
||||||
|
|
||||||
// For querying about types.
|
// For querying about types.
|
||||||
Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
|
Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
|
||||||
Id getDerefTypeId(Id resultId) const;
|
Id getDerefTypeId(Id resultId) const;
|
||||||
OpCode getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); }
|
Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); }
|
||||||
OpCode getTypeClass(Id typeId) const { return getOpCode(typeId); }
|
Op getTypeClass(Id typeId) const { return getOpCode(typeId); }
|
||||||
OpCode getMostBasicTypeClass(Id typeId) const;
|
Op getMostBasicTypeClass(Id typeId) const;
|
||||||
int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
|
int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
|
||||||
int getNumTypeComponents(Id typeId) const;
|
int getNumTypeComponents(Id typeId) const;
|
||||||
Id getScalarTypeId(Id typeId) const;
|
Id getScalarTypeId(Id typeId) const;
|
||||||
@ -151,10 +151,10 @@ public:
|
|||||||
}
|
}
|
||||||
int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
|
int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
|
||||||
|
|
||||||
Dimensionality getDimensionality(Id resultId) const
|
Dim getDimensionality(Id resultId) const
|
||||||
{
|
{
|
||||||
assert(isSamplerType(getTypeId(resultId)));
|
assert(isSamplerType(getTypeId(resultId)));
|
||||||
return (Dimensionality)module.getInstruction(getTypeId(resultId))->getImmediateOperand(1);
|
return (Dim)module.getInstruction(getTypeId(resultId))->getImmediateOperand(1);
|
||||||
}
|
}
|
||||||
bool isArrayedSampler(Id resultId) const
|
bool isArrayedSampler(Id resultId) const
|
||||||
{
|
{
|
||||||
@ -228,14 +228,14 @@ public:
|
|||||||
Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index);
|
Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index);
|
||||||
Id createCompositeInsert(Id object, Id composite, Id typeId, std::vector<unsigned>& indexes);
|
Id createCompositeInsert(Id object, Id composite, Id typeId, std::vector<unsigned>& indexes);
|
||||||
|
|
||||||
void createNoResultOp(OpCode);
|
void createNoResultOp(Op);
|
||||||
void createNoResultOp(OpCode, Id operand);
|
void createNoResultOp(Op, Id operand);
|
||||||
void createControlBarrier(unsigned executionScope);
|
void createControlBarrier(unsigned executionScope);
|
||||||
void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics);
|
void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics);
|
||||||
Id createUnaryOp(OpCode, Id typeId, Id operand);
|
Id createUnaryOp(Op, Id typeId, Id operand);
|
||||||
Id createBinOp(OpCode, Id typeId, Id operand1, Id operand2);
|
Id createBinOp(Op, Id typeId, Id operand1, Id operand2);
|
||||||
Id createTriOp(OpCode, Id typeId, Id operand1, Id operand2, Id operand3);
|
Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
|
||||||
Id createTernaryOp(OpCode, Id typeId, Id operand1, Id operand2, Id operand3);
|
Id createTernaryOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
|
||||||
Id createFunctionCall(spv::Function*, std::vector<spv::Id>&);
|
Id createFunctionCall(spv::Function*, std::vector<spv::Id>&);
|
||||||
|
|
||||||
// Take an rvalue (source) and a set of channels to extract from it to
|
// Take an rvalue (source) and a set of channels to extract from it to
|
||||||
@ -289,7 +289,7 @@ public:
|
|||||||
|
|
||||||
// Emit the OpTextureQuery* instruction that was passed in.
|
// Emit the OpTextureQuery* instruction that was passed in.
|
||||||
// Figure out the right return value and type, and return it.
|
// Figure out the right return value and type, and return it.
|
||||||
Id createTextureQueryCall(OpCode, const TextureParameters&);
|
Id createTextureQueryCall(Op, const TextureParameters&);
|
||||||
|
|
||||||
Id createSamplePositionCall(Decoration precision, Id, Id);
|
Id createSamplePositionCall(Decoration precision, Id, Id);
|
||||||
|
|
||||||
@ -461,13 +461,13 @@ public:
|
|||||||
void dump(std::vector<unsigned int>&) const;
|
void dump(std::vector<unsigned int>&) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Id findScalarConstant(OpCode typeClass, Id typeId, unsigned value) const;
|
Id findScalarConstant(Op typeClass, Id typeId, unsigned value) const;
|
||||||
Id findCompositeConstant(OpCode typeClass, std::vector<Id>& comps) const;
|
Id findCompositeConstant(Op typeClass, std::vector<Id>& comps) const;
|
||||||
Id collapseAccessChain();
|
Id collapseAccessChain();
|
||||||
void simplifyAccessChainSwizzle();
|
void simplifyAccessChainSwizzle();
|
||||||
void createAndSetNoPredecessorBlock(const char*);
|
void createAndSetNoPredecessorBlock(const char*);
|
||||||
void createBranch(Block* block);
|
void createBranch(Block* block);
|
||||||
void createMerge(OpCode, Block*, unsigned int control);
|
void createMerge(Op, Block*, unsigned int control);
|
||||||
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
|
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
|
||||||
void dumpInstructions(std::vector<unsigned int>&, const std::vector<Instruction*>&) const;
|
void dumpInstructions(std::vector<unsigned int>&, const std::vector<Instruction*>&) const;
|
||||||
|
|
||||||
|
@ -40,10 +40,11 @@
|
|||||||
// Disassembler for SPIR-V.
|
// Disassembler for SPIR-V.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "stdlib.h"
|
|
||||||
|
|
||||||
#include "GLSL450Lib.h"
|
#include "GLSL450Lib.h"
|
||||||
extern const char* GlslStd450DebugNames[GLSL_STD_450::Count];
|
extern const char* GlslStd450DebugNames[GLSL_STD_450::Count];
|
||||||
@ -69,7 +70,7 @@ public:
|
|||||||
void processInstructions();
|
void processInstructions();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
OpCode getOpCode(int id) const { return idInstruction[id] ? (OpCode)(stream[idInstruction[id]] & OpCodeMask) : OpNop; }
|
Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; }
|
||||||
|
|
||||||
// Output methods
|
// Output methods
|
||||||
void outputIndent();
|
void outputIndent();
|
||||||
@ -80,7 +81,7 @@ protected:
|
|||||||
void disassembleImmediates(int numOperands);
|
void disassembleImmediates(int numOperands);
|
||||||
void disassembleIds(int numOperands);
|
void disassembleIds(int numOperands);
|
||||||
void disassembleString();
|
void disassembleString();
|
||||||
void disassembleInstruction(Id resultId, Id typeId, OpCode opCode, int numOperands);
|
void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
std::ostream& out; // where to write the disassembly
|
std::ostream& out; // where to write the disassembly
|
||||||
@ -144,7 +145,7 @@ void SpirvStream::processInstructions()
|
|||||||
// Instruction wordCount and opcode
|
// Instruction wordCount and opcode
|
||||||
unsigned int firstWord = stream[word];
|
unsigned int firstWord = stream[word];
|
||||||
unsigned wordCount = firstWord >> WordCountShift;
|
unsigned wordCount = firstWord >> WordCountShift;
|
||||||
OpCode opCode = (OpCode)(firstWord & OpCodeMask);
|
Op opCode = (Op)(firstWord & OpCodeMask);
|
||||||
int nextInst = word + wordCount;
|
int nextInst = word + wordCount;
|
||||||
++word;
|
++word;
|
||||||
|
|
||||||
@ -176,7 +177,7 @@ void SpirvStream::processInstructions()
|
|||||||
outputTypeId(typeId);
|
outputTypeId(typeId);
|
||||||
outputIndent();
|
outputIndent();
|
||||||
|
|
||||||
// Hand off the OpCode and all its operands
|
// Hand off the Op and all its operands
|
||||||
disassembleInstruction(resultId, typeId, opCode, numOperands);
|
disassembleInstruction(resultId, typeId, opCode, numOperands);
|
||||||
if (word != nextInst) {
|
if (word != nextInst) {
|
||||||
out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;
|
out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;
|
||||||
@ -277,14 +278,11 @@ void SpirvStream::disassembleString()
|
|||||||
out << "\"";
|
out << "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvStream::disassembleInstruction(Id resultId, Id typeId, OpCode opCode, int numOperands)
|
void SpirvStream::disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands)
|
||||||
{
|
{
|
||||||
// Process the opcode
|
// Process the opcode
|
||||||
|
|
||||||
if (opCode < 0 || opCode >= OpCount)
|
out << (OpcodeString(opCode) + 2); // leave out the "Op"
|
||||||
Kill(out, "Bad opcode");
|
|
||||||
else
|
|
||||||
out << InstructionDesc[opCode].opName + 2; // Skip the "Op"
|
|
||||||
|
|
||||||
if (opCode == OpLoopMerge || opCode == OpSelectionMerge)
|
if (opCode == OpLoopMerge || opCode == OpSelectionMerge)
|
||||||
nextNestedControl = stream[word];
|
nextNestedControl = stream[word];
|
||||||
@ -339,7 +337,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id typeId, OpCode opCode,
|
|||||||
// Handle textures specially, so can put out helpful strings.
|
// Handle textures specially, so can put out helpful strings.
|
||||||
if (opCode == OpTypeSampler) {
|
if (opCode == OpTypeSampler) {
|
||||||
disassembleIds(1);
|
disassembleIds(1);
|
||||||
out << " " << DimensionString((Dimensionality)stream[word++]);
|
out << " " << DimensionString((Dim)stream[word++]);
|
||||||
switch (stream[word++]) {
|
switch (stream[word++]) {
|
||||||
case 0: out << " texture"; break;
|
case 0: out << " texture"; break;
|
||||||
case 1: out << " image"; break;
|
case 1: out << " image"; break;
|
||||||
@ -354,7 +352,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id typeId, OpCode opCode,
|
|||||||
// Handle all the parameterized operands
|
// Handle all the parameterized operands
|
||||||
for (int op = 0; op < InstructionDesc[opCode].operands.getNum(); ++op) {
|
for (int op = 0; op < InstructionDesc[opCode].operands.getNum(); ++op) {
|
||||||
out << " ";
|
out << " ";
|
||||||
switch (InstructionDesc[opCode].operands.getClass(op)) {
|
OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op);
|
||||||
|
switch (operandClass) {
|
||||||
case OperandId:
|
case OperandId:
|
||||||
disassembleIds(1);
|
disassembleIds(1);
|
||||||
// Get names for printing "(XXX)" for readability, *after* this id
|
// Get names for printing "(XXX)" for readability, *after* this id
|
||||||
@ -366,7 +365,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id typeId, OpCode opCode,
|
|||||||
disassembleIds(numOperands);
|
disassembleIds(numOperands);
|
||||||
return;
|
return;
|
||||||
case OperandVariableLiterals:
|
case OperandVariableLiterals:
|
||||||
if (opCode == OpDecorate && stream[word - 1] == DecBuiltIn) {
|
if (opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) {
|
||||||
out << BuiltInString(stream[word++]);
|
out << BuiltInString(stream[word++]);
|
||||||
--numOperands;
|
--numOperands;
|
||||||
++op;
|
++op;
|
||||||
@ -376,8 +375,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id typeId, OpCode opCode,
|
|||||||
case OperandVariableLiteralId:
|
case OperandVariableLiteralId:
|
||||||
while (numOperands > 0) {
|
while (numOperands > 0) {
|
||||||
out << std::endl;
|
out << std::endl;
|
||||||
outputResultId(NoResult);
|
outputResultId(0);
|
||||||
outputTypeId(NoType);
|
outputTypeId(0);
|
||||||
outputIndent();
|
outputIndent();
|
||||||
out << " case ";
|
out << " case ";
|
||||||
disassembleImmediates(1);
|
disassembleImmediates(1);
|
||||||
@ -397,76 +396,23 @@ void SpirvStream::disassembleInstruction(Id resultId, Id typeId, OpCode opCode,
|
|||||||
case OperandLiteralString:
|
case OperandLiteralString:
|
||||||
disassembleString();
|
disassembleString();
|
||||||
return;
|
return;
|
||||||
case OperandSource:
|
|
||||||
out << SourceString((SourceLanguage)stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandExecutionModel:
|
|
||||||
out << ExecutionModelString((ExecutionModel)stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandAddressing:
|
|
||||||
out << AddressingString((AddressingModel)stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandMemory:
|
|
||||||
out << MemoryString((MemoryModel)stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandExecutionMode:
|
|
||||||
out << ExecutionModeString((ExecutionMode)stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandStorage:
|
|
||||||
out << StorageClassString((StorageClass)stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandDimensionality:
|
|
||||||
out << DimensionString((Dimensionality)stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandDecoration:
|
|
||||||
out << DecorationString((Decoration)stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandBuiltIn:
|
|
||||||
out << BuiltInString((BuiltIn)stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandSelect:
|
|
||||||
out << SelectControlString((SelectControl)stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandLoop:
|
|
||||||
out << LoopControlString((LoopControl)stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandFunction:
|
|
||||||
{
|
|
||||||
unsigned int control = stream[word++];
|
|
||||||
if (control == 0)
|
|
||||||
out << FunctionControlString(control);
|
|
||||||
else {
|
|
||||||
for (int m = 0; m < FunctionControlCount; ++m) {
|
|
||||||
if (control & (1 << m))
|
|
||||||
out << FunctionControlString(m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OperandMemorySemantics:
|
|
||||||
for (int shift = 0; shift < MemorySemanticsCount; ++shift) {
|
|
||||||
unsigned lit = (stream[word] & (1 << shift));
|
|
||||||
if (lit)
|
|
||||||
out << MemorySemanticsString(lit) << " ";
|
|
||||||
}
|
|
||||||
word++;
|
|
||||||
break;
|
|
||||||
case OperandMemoryAccess:
|
|
||||||
out << MemoryAccessString(stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandExecutionScope:
|
|
||||||
out << ExecutionScopeString(stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandGroupOperation:
|
|
||||||
out << GroupOperationString(stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandKernelEnqueueFlags:
|
|
||||||
out << KernelEnqueueFlagsString(stream[word++]);
|
|
||||||
break;
|
|
||||||
case OperandKernelProfilingInfo:
|
|
||||||
out << KernelProfilingInfoString(stream[word++]);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
|
assert(operandClass >= OperandSource && operandClass < OperandOpcode);
|
||||||
|
|
||||||
|
if (OperandClassParams[operandClass].bitmask) {
|
||||||
|
unsigned int mask = stream[word++];
|
||||||
|
if (mask == 0)
|
||||||
|
out << "None";
|
||||||
|
else {
|
||||||
|
for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {
|
||||||
|
if (mask & (1 << m))
|
||||||
|
out << OperandClassParams[operandClass].getName(m) << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
out << OperandClassParams[operandClass].getName(stream[word++]);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
--numOperands;
|
--numOperands;
|
||||||
|
3428
SPIRV/doc.cpp
3428
SPIRV/doc.cpp
File diff suppressed because it is too large
Load Diff
108
SPIRV/doc.h
108
SPIRV/doc.h
@ -37,8 +37,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return English versions of instruction/operand information.
|
// Parameterize the SPIR-V enumerants.
|
||||||
// This can be used for disassembly, printing documentation, etc.
|
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "spirv.h"
|
#include "spirv.h"
|
||||||
@ -47,7 +46,7 @@
|
|||||||
|
|
||||||
namespace spv {
|
namespace spv {
|
||||||
|
|
||||||
// Fill in all the parameters of the instruction set
|
// Fill in all the parameters
|
||||||
void Parameterize();
|
void Parameterize();
|
||||||
|
|
||||||
// Return the English names of all the enums.
|
// Return the English names of all the enums.
|
||||||
@ -76,6 +75,35 @@ const char* ExecutionScopeString(int);
|
|||||||
const char* GroupOperationString(int);
|
const char* GroupOperationString(int);
|
||||||
const char* KernelEnqueueFlagsString(int);
|
const char* KernelEnqueueFlagsString(int);
|
||||||
const char* KernelProfilingInfoString(int);
|
const char* KernelProfilingInfoString(int);
|
||||||
|
const char* OpcodeString(int);
|
||||||
|
|
||||||
|
// For grouping opcodes into subsections
|
||||||
|
enum OpcodeClass {
|
||||||
|
OpClassMisc, // default, until opcode is classified
|
||||||
|
OpClassDebug,
|
||||||
|
OpClassAnnotate,
|
||||||
|
OpClassExtension,
|
||||||
|
OpClassMode,
|
||||||
|
OpClassType,
|
||||||
|
OpClassConstant,
|
||||||
|
OpClassMemory,
|
||||||
|
OpClassFunction,
|
||||||
|
OpClassTexture,
|
||||||
|
OpClassConvert,
|
||||||
|
OpClassComposite,
|
||||||
|
OpClassArithmetic,
|
||||||
|
OpClassRelationalLogical,
|
||||||
|
OpClassDerivative,
|
||||||
|
OpClassFlowControl,
|
||||||
|
OpClassAtomic,
|
||||||
|
OpClassPrimitive,
|
||||||
|
OpClassBarrier,
|
||||||
|
OpClassGroup,
|
||||||
|
OpClassDeviceSideEnqueue,
|
||||||
|
OpClassPipe,
|
||||||
|
|
||||||
|
OpClassCount
|
||||||
|
};
|
||||||
|
|
||||||
// For parameterizing operands.
|
// For parameterizing operands.
|
||||||
enum OperandClass {
|
enum OperandClass {
|
||||||
@ -99,35 +127,85 @@ enum OperandClass {
|
|||||||
OperandFPFastMath,
|
OperandFPFastMath,
|
||||||
OperandFPRoundingMode,
|
OperandFPRoundingMode,
|
||||||
OperandLinkageType,
|
OperandLinkageType,
|
||||||
|
OperandAccessQualifier,
|
||||||
OperandFuncParamAttr,
|
OperandFuncParamAttr,
|
||||||
OperandDecoration,
|
OperandDecoration,
|
||||||
OperandBuiltIn,
|
OperandBuiltIn,
|
||||||
OperandSelect,
|
OperandSelect,
|
||||||
OperandLoop,
|
OperandLoop,
|
||||||
OperandFunction,
|
OperandFunction,
|
||||||
OperandAccessQualifier,
|
|
||||||
OperandMemorySemantics,
|
OperandMemorySemantics,
|
||||||
OperandMemoryAccess,
|
OperandMemoryAccess,
|
||||||
OperandExecutionScope,
|
OperandExecutionScope,
|
||||||
OperandGroupOperation,
|
OperandGroupOperation,
|
||||||
OperandKernelEnqueueFlags,
|
OperandKernelEnqueueFlags,
|
||||||
OperandKernelProfilingInfo,
|
OperandKernelProfilingInfo,
|
||||||
|
|
||||||
|
OperandOpcode,
|
||||||
|
|
||||||
OperandCount
|
OperandCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Set of capabilities. Generally, something is assumed to be in core,
|
||||||
|
// if nothing else is said. So, these are used to identify when something
|
||||||
|
// requires a specific capability to be declared.
|
||||||
|
enum Capability {
|
||||||
|
CapMatrix,
|
||||||
|
CapShader,
|
||||||
|
CapGeom,
|
||||||
|
CapTess,
|
||||||
|
CapAddr,
|
||||||
|
CapLink,
|
||||||
|
CapKernel
|
||||||
|
};
|
||||||
|
|
||||||
|
// Any specific enum can have a set of capabilities that allow it:
|
||||||
|
typedef std::vector<Capability> EnumCaps;
|
||||||
|
|
||||||
// Parameterize a set of operands with their OperandClass(es) and descriptions.
|
// Parameterize a set of operands with their OperandClass(es) and descriptions.
|
||||||
class OperandParameters {
|
class OperandParameters {
|
||||||
public:
|
public:
|
||||||
OperandParameters() { }
|
OperandParameters() { }
|
||||||
void push(OperandClass oc)
|
void push(OperandClass oc, const char* d)
|
||||||
{
|
{
|
||||||
opClass.push_back(oc);
|
opClass.push_back(oc);
|
||||||
|
desc.push_back(d);
|
||||||
}
|
}
|
||||||
OperandClass getClass(int op) const { return opClass[op]; }
|
OperandClass getClass(int op) const { return opClass[op]; }
|
||||||
|
const char* getDesc(int op) const { return desc[op]; }
|
||||||
int getNum() const { return (int)opClass.size(); }
|
int getNum() const { return (int)opClass.size(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<OperandClass> opClass;
|
std::vector<OperandClass> opClass;
|
||||||
|
std::vector<const char*> desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parameterize an enumerant
|
||||||
|
class EnumParameters {
|
||||||
|
public:
|
||||||
|
EnumParameters() : desc(0) { }
|
||||||
|
EnumCaps caps;
|
||||||
|
const char* desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parameterize a set of enumerants that form an enum
|
||||||
|
class EnumDefinition : public EnumParameters {
|
||||||
|
public:
|
||||||
|
EnumDefinition() :
|
||||||
|
ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { }
|
||||||
|
void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false)
|
||||||
|
{
|
||||||
|
ceiling = ceil;
|
||||||
|
getName = name;
|
||||||
|
bitmask = mask;
|
||||||
|
enumParams = ep;
|
||||||
|
}
|
||||||
|
void setOperands(OperandParameters* op) { operandParams = op; }
|
||||||
|
int ceiling; // ceiling of enumerants
|
||||||
|
bool bitmask; // true if these enumerants combine into a bitmask
|
||||||
|
const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift)
|
||||||
|
EnumParameters* enumParams; // parameters for each individual enumerant
|
||||||
|
OperandParameters* operandParams; // sets of operands
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parameterize an instruction's logical format, including its known set of operands,
|
// Parameterize an instruction's logical format, including its known set of operands,
|
||||||
@ -137,7 +215,8 @@ public:
|
|||||||
InstructionParameters() :
|
InstructionParameters() :
|
||||||
typePresent(true), // most normal, only exceptions have to be spelled out
|
typePresent(true), // most normal, only exceptions have to be spelled out
|
||||||
resultPresent(true), // most normal, only exceptions have to be spelled out
|
resultPresent(true), // most normal, only exceptions have to be spelled out
|
||||||
opName(0)
|
opDesc(0),
|
||||||
|
opClass(OpClassMisc)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void setResultAndType(bool r, bool t)
|
void setResultAndType(bool r, bool t)
|
||||||
@ -149,7 +228,9 @@ public:
|
|||||||
bool hasResult() const { return resultPresent != 0; }
|
bool hasResult() const { return resultPresent != 0; }
|
||||||
bool hasType() const { return typePresent != 0; }
|
bool hasType() const { return typePresent != 0; }
|
||||||
|
|
||||||
const char* opName;
|
const char* opDesc;
|
||||||
|
EnumCaps capabilities;
|
||||||
|
OpcodeClass opClass;
|
||||||
OperandParameters operands;
|
OperandParameters operands;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -157,8 +238,19 @@ protected:
|
|||||||
int resultPresent : 1;
|
int resultPresent : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const int OpcodeCeiling = 267;
|
||||||
|
|
||||||
// The set of objects that hold all the instruction/operand
|
// The set of objects that hold all the instruction/operand
|
||||||
// parameterization information.
|
// parameterization information.
|
||||||
extern InstructionParameters InstructionDesc[spv::OpCount];
|
extern InstructionParameters InstructionDesc[];
|
||||||
|
|
||||||
|
// These hold definitions of the enumerants used for operands
|
||||||
|
extern EnumDefinition OperandClassParams[];
|
||||||
|
|
||||||
|
const char* GetOperandDesc(OperandClass operand);
|
||||||
|
void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false);
|
||||||
|
const char* AccessQualifierString(int attr);
|
||||||
|
|
||||||
|
void PrintOperands(const OperandParameters& operands, int reservedOperands);
|
||||||
|
|
||||||
}; // end namespace spv
|
}; // end namespace spv
|
||||||
|
1835
SPIRV/spirv.h
1835
SPIRV/spirv.h
File diff suppressed because it is too large
Load Diff
@ -60,14 +60,21 @@ namespace spv {
|
|||||||
class Function;
|
class Function;
|
||||||
class Module;
|
class Module;
|
||||||
|
|
||||||
|
const Id NoResult = 0;
|
||||||
|
const Id NoType = 0;
|
||||||
|
|
||||||
|
const unsigned int BadValue = 0xFFFFFFFF;
|
||||||
|
const Decoration NoPrecision = (Decoration)BadValue;
|
||||||
|
const MemorySemanticsMask MemorySemanticsAllMemory = (MemorySemanticsMask)0x3FF;
|
||||||
|
|
||||||
//
|
//
|
||||||
// SPIR-V IR instruction.
|
// SPIR-V IR instruction.
|
||||||
//
|
//
|
||||||
|
|
||||||
class Instruction {
|
class Instruction {
|
||||||
public:
|
public:
|
||||||
Instruction(Id resultId, Id typeId, OpCode opCode) : resultId(resultId), typeId(typeId), opCode(opCode), string(0) { }
|
Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), string(0) { }
|
||||||
explicit Instruction(OpCode opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), string(0) { }
|
explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), string(0) { }
|
||||||
virtual ~Instruction()
|
virtual ~Instruction()
|
||||||
{
|
{
|
||||||
delete string;
|
delete string;
|
||||||
@ -103,7 +110,7 @@ public:
|
|||||||
|
|
||||||
originalString = str;
|
originalString = str;
|
||||||
}
|
}
|
||||||
OpCode getOpCode() const { return opCode; }
|
Op getOpCode() const { return opCode; }
|
||||||
int getNumOperands() const { return operands.size(); }
|
int getNumOperands() const { return operands.size(); }
|
||||||
Id getResultId() const { return resultId; }
|
Id getResultId() const { return resultId; }
|
||||||
Id getTypeId() const { return typeId; }
|
Id getTypeId() const { return typeId; }
|
||||||
@ -143,7 +150,7 @@ protected:
|
|||||||
Instruction(const Instruction&);
|
Instruction(const Instruction&);
|
||||||
Id resultId;
|
Id resultId;
|
||||||
Id typeId;
|
Id typeId;
|
||||||
OpCode opCode;
|
Op opCode;
|
||||||
std::vector<Id> operands;
|
std::vector<Id> operands;
|
||||||
std::vector<unsigned int>* string; // usually non-existent
|
std::vector<unsigned int>* string; // usually non-existent
|
||||||
std::string originalString; // could be optimized away; convenience for getting string operand
|
std::string originalString; // could be optimized away; convenience for getting string operand
|
||||||
@ -310,7 +317,7 @@ __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParam
|
|||||||
: parent(parent), functionInstruction(id, resultType, OpFunction)
|
: parent(parent), functionInstruction(id, resultType, OpFunction)
|
||||||
{
|
{
|
||||||
// OpFunction
|
// OpFunction
|
||||||
functionInstruction.addImmediateOperand(FunctionControlNone);
|
functionInstruction.addImmediateOperand(FunctionControlMaskNone);
|
||||||
functionInstruction.addIdOperand(functionType);
|
functionInstruction.addIdOperand(functionType);
|
||||||
parent.mapInstruction(&functionInstruction);
|
parent.mapInstruction(&functionInstruction);
|
||||||
parent.addFunction(this);
|
parent.addFunction(this);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user