//
-//Copyright (C) 2014 LunarG, Inc.
+// Copyright (C) 2014 LunarG, Inc.
//
-//All rights reserved.
+// All rights reserved.
//
-//Redistribution and use in source and binary forms, with or without
-//modification, are permitted provided that the following conditions
-//are met:
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
-//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-//POSSIBILITY OF SUCH DAMAGE.
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
//
// Author: John Kessenich, LunarG
#include "SpvBuilder.h"
#ifndef _WIN32
- #include <cstdio>
+#include <cstdio>
#endif
namespace spv {
-Builder::Builder(unsigned int magicNumber) :
- source(SourceLanguageUnknown),
- sourceVersion(0),
- addressModel(AddressingModelLogical),
- memoryModel(MemoryModelGLSL450),
- builderNumber(magicNumber),
- buildPoint(0),
- uniqueId(0),
- mainFunction(0)
+Builder::Builder(unsigned int magicNumber)
+ : source(SourceLanguageUnknown),
+ sourceVersion(0),
+ addressModel(AddressingModelLogical),
+ memoryModel(MemoryModelGLSL450),
+ builderNumber(magicNumber),
+ buildPoint(0),
+ uniqueId(0),
+ mainFunction(0)
{
clearAccessChain();
}
-Builder::~Builder()
-{
-}
-
+Builder::~Builder() {}
Id Builder::import(const char* name)
{
Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport);
import->addStringOperand(name);
-
+
imports.push_back(import);
return import->getResultId();
}
type = groupedTypes[OpTypeStruct][t];
if (type->getNumOperands() != 2)
continue;
- if (type->getIdOperand(0) != type0 ||
- type->getIdOperand(1) != type1)
+ if (type->getIdOperand(0) != type0 || type->getIdOperand(1) != type1)
continue;
return type->getResultId();
}
Instruction* type;
for (int t = 0; t < (int)groupedTypes[OpTypeVector].size(); ++t) {
type = groupedTypes[OpTypeVector][t];
- if (type->getIdOperand(0) == component &&
- type->getImmediateOperand(1) == (unsigned)size)
+ if (type->getIdOperand(0) == component && type->getImmediateOperand(1) == (unsigned)size)
return type->getResultId();
}
Instruction* type;
for (int t = 0; t < (int)groupedTypes[OpTypeMatrix].size(); ++t) {
type = groupedTypes[OpTypeMatrix][t];
- if (type->getIdOperand(0) == column &&
- type->getImmediateOperand(1) == (unsigned)cols)
+ if (type->getIdOperand(0) == column && type->getImmediateOperand(1) == (unsigned)cols)
return type->getResultId();
}
// try to find existing type
for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) {
type = groupedTypes[OpTypeArray][t];
- if (type->getIdOperand(0) == element &&
- type->getIdOperand(1) == sizeId)
+ if (type->getIdOperand(0) == element && type->getIdOperand(1) == sizeId)
return type->getResultId();
}
}
Instruction* type;
for (int t = 0; t < (int)groupedTypes[OpTypeFunction].size(); ++t) {
type = groupedTypes[OpTypeFunction][t];
- if (type->getIdOperand(0) != returnType || (int)paramTypes.size() != type->getNumOperands() - 1)
+ if (type->getIdOperand(0) != returnType ||
+ (int)paramTypes.size() != type->getNumOperands() - 1)
continue;
bool mismatch = false;
for (int p = 0; p < (int)paramTypes.size(); ++p) {
break;
}
}
- if (! mismatch)
+ if (!mismatch)
return type->getResultId();
}
return type->getResultId();
}
-Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
+Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms,
+ unsigned sampled, ImageFormat format)
{
// try to find it
Instruction* type;
type = groupedTypes[OpTypeImage][t];
if (type->getIdOperand(0) == sampledType &&
type->getImmediateOperand(1) == (unsigned int)dim &&
- type->getImmediateOperand(2) == ( depth ? 1u : 0u) &&
+ type->getImmediateOperand(2) == (depth ? 1u : 0u) &&
type->getImmediateOperand(3) == (arrayed ? 1u : 0u) &&
- type->getImmediateOperand(4) == ( ms ? 1u : 0u) &&
+ type->getImmediateOperand(4) == (ms ? 1u : 0u) &&
type->getImmediateOperand(5) == sampled &&
type->getImmediateOperand(6) == (unsigned int)format)
return type->getResultId();
// not found, make it
type = new Instruction(getUniqueId(), NoType, OpTypeImage);
type->addIdOperand(sampledType);
- type->addImmediateOperand( dim);
- type->addImmediateOperand( depth ? 1 : 0);
+ type->addImmediateOperand(dim);
+ type->addImmediateOperand(depth ? 1 : 0);
type->addImmediateOperand(arrayed ? 1 : 0);
- type->addImmediateOperand( ms ? 1 : 0);
+ type->addImmediateOperand(ms ? 1 : 0);
type->addImmediateOperand(sampled);
type->addImmediateOperand((unsigned int)format);
Instruction* instr = module.getInstruction(typeId);
Op typeClass = instr->getOpCode();
- switch (typeClass)
- {
+ switch (typeClass) {
case OpTypeVoid:
case OpTypeBool:
case OpTypeInt:
{
Instruction* instr = module.getInstruction(typeId);
- switch (instr->getOpCode())
- {
+ switch (instr->getOpCode()) {
case OpTypeBool:
case OpTypeInt:
case OpTypeFloat:
Instruction* instr = module.getInstruction(typeId);
Op typeClass = instr->getOpCode();
- switch (typeClass)
- {
+ switch (typeClass) {
case OpTypeVoid:
case OpTypeBool:
case OpTypeInt:
Instruction* instr = module.getInstruction(typeId);
Op typeClass = instr->getOpCode();
- switch (typeClass)
- {
+ switch (typeClass) {
case OpTypeVector:
case OpTypeMatrix:
case OpTypeArray:
}
// Return the immediately contained type of a given composite type.
-Id Builder::getContainedTypeId(Id typeId) const
-{
- return getContainedTypeId(typeId, 0);
-}
-
+Id Builder::getContainedTypeId(Id typeId) const { return getContainedTypeId(typeId, 0); }
// See if a scalar constant of this type has already been created, so it
// can be reused rather than duplicated. (Required by the specification).
Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const
Instruction* constant;
for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
constant = groupedConstants[typeClass][i];
- if (constant->getOpCode() == opcode &&
- constant->getTypeId() == typeId &&
+ if (constant->getOpCode() == opcode && constant->getTypeId() == typeId &&
constant->getImmediateOperand(0) == value)
return constant->getResultId();
}
Instruction* constant;
for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
constant = groupedConstants[typeClass][i];
- if (constant->getOpCode() == opcode &&
- constant->getTypeId() == typeId &&
- constant->getImmediateOperand(0) == v1 &&
- constant->getImmediateOperand(1) == v2)
+ if (constant->getOpCode() == opcode && constant->getTypeId() == typeId &&
+ constant->getImmediateOperand(0) == v1 && constant->getImmediateOperand(1) == v2)
return constant->getResultId();
}
bool Builder::isConstantOpCode(Op opcode) const
{
switch (opcode) {
- case OpUndef:
+ case OpUndef:
case OpConstantTrue:
case OpConstantFalse:
case OpConstant:
{
Id typeId = makeBoolType();
Instruction* constant;
- Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse) : (b ? OpConstantTrue : OpConstantFalse);
+ Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse)
+ : (b ? OpConstantTrue : OpConstantFalse);
// See if we already made it
Id existing = 0;
break;
}
}
- if (! mismatch) {
+ if (!mismatch) {
found = true;
break;
}
}
// Currently relying on the fact that all 'value' of interest are small non-negative values.
-void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2, int value3)
+void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2,
+ int value3)
{
Instruction* instr = new Instruction(OpExecutionMode);
instr->addIdOperand(entryPoint->getId());
// Comments in header
Function* Builder::makeMain()
{
- assert(! mainFunction);
+ assert(!mainFunction);
Block* entry;
std::vector<Id> params;
}
// Comments in header
-Function* Builder::makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes, Block **entry)
+Function* Builder::makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes,
+ Block** entry)
{
Id typeId = makeFunctionType(returnType, paramTypes);
Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size());
} else
buildPoint->addInstruction(new Instruction(NoResult, NoType, OpReturn));
- if (! implicit)
+ if (!implicit)
createAndSetNoPredecessorBlock("post-return");
}
assert(block);
// If our function did not contain a return, add a return void now.
- if (! block->isTerminated()) {
-
+ if (!block->isTerminated()) {
// Whether we're in an unreachable (non-entry) block.
bool unreachable = function.getEntryBlock() != block && block->getNumPredecessors() == 0;
// Comments in header
Id Builder::createUndefined(Id type)
{
- Instruction* inst = new Instruction(getUniqueId(), type, OpUndef);
- buildPoint->addInstruction(inst);
- return inst->getResultId();
+ Instruction* inst = new Instruction(getUniqueId(), type, OpUndef);
+ buildPoint->addInstruction(inst);
+ return inst->getResultId();
}
// Comments in header
return insert->getResultId();
}
-Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, std::vector<unsigned>& indexes)
+Id Builder::createCompositeInsert(Id object, Id composite, Id typeId,
+ std::vector<unsigned>& indexes)
{
Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert);
insert->addIdOperand(object);
int direction = getNumComponents(right) - getNumComponents(left);
if (direction > 0)
- left = smearScalar(precision, left, makeVectorType(getTypeId(left), getNumComponents(right)));
+ left =
+ smearScalar(precision, left, makeVectorType(getTypeId(left), getNumComponents(right)));
else if (direction < 0)
- right = smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left)));
+ right =
+ smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left)));
return;
}
}
// Comments in header
-Id Builder::createBuiltinCall(Decoration /*precision*/, Id resultType, Id builtins, int entryPoint, std::vector<Id>& args)
+Id Builder::createBuiltinCall(Decoration /*precision*/, Id resultType, Id builtins, int entryPoint,
+ std::vector<Id>& args)
{
Instruction* inst = new Instruction(getUniqueId(), resultType, OpExtInst);
inst->addIdOperand(builtins);
// Accept all parameters needed to create a texture instruction.
// Create the correct instruction based on the inputs, and make the call.
-Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, bool gather, const TextureParameters& parameters)
+Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj,
+ bool gather, const TextureParameters& parameters)
{
static const int maxTextureArgs = 10;
Id texArgs[maxTextureArgs] = {};
//
// Set up the optional arguments
//
- int optArgNum = numArgs; // track which operand, if it exists, is the mask of optional arguments
- ++numArgs; // speculatively make room for the mask operand
- ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand
+ int optArgNum =
+ numArgs; // track which operand, if it exists, is the mask of optional arguments
+ ++numArgs; // speculatively make room for the mask operand
+ ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand
if (parameters.bias) {
mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask);
texArgs[numArgs++] = parameters.bias;
// This happens when a legacy shadow*() call is made, which
// gets a vec4 back instead of a float.
Id smearedType = resultType;
- if (! isScalarType(resultType)) {
+ if (!isScalarType(resultType)) {
switch (opCode) {
case OpImageSampleDrefImplicitLod:
case OpImageSampleDrefExplicitLod:
Id resultType = 0;
switch (opCode) {
case OpImageQuerySize:
- case OpImageQuerySizeLod:
- {
+ case OpImageQuerySizeLod: {
int numComponents;
switch (getTypeDimensionality(getImageType(parameters.sampler))) {
case Dim1D:
if (constituent == 0)
resultId = subResultId;
else
- resultId = createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId);
+ resultId =
+ createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId);
}
return resultId;
// OpCompositeConstruct
Id Builder::createCompositeConstruct(Id typeId, std::vector<Id>& constituents)
{
- assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
+ assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 &&
+ getNumTypeConstituents(typeId) == (int)constituents.size()));
Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
for (int c = 0; c < (int)constituents.size(); ++c)
Id scalarTypeId = getScalarTypeId(resultTypeId);
std::vector<Id> constituents; // accumulate the arguments for OpCompositeConstruct
for (unsigned int i = 0; i < sources.size(); ++i) {
- assert(! isAggregate(sources[i]));
+ assert(!isAggregate(sources[i]));
unsigned int sourceSize = getNumComponents(sources[i]);
unsigned int sourcesToUse = sourceSize;
if (sourcesToUse + targetComponent > numTargetComponents)
}
// Comments in header
-Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
+Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>& sources,
+ Id resultTypeId)
{
Id componentTypeId = getScalarTypeId(resultTypeId);
int numCols = getTypeNumColumns(resultTypeId);
// initialize the array to the identity matrix
Id ids[maxMatrixSize][maxMatrixSize];
- Id one = makeFloatConstant(1.0);
+ Id one = makeFloatConstant(1.0);
Id zero = makeFloatConstant(0.0);
for (int col = 0; col < 4; ++col) {
for (int row = 0; row < 4; ++row) {
for (int col = 0; col < 4; ++col)
ids[col][col] = sources[0];
} else if (isMatrix(sources[0])) {
- // constructing from another matrix; copy over the parts that exist in both the argument and constructee
+ // constructing from another matrix; copy over the parts that exist in both the argument and
+ // constructee
Id matrix = sources[0];
int minCols = std::min(numCols, getNumColumns(matrix));
int minRows = std::min(numRows, getNumRows(matrix));
}
}
-
// Step 2: Construct a matrix from that array.
// First make the column vectors, then make the matrix.
}
// Comments in header
-Builder::If::If(Id cond, Builder& gb) :
- builder(gb),
- condition(cond),
- elseBlock(0)
+Builder::If::If(Id cond, Builder& gb) : builder(gb), condition(cond), elseBlock(0)
{
function = &builder.getBuildPoint()->getParent();
}
// Comments in header
-void Builder::makeSwitch(Id selector, int numSegments, std::vector<int>& caseValues, std::vector<int>& valueIndexToSegment, int defaultSegment,
+void Builder::makeSwitch(Id selector, int numSegments, std::vector<int>& caseValues,
+ std::vector<int>& valueIndexToSegment, int defaultSegment,
std::vector<Block*>& segmentBlocks)
{
Function& function = buildPoint->getParent();
// make the switch instruction
Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
switchInst->addIdOperand(selector);
- switchInst->addIdOperand(defaultSegment >= 0 ? segmentBlocks[defaultSegment]->getId() : mergeBlock->getId());
+ switchInst->addIdOperand(defaultSegment >= 0 ? segmentBlocks[defaultSegment]->getId()
+ : mergeBlock->getId());
for (int i = 0; i < (int)caseValues.size(); ++i) {
switchInst->addImmediateOperand(caseValues[i]);
switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId());
int lastSegment = nextSegment - 1;
if (lastSegment >= 0) {
// Close out previous segment by jumping, if necessary, to next segment
- if (! buildPoint->isTerminated())
+ if (!buildPoint->isTerminated())
createBranch(segmentBlock[nextSegment]);
}
Block* block = segmentBlock[nextSegment];
void Builder::endSwitch(std::vector<Block*>& /*segmentBlock*/)
{
// Close out previous segment by jumping, if necessary, to next segment
- if (! buildPoint->isTerminated())
+ if (!buildPoint->isTerminated())
addSwitchBreak();
switchMerges.top()->getParent().addBlock(switchMerges.top());
Id source = NoResult;
if (accessChain.swizzle.size()) {
Id tempBaseId = createLoad(base);
- source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, rvalue, accessChain.swizzle);
+ source =
+ createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, rvalue, accessChain.swizzle);
}
// dynamic component selection
if (accessChain.component != NoResult) {
Id tempBaseId = (source == NoResult) ? createLoad(base) : source;
- source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue, accessChain.component);
+ source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue,
+ accessChain.component);
}
if (source == NoResult)
// transfer access chain, but keep it static, so we can stay in registers
transferAccessChainSwizzle(false);
if (accessChain.indexChain.size() > 0) {
- Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType;
-
+ Id swizzleBase = accessChain.preSwizzleBaseType != NoType
+ ? accessChain.preSwizzleBaseType
+ : resultType;
+
// if all the accesses are constants, we can use OpCompositeExtract
std::vector<unsigned> indexes;
bool constant = true;
id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
else {
// make a new function variable for this r-value
- Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
+ Id lValue =
+ createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
// store into it
createStore(accessChain.base, lValue);
if (accessChain.indexChain.size() > 0) {
if (accessChain.instr == 0) {
- StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base));
- accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain);
+ StorageClass storageClass =
+ (StorageClass)module.getStorageClass(getTypeId(accessChain.base));
+ accessChain.instr =
+ createAccessChain(storageClass, accessChain.base, accessChain.indexChain);
}
return accessChain.instr;
buildPoint->getParent().addBlock(block);
setBuildPoint(block);
- //if (name)
+ // if (name)
// addName(block->getId(), name);
}
elseBlock->addPredecessor(buildPoint);
}
-void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<Instruction*>& instructions) const
+void Builder::dumpInstructions(std::vector<unsigned int>& out,
+ const std::vector<Instruction*>& instructions) const
{
for (int i = 0; i < (int)instructions.size(); ++i) {
instructions[i]->dump(out);
}
}
-void MissingFunctionality(const char* fun)
-{
- printf("Missing functionality: %s\n", fun);
-}
-
+void MissingFunctionality(const char* fun) { printf("Missing functionality: %s\n", fun); }
Builder::Loop::Loop(Builder& builder, bool testFirstArg)
- : function(&builder.getBuildPoint()->getParent()),
- header(new Block(builder.getUniqueId(), *function)),
- merge(new Block(builder.getUniqueId(), *function)),
- body(new Block(builder.getUniqueId(), *function)),
- testFirst(testFirstArg),
- isFirstIteration(nullptr)
-{
- if (!testFirst)
- {
-// You may be tempted to rewrite this as
-// new Instruction(builder.getUniqueId(), builder.makeBoolType(), OpPhi);
-// This will cause subtle test failures because builder.getUniqueId(),
-// and builder.makeBoolType() can then get run in a compiler-specific
-// order making tests fail for certain configurations.
+ : function(&builder.getBuildPoint()->getParent()),
+ header(new Block(builder.getUniqueId(), *function)),
+ merge(new Block(builder.getUniqueId(), *function)),
+ body(new Block(builder.getUniqueId(), *function)),
+ testFirst(testFirstArg),
+ isFirstIteration(nullptr)
+{
+ if (!testFirst) {
+ // You may be tempted to rewrite this as
+ // new Instruction(builder.getUniqueId(), builder.makeBoolType(), OpPhi);
+ // This will cause subtle test failures because builder.getUniqueId(),
+ // and builder.makeBoolType() can then get run in a compiler-specific
+ // order making tests fail for certain configurations.
Id instructionId = builder.getUniqueId();
isFirstIteration = new Instruction(instructionId, builder.makeBoolType(), OpPhi);
}
}
-}; // end spv namespace
+}; // end spv namespace
//
-//Copyright (C) 2014 LunarG, Inc.
+// Copyright (C) 2014 LunarG, Inc.
//
-//All rights reserved.
+// All rights reserved.
//
-//Redistribution and use in source and binary forms, with or without
-//modification, are permitted provided that the following conditions
-//are met:
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
-//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-//POSSIBILITY OF SUCH DAMAGE.
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
//
// Author: John Kessenich, LunarG
#include "spvIR.h"
#include <algorithm>
-#include <stack>
#include <map>
+#include <stack>
namespace spv {
}
void addCapability(spv::Capability cap) { capabilities.push_back(cap); }
-
// To get a new <id> for anything needing a new one.
Id getUniqueId() { return ++uniqueId; }
-
// To get a set of new <id>s, e.g., for a set of function parameters
Id getUniqueIds(int numIds)
{
Id makeVoidType();
Id makeBoolType();
Id makePointer(StorageClass, Id type);
- Id makeIntegerType(int width, bool hasSign); // generic
+ Id makeIntegerType(int width, bool hasSign); // generic
Id makeIntType(int width) { return makeIntegerType(width, true); }
Id makeUintType(int width) { return makeIntegerType(width, false); }
Id makeFloatType(int width);
Id makeArrayType(Id element, unsigned size, int stride); // 0 means no stride decoration
Id makeRuntimeArray(Id element);
Id makeFunctionType(Id returnType, std::vector<Id>& paramTypes);
- Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
+ Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled,
+ ImageFormat format);
Id makeSamplerType();
Id makeSampledImageType(Id imageType);
Id getContainedTypeId(Id typeId) const;
Id getContainedTypeId(Id typeId, int) const;
StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
-
- bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
- bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
- bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); }
- bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); }
- bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
+ bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
+ bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
+ bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); }
+ bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); }
+ bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
-
- bool isBoolType(Id typeId) const { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
- bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
- bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
- bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
- bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; }
- bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; }
- bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; }
- bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId); }
- bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
- bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
+ bool isBoolType(Id typeId) const
+ {
+ return groupedTypes[OpTypeBool].size() > 0 &&
+ typeId == groupedTypes[OpTypeBool].back()->getResultId();
+ }
+ bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
+ bool isScalarType(Id typeId) const
+ {
+ return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt ||
+ getTypeClass(typeId) == OpTypeBool;
+ }
+ bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
+ bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; }
+ bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; }
+ bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; }
+ bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId); }
+ bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
+ bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
-
bool isConstantOpCode(Op opcode) const;
bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
- unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
- StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
+ unsigned int getConstantScalar(Id resultId) const
+ {
+ return module.getInstruction(resultId)->getImmediateOperand(0);
+ }
+ StorageClass getStorageClass(Id resultId) const
+ {
+ return getTypeStorageClass(getTypeId(resultId));
+ }
int getTypeNumColumns(Id typeId) const
{
return getNumTypeComponents(getContainedTypeId(typeId));
}
int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
-
Dim getTypeDimensionality(Id typeId) const
{
assert(isImageType(typeId));
// For making new constants (will return old constant if the requested one was already made).
Id makeBoolConstant(bool b, bool specConstant = false);
- Id makeIntConstant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
- Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); }
+ Id makeIntConstant(int i, bool specConstant = false)
+ {
+ return makeIntConstant(makeIntType(32), (unsigned)i, specConstant);
+ }
+ Id makeUintConstant(unsigned u, bool specConstant = false)
+ {
+ return makeIntConstant(makeUintType(32), u, specConstant);
+ }
Id makeFloatConstant(float f, bool specConstant = false);
Id makeDoubleConstant(double d, bool specConstant = false);
// Methods for adding information outside the CFG.
Instruction* addEntryPoint(ExecutionModel, Function*, const char* name);
- void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
+ void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1,
+ int value3 = -1);
void addName(Id, const char* name);
void addMemberName(Id, int member, const char* name);
void addLine(Id target, Id fileName, int line, int column);
// At the end of what block do the next create*() instructions go?
void setBuildPoint(Block* bp) { buildPoint = bp; }
Block* getBuildPoint() const { return buildPoint; }
-
// Make the main function.
Function* makeMain();
// Make a shader-style function, and create its entry block if entry is non-zero.
// Return the function, pass back the entry.
- Function* makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes, Block **entry = 0);
+ Function* makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes,
+ Block** entry = 0);
// Create a return. An 'implicit' return is one not appearing in the source
// code. In the case of an implicit return, no post-return block is inserted.
void setPrecision(Id /* value */, Decoration precision)
{
if (precision != NoPrecision) {
- ;// TODO
+ ; // TODO
}
}
// - promoteScalar(scalar, scalar) // do nothing
// Other forms are not allowed.
//
- // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'.
+ // Generally, the type of 'scalar' does not need to be the same type as the components in
+ // 'vector'.
// The type of the created vector is a vector of components of the same type as the scalar.
//
- // Note: One of the arguments will change, with the result coming back that way rather than
+ // Note: One of the arguments will change, with the result coming back that way rather than
// through the return value.
void promoteScalar(Decoration precision, Id& left, Id& right);
Id smearScalar(Decoration precision, Id scalarVal, Id vectorType);
// Create a call to a built-in function.
- Id createBuiltinCall(Decoration precision, Id resultType, Id builtins, int entryPoint, std::vector<Id>& args);
+ Id createBuiltinCall(Decoration precision, Id resultType, Id builtins, int entryPoint,
+ std::vector<Id>& args);
// List of parameters used to create a texture operation
struct TextureParameters {
};
// Select the correct texture operation based on all inputs, and emit the correct instruction
- Id createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, bool gather, const TextureParameters&);
+ Id createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, bool gather,
+ const TextureParameters&);
// Emit the OpTextureQuery* instruction that was passed in.
// Figure out the right return value and type, and return it.
Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id);
// Reduction comparision for composites: For equal and not-equal resulting in a scalar.
- Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */);
+ Id createCompositeCompare(Decoration precision, Id, Id,
+ bool /* true if for equal, false if for not-equal */);
// OpCompositeConstruct
Id createCompositeConstruct(Id typeId, std::vector<Id>& constituents);
Id createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId);
// matrix constructor
- Id createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id constructee);
+ Id createMatrixConstructor(Decoration precision, const std::vector<Id>& sources,
+ Id constructee);
// Helper to use for building nested control flow with if-then-else.
class If {
public:
If(Id condition, Builder& builder);
~If() {}
-
void makeBeginElse();
void makeEndIf();
// Returns the right set of basic blocks to start each code segment with, so that the caller's
// recursion stack can hold the memory for it.
//
- void makeSwitch(Id condition, int numSegments, std::vector<int>& caseValues, std::vector<int>& valueToSegment, int defaultSegment,
+ void makeSwitch(Id condition, int numSegments, std::vector<int>& caseValues,
+ std::vector<int>& valueToSegment, int defaultSegment,
std::vector<Block*>& segmentBB); // return argument
// Add a branch to the innermost switch's merge block.
//
struct AccessChain {
- Id base; // for l-values, pointer to the base object, for r-values, the base object
+ Id base; // for l-values, pointer to the base object, for r-values, the base object
std::vector<Id> indexChain;
- Id instr; // cache the instruction that generates this access chain
- std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number
- Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present
- Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
- bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value
+ Id instr; // cache the instruction that generates this access chain
+ std::vector<unsigned>
+ swizzle; // each std::vector element selects the next GLSL component number
+ Id component; // a dynamic component index, can coexist with a swizzle, done after the
+ // swizzle, NoResult if not present
+ Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType
+ // unless a swizzle or component is present
+ bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value
};
//
// for external save and restore
AccessChain getAccessChain() { return accessChain; }
void setAccessChain(AccessChain newChain) { accessChain = newChain; }
-
// clear accessChain
void clearAccessChain();
}
// push offset onto the end of the chain
- void accessChainPush(Id offset)
- {
- accessChain.indexChain.push_back(offset);
- }
-
+ void accessChainPush(Id offset) { accessChain.indexChain.push_back(offset); }
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType);
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
void dumpInstructions(std::vector<unsigned int>&, const std::vector<Instruction*>&) const;
- struct Loop; // Defined below.
+ struct Loop; // Defined below.
void createBranchToLoopHeaderFromInside(const Loop& loop);
SourceLanguage source;
std::vector<Instruction*> constantsTypesGlobals;
std::vector<Instruction*> externals;
- // not output, internally used for quick & dirty canonical (unique) creation
+ // not output, internally used for quick & dirty canonical (unique) creation
std::vector<Instruction*> groupedConstants[OpConstant]; // all types appear before OpConstant
std::vector<Instruction*> groupedTypes[OpConstant];
}; // end spv namespace
-#endif // SpvBuilder_H
+#endif // SpvBuilder_H