Add .clang-format.

This allows automatic source-file formatting with clang-format, freeing
contributors from worrying about formatting while keeping the style
consistent everywhere.
This commit is contained in:
Dejan Mircevski 2016-01-11 16:42:47 -05:00
parent e23c9849c2
commit 778b876587
3 changed files with 229 additions and 203 deletions

11
.clang-format Normal file
View File

@ -0,0 +1,11 @@
Language: Cpp
IndentWidth: 4
BreakBeforeBraces: Custom
BraceWrapping: { AfterFunction: true }
IndentCaseLabels: false
ColumnLimit: 100
AccessModifierOffset: -4
AlignTrailingComments: true
AllowShortBlocksOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false

View File

@ -1,11 +1,11 @@
// //
//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 // Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions // modification, are permitted provided that the following conditions
//are met: // are met:
// //
// Redistributions of source code must retain the above copyright // Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer. // notice, this list of conditions and the following disclaimer.
@ -19,18 +19,18 @@
// contributors may be used to endorse or promote products derived // contributors may be used to endorse or promote products derived
// from this software without specific prior written permission. // 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 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
// //
// Author: John Kessenich, LunarG // Author: John Kessenich, LunarG
@ -50,28 +50,25 @@
#include "SpvBuilder.h" #include "SpvBuilder.h"
#ifndef _WIN32 #ifndef _WIN32
#include <cstdio> #include <cstdio>
#endif #endif
namespace spv { namespace spv {
Builder::Builder(unsigned int magicNumber) : Builder::Builder(unsigned int magicNumber)
source(SourceLanguageUnknown), : source(SourceLanguageUnknown),
sourceVersion(0), sourceVersion(0),
addressModel(AddressingModelLogical), addressModel(AddressingModelLogical),
memoryModel(MemoryModelGLSL450), memoryModel(MemoryModelGLSL450),
builderNumber(magicNumber), builderNumber(magicNumber),
buildPoint(0), buildPoint(0),
uniqueId(0), uniqueId(0),
mainFunction(0) mainFunction(0)
{ {
clearAccessChain(); clearAccessChain();
} }
Builder::~Builder() Builder::~Builder() {}
{
}
Id Builder::import(const char* name) Id Builder::import(const char* name)
{ {
Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport); Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport);
@ -219,8 +216,7 @@ Id Builder::makeStructResultType(Id type0, Id type1)
type = groupedTypes[OpTypeStruct][t]; type = groupedTypes[OpTypeStruct][t];
if (type->getNumOperands() != 2) if (type->getNumOperands() != 2)
continue; continue;
if (type->getIdOperand(0) != type0 || if (type->getIdOperand(0) != type0 || type->getIdOperand(1) != type1)
type->getIdOperand(1) != type1)
continue; continue;
return type->getResultId(); return type->getResultId();
} }
@ -239,8 +235,7 @@ Id Builder::makeVectorType(Id component, int size)
Instruction* type; Instruction* type;
for (int t = 0; t < (int)groupedTypes[OpTypeVector].size(); ++t) { for (int t = 0; t < (int)groupedTypes[OpTypeVector].size(); ++t) {
type = groupedTypes[OpTypeVector][t]; type = groupedTypes[OpTypeVector][t];
if (type->getIdOperand(0) == component && if (type->getIdOperand(0) == component && type->getImmediateOperand(1) == (unsigned)size)
type->getImmediateOperand(1) == (unsigned)size)
return type->getResultId(); return type->getResultId();
} }
@ -265,8 +260,7 @@ Id Builder::makeMatrixType(Id component, int cols, int rows)
Instruction* type; Instruction* type;
for (int t = 0; t < (int)groupedTypes[OpTypeMatrix].size(); ++t) { for (int t = 0; t < (int)groupedTypes[OpTypeMatrix].size(); ++t) {
type = groupedTypes[OpTypeMatrix][t]; type = groupedTypes[OpTypeMatrix][t];
if (type->getIdOperand(0) == column && if (type->getIdOperand(0) == column && type->getImmediateOperand(1) == (unsigned)cols)
type->getImmediateOperand(1) == (unsigned)cols)
return type->getResultId(); return type->getResultId();
} }
@ -294,8 +288,7 @@ Id Builder::makeArrayType(Id element, unsigned size, int stride)
// try to find existing type // try to find existing type
for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) { for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) {
type = groupedTypes[OpTypeArray][t]; type = groupedTypes[OpTypeArray][t];
if (type->getIdOperand(0) == element && if (type->getIdOperand(0) == element && type->getIdOperand(1) == sizeId)
type->getIdOperand(1) == sizeId)
return type->getResultId(); return type->getResultId();
} }
} }
@ -327,7 +320,8 @@ Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
Instruction* type; Instruction* type;
for (int t = 0; t < (int)groupedTypes[OpTypeFunction].size(); ++t) { for (int t = 0; t < (int)groupedTypes[OpTypeFunction].size(); ++t) {
type = groupedTypes[OpTypeFunction][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; continue;
bool mismatch = false; bool mismatch = false;
for (int p = 0; p < (int)paramTypes.size(); ++p) { for (int p = 0; p < (int)paramTypes.size(); ++p) {
@ -336,7 +330,7 @@ Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
break; break;
} }
} }
if (! mismatch) if (!mismatch)
return type->getResultId(); return type->getResultId();
} }
@ -352,7 +346,8 @@ Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
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 // try to find it
Instruction* type; Instruction* type;
@ -360,9 +355,9 @@ Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, boo
type = groupedTypes[OpTypeImage][t]; type = groupedTypes[OpTypeImage][t];
if (type->getIdOperand(0) == sampledType && if (type->getIdOperand(0) == sampledType &&
type->getImmediateOperand(1) == (unsigned int)dim && 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(3) == (arrayed ? 1u : 0u) &&
type->getImmediateOperand(4) == ( ms ? 1u : 0u) && type->getImmediateOperand(4) == (ms ? 1u : 0u) &&
type->getImmediateOperand(5) == sampled && type->getImmediateOperand(5) == sampled &&
type->getImmediateOperand(6) == (unsigned int)format) type->getImmediateOperand(6) == (unsigned int)format)
return type->getResultId(); return type->getResultId();
@ -371,10 +366,10 @@ Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, boo
// not found, make it // not found, make it
type = new Instruction(getUniqueId(), NoType, OpTypeImage); type = new Instruction(getUniqueId(), NoType, OpTypeImage);
type->addIdOperand(sampledType); type->addIdOperand(sampledType);
type->addImmediateOperand( dim); type->addImmediateOperand(dim);
type->addImmediateOperand( depth ? 1 : 0); type->addImmediateOperand(depth ? 1 : 0);
type->addImmediateOperand(arrayed ? 1 : 0); type->addImmediateOperand(arrayed ? 1 : 0);
type->addImmediateOperand( ms ? 1 : 0); type->addImmediateOperand(ms ? 1 : 0);
type->addImmediateOperand(sampled); type->addImmediateOperand(sampled);
type->addImmediateOperand((unsigned int)format); type->addImmediateOperand((unsigned int)format);
@ -419,8 +414,7 @@ Op Builder::getMostBasicTypeClass(Id typeId) const
Instruction* instr = module.getInstruction(typeId); Instruction* instr = module.getInstruction(typeId);
Op typeClass = instr->getOpCode(); Op typeClass = instr->getOpCode();
switch (typeClass) switch (typeClass) {
{
case OpTypeVoid: case OpTypeVoid:
case OpTypeBool: case OpTypeBool:
case OpTypeInt: case OpTypeInt:
@ -444,8 +438,7 @@ int Builder::getNumTypeConstituents(Id typeId) const
{ {
Instruction* instr = module.getInstruction(typeId); Instruction* instr = module.getInstruction(typeId);
switch (instr->getOpCode()) switch (instr->getOpCode()) {
{
case OpTypeBool: case OpTypeBool:
case OpTypeInt: case OpTypeInt:
case OpTypeFloat: case OpTypeFloat:
@ -470,8 +463,7 @@ Id Builder::getScalarTypeId(Id typeId) const
Instruction* instr = module.getInstruction(typeId); Instruction* instr = module.getInstruction(typeId);
Op typeClass = instr->getOpCode(); Op typeClass = instr->getOpCode();
switch (typeClass) switch (typeClass) {
{
case OpTypeVoid: case OpTypeVoid:
case OpTypeBool: case OpTypeBool:
case OpTypeInt: case OpTypeInt:
@ -496,8 +488,7 @@ Id Builder::getContainedTypeId(Id typeId, int member) const
Instruction* instr = module.getInstruction(typeId); Instruction* instr = module.getInstruction(typeId);
Op typeClass = instr->getOpCode(); Op typeClass = instr->getOpCode();
switch (typeClass) switch (typeClass) {
{
case OpTypeVector: case OpTypeVector:
case OpTypeMatrix: case OpTypeMatrix:
case OpTypeArray: case OpTypeArray:
@ -514,11 +505,7 @@ Id Builder::getContainedTypeId(Id typeId, int member) const
} }
// Return the immediately contained type of a given composite type. // Return the immediately contained type of a given composite type.
Id Builder::getContainedTypeId(Id typeId) const Id Builder::getContainedTypeId(Id typeId) const { return getContainedTypeId(typeId, 0); }
{
return getContainedTypeId(typeId, 0);
}
// 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(Op typeClass, Op opcode, Id typeId, unsigned value) const Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const
@ -526,8 +513,7 @@ Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned valu
Instruction* constant; Instruction* constant;
for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
constant = groupedConstants[typeClass][i]; constant = groupedConstants[typeClass][i];
if (constant->getOpCode() == opcode && if (constant->getOpCode() == opcode && constant->getTypeId() == typeId &&
constant->getTypeId() == typeId &&
constant->getImmediateOperand(0) == value) constant->getImmediateOperand(0) == value)
return constant->getResultId(); return constant->getResultId();
} }
@ -541,10 +527,8 @@ Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1,
Instruction* constant; Instruction* constant;
for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
constant = groupedConstants[typeClass][i]; constant = groupedConstants[typeClass][i];
if (constant->getOpCode() == opcode && if (constant->getOpCode() == opcode && constant->getTypeId() == typeId &&
constant->getTypeId() == typeId && constant->getImmediateOperand(0) == v1 && constant->getImmediateOperand(1) == v2)
constant->getImmediateOperand(0) == v1 &&
constant->getImmediateOperand(1) == v2)
return constant->getResultId(); return constant->getResultId();
} }
@ -579,7 +563,8 @@ Id Builder::makeBoolConstant(bool b, bool specConstant)
{ {
Id typeId = makeBoolType(); Id typeId = makeBoolType();
Instruction* constant; 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 // See if we already made it
Id existing = 0; Id existing = 0;
@ -675,7 +660,7 @@ Id Builder::findCompositeConstant(Op typeClass, std::vector<Id>& comps) const
break; break;
} }
} }
if (! mismatch) { if (!mismatch) {
found = true; found = true;
break; break;
} }
@ -728,7 +713,8 @@ Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, co
} }
// Currently relying on the fact that all 'value' of interest are small non-negative values. // 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); Instruction* instr = new Instruction(OpExecutionMode);
instr->addIdOperand(entryPoint->getId()); instr->addIdOperand(entryPoint->getId());
@ -801,7 +787,7 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
// Comments in header // Comments in header
Function* Builder::makeMain() Function* Builder::makeMain()
{ {
assert(! mainFunction); assert(!mainFunction);
Block* entry; Block* entry;
std::vector<Id> params; std::vector<Id> params;
@ -812,7 +798,8 @@ Function* Builder::makeMain()
} }
// Comments in header // 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 typeId = makeFunctionType(returnType, paramTypes);
Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size()); Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size());
@ -840,7 +827,7 @@ void Builder::makeReturn(bool implicit, Id retVal)
} else } else
buildPoint->addInstruction(new Instruction(NoResult, NoType, OpReturn)); buildPoint->addInstruction(new Instruction(NoResult, NoType, OpReturn));
if (! implicit) if (!implicit)
createAndSetNoPredecessorBlock("post-return"); createAndSetNoPredecessorBlock("post-return");
} }
@ -852,8 +839,7 @@ void Builder::leaveFunction()
assert(block); assert(block);
// If our function did not contain a return, add a return void now. // 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. // Whether we're in an unreachable (non-entry) block.
bool unreachable = function.getEntryBlock() != block && block->getNumPredecessors() == 0; bool unreachable = function.getEntryBlock() != block && block->getNumPredecessors() == 0;
@ -910,9 +896,9 @@ Id Builder::createVariable(StorageClass storageClass, Id type, const char* name)
// Comments in header // Comments in header
Id Builder::createUndefined(Id type) Id Builder::createUndefined(Id type)
{ {
Instruction* inst = new Instruction(getUniqueId(), type, OpUndef); Instruction* inst = new Instruction(getUniqueId(), type, OpUndef);
buildPoint->addInstruction(inst); buildPoint->addInstruction(inst);
return inst->getResultId(); return inst->getResultId();
} }
// Comments in header // Comments in header
@ -1002,7 +988,8 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned i
return insert->getResultId(); 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); Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert);
insert->addIdOperand(object); insert->addIdOperand(object);
@ -1182,9 +1169,11 @@ void Builder::promoteScalar(Decoration precision, Id& left, Id& right)
int direction = getNumComponents(right) - getNumComponents(left); int direction = getNumComponents(right) - getNumComponents(left);
if (direction > 0) 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) else if (direction < 0)
right = smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left))); right =
smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left)));
return; return;
} }
@ -1208,7 +1197,8 @@ Id Builder::smearScalar(Decoration /*precision*/, Id scalar, Id vectorType)
} }
// Comments in header // 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); Instruction* inst = new Instruction(getUniqueId(), resultType, OpExtInst);
inst->addIdOperand(builtins); inst->addIdOperand(builtins);
@ -1222,7 +1212,8 @@ Id Builder::createBuiltinCall(Decoration /*precision*/, Id resultType, Id builti
// Accept all parameters needed to create a texture instruction. // Accept all parameters needed to create a texture instruction.
// Create the correct instruction based on the inputs, and make the call. // 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; static const int maxTextureArgs = 10;
Id texArgs[maxTextureArgs] = {}; Id texArgs[maxTextureArgs] = {};
@ -1242,9 +1233,10 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, b
// //
// Set up the optional arguments // Set up the optional arguments
// //
int optArgNum = numArgs; // track which operand, if it exists, is the mask of optional arguments int optArgNum =
++numArgs; // speculatively make room for the mask operand numArgs; // track which operand, if it exists, is the mask of optional arguments
ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand ++numArgs; // speculatively make room for the mask operand
ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand
if (parameters.bias) { if (parameters.bias) {
mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask); mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask);
texArgs[numArgs++] = parameters.bias; texArgs[numArgs++] = parameters.bias;
@ -1322,7 +1314,7 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, b
// This happens when a legacy shadow*() call is made, which // This happens when a legacy shadow*() call is made, which
// gets a vec4 back instead of a float. // gets a vec4 back instead of a float.
Id smearedType = resultType; Id smearedType = resultType;
if (! isScalarType(resultType)) { if (!isScalarType(resultType)) {
switch (opCode) { switch (opCode) {
case OpImageSampleDrefImplicitLod: case OpImageSampleDrefImplicitLod:
case OpImageSampleDrefExplicitLod: case OpImageSampleDrefExplicitLod:
@ -1363,8 +1355,7 @@ Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameter
Id resultType = 0; Id resultType = 0;
switch (opCode) { switch (opCode) {
case OpImageQuerySize: case OpImageQuerySize:
case OpImageQuerySizeLod: case OpImageQuerySizeLod: {
{
int numComponents; int numComponents;
switch (getTypeDimensionality(getImageType(parameters.sampler))) { switch (getTypeDimensionality(getImageType(parameters.sampler))) {
case Dim1D: case Dim1D:
@ -1480,7 +1471,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
if (constituent == 0) if (constituent == 0)
resultId = subResultId; resultId = subResultId;
else else
resultId = createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId); resultId =
createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId);
} }
return resultId; return resultId;
@ -1489,7 +1481,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
// OpCompositeConstruct // OpCompositeConstruct
Id Builder::createCompositeConstruct(Id typeId, std::vector<Id>& constituents) 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); Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
for (int c = 0; c < (int)constituents.size(); ++c) for (int c = 0; c < (int)constituents.size(); ++c)
@ -1514,7 +1507,7 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
Id scalarTypeId = getScalarTypeId(resultTypeId); Id scalarTypeId = getScalarTypeId(resultTypeId);
std::vector<Id> constituents; // accumulate the arguments for OpCompositeConstruct std::vector<Id> constituents; // accumulate the arguments for OpCompositeConstruct
for (unsigned int i = 0; i < sources.size(); ++i) { 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 sourceSize = getNumComponents(sources[i]);
unsigned int sourcesToUse = sourceSize; unsigned int sourcesToUse = sourceSize;
if (sourcesToUse + targetComponent > numTargetComponents) if (sourcesToUse + targetComponent > numTargetComponents)
@ -1548,7 +1541,8 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
} }
// Comments in header // 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); Id componentTypeId = getScalarTypeId(resultTypeId);
int numCols = getTypeNumColumns(resultTypeId); int numCols = getTypeNumColumns(resultTypeId);
@ -1562,7 +1556,7 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
// initialize the array to the identity matrix // initialize the array to the identity matrix
Id ids[maxMatrixSize][maxMatrixSize]; Id ids[maxMatrixSize][maxMatrixSize];
Id one = makeFloatConstant(1.0); Id one = makeFloatConstant(1.0);
Id zero = makeFloatConstant(0.0); Id zero = makeFloatConstant(0.0);
for (int col = 0; col < 4; ++col) { for (int col = 0; col < 4; ++col) {
for (int row = 0; row < 4; ++row) { for (int row = 0; row < 4; ++row) {
@ -1579,7 +1573,8 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
for (int col = 0; col < 4; ++col) for (int col = 0; col < 4; ++col)
ids[col][col] = sources[0]; ids[col][col] = sources[0];
} else if (isMatrix(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]; Id matrix = sources[0];
int minCols = std::min(numCols, getNumColumns(matrix)); int minCols = std::min(numCols, getNumColumns(matrix));
int minRows = std::min(numRows, getNumRows(matrix)); int minRows = std::min(numRows, getNumRows(matrix));
@ -1614,7 +1609,6 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
} }
} }
// Step 2: Construct a matrix from that array. // Step 2: Construct a matrix from that array.
// First make the column vectors, then make the matrix. // First make the column vectors, then make the matrix.
@ -1633,10 +1627,7 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
} }
// Comments in header // Comments in header
Builder::If::If(Id cond, Builder& gb) : Builder::If::If(Id cond, Builder& gb) : builder(gb), condition(cond), elseBlock(0)
builder(gb),
condition(cond),
elseBlock(0)
{ {
function = &builder.getBuildPoint()->getParent(); function = &builder.getBuildPoint()->getParent();
@ -1688,7 +1679,8 @@ void Builder::If::makeEndIf()
} }
// Comments in header // 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) std::vector<Block*>& segmentBlocks)
{ {
Function& function = buildPoint->getParent(); Function& function = buildPoint->getParent();
@ -1705,7 +1697,8 @@ void Builder::makeSwitch(Id selector, int numSegments, std::vector<int>& caseVal
// make the switch instruction // make the switch instruction
Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch); Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
switchInst->addIdOperand(selector); 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) { for (int i = 0; i < (int)caseValues.size(); ++i) {
switchInst->addImmediateOperand(caseValues[i]); switchInst->addImmediateOperand(caseValues[i]);
switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId()); switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId());
@ -1730,7 +1723,7 @@ void Builder::nextSwitchSegment(std::vector<Block*>& segmentBlock, int nextSegme
int lastSegment = nextSegment - 1; int lastSegment = nextSegment - 1;
if (lastSegment >= 0) { if (lastSegment >= 0) {
// Close out previous segment by jumping, if necessary, to next segment // Close out previous segment by jumping, if necessary, to next segment
if (! buildPoint->isTerminated()) if (!buildPoint->isTerminated())
createBranch(segmentBlock[nextSegment]); createBranch(segmentBlock[nextSegment]);
} }
Block* block = segmentBlock[nextSegment]; Block* block = segmentBlock[nextSegment];
@ -1742,7 +1735,7 @@ void Builder::nextSwitchSegment(std::vector<Block*>& segmentBlock, int nextSegme
void Builder::endSwitch(std::vector<Block*>& /*segmentBlock*/) void Builder::endSwitch(std::vector<Block*>& /*segmentBlock*/)
{ {
// Close out previous segment by jumping, if necessary, to next segment // Close out previous segment by jumping, if necessary, to next segment
if (! buildPoint->isTerminated()) if (!buildPoint->isTerminated())
addSwitchBreak(); addSwitchBreak();
switchMerges.top()->getParent().addBlock(switchMerges.top()); switchMerges.top()->getParent().addBlock(switchMerges.top());
@ -1944,13 +1937,15 @@ void Builder::accessChainStore(Id rvalue)
Id source = NoResult; Id source = NoResult;
if (accessChain.swizzle.size()) { if (accessChain.swizzle.size()) {
Id tempBaseId = createLoad(base); Id tempBaseId = createLoad(base);
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, rvalue, accessChain.swizzle); source =
createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, rvalue, accessChain.swizzle);
} }
// dynamic component selection // dynamic component selection
if (accessChain.component != NoResult) { if (accessChain.component != NoResult) {
Id tempBaseId = (source == NoResult) ? createLoad(base) : source; 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) if (source == NoResult)
@ -1968,7 +1963,9 @@ Id Builder::accessChainLoad(Id resultType)
// transfer access chain, but keep it static, so we can stay in registers // transfer access chain, but keep it static, so we can stay in registers
transferAccessChainSwizzle(false); transferAccessChainSwizzle(false);
if (accessChain.indexChain.size() > 0) { 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 // if all the accesses are constants, we can use OpCompositeExtract
std::vector<unsigned> indexes; std::vector<unsigned> indexes;
@ -1986,7 +1983,8 @@ Id Builder::accessChainLoad(Id resultType)
id = createCompositeExtract(accessChain.base, swizzleBase, indexes); id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
else { else {
// make a new function variable for this r-value // 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 // store into it
createStore(accessChain.base, lValue); createStore(accessChain.base, lValue);
@ -2111,8 +2109,10 @@ Id Builder::collapseAccessChain()
if (accessChain.indexChain.size() > 0) { if (accessChain.indexChain.size() > 0) {
if (accessChain.instr == 0) { if (accessChain.instr == 0) {
StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base)); StorageClass storageClass =
accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain); (StorageClass)module.getStorageClass(getTypeId(accessChain.base));
accessChain.instr =
createAccessChain(storageClass, accessChain.base, accessChain.indexChain);
} }
return accessChain.instr; return accessChain.instr;
@ -2194,7 +2194,7 @@ void Builder::createAndSetNoPredecessorBlock(const char* /*name*/)
buildPoint->getParent().addBlock(block); buildPoint->getParent().addBlock(block);
setBuildPoint(block); setBuildPoint(block);
//if (name) // if (name)
// addName(block->getId(), name); // addName(block->getId(), name);
} }
@ -2235,7 +2235,8 @@ void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* els
elseBlock->addPredecessor(buildPoint); 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) { for (int i = 0; i < (int)instructions.size(); ++i) {
instructions[i]->dump(out); instructions[i]->dump(out);
@ -2252,29 +2253,24 @@ void TbdFunctionality(const char* tbd)
} }
} }
void MissingFunctionality(const char* fun) void MissingFunctionality(const char* fun) { printf("Missing functionality: %s\n", fun); }
{
printf("Missing functionality: %s\n", fun);
}
Builder::Loop::Loop(Builder& builder, bool testFirstArg) Builder::Loop::Loop(Builder& builder, bool testFirstArg)
: function(&builder.getBuildPoint()->getParent()), : function(&builder.getBuildPoint()->getParent()),
header(new Block(builder.getUniqueId(), *function)), header(new Block(builder.getUniqueId(), *function)),
merge(new Block(builder.getUniqueId(), *function)), merge(new Block(builder.getUniqueId(), *function)),
body(new Block(builder.getUniqueId(), *function)), body(new Block(builder.getUniqueId(), *function)),
testFirst(testFirstArg), testFirst(testFirstArg),
isFirstIteration(nullptr) isFirstIteration(nullptr)
{ {
if (!testFirst) if (!testFirst) {
{ // You may be tempted to rewrite this as
// You may be tempted to rewrite this as // new Instruction(builder.getUniqueId(), builder.makeBoolType(), OpPhi);
// new Instruction(builder.getUniqueId(), builder.makeBoolType(), OpPhi); // This will cause subtle test failures because builder.getUniqueId(),
// This will cause subtle test failures because builder.getUniqueId(), // and builder.makeBoolType() can then get run in a compiler-specific
// and builder.makeBoolType() can then get run in a compiler-specific // order making tests fail for certain configurations.
// order making tests fail for certain configurations.
Id instructionId = builder.getUniqueId(); Id instructionId = builder.getUniqueId();
isFirstIteration = new Instruction(instructionId, builder.makeBoolType(), OpPhi); isFirstIteration = new Instruction(instructionId, builder.makeBoolType(), OpPhi);
} }
} }
}; // end spv namespace }; // end spv namespace

View File

@ -1,11 +1,11 @@
// //
//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 // Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions // modification, are permitted provided that the following conditions
//are met: // are met:
// //
// Redistributions of source code must retain the above copyright // Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer. // notice, this list of conditions and the following disclaimer.
@ -19,18 +19,18 @@
// contributors may be used to endorse or promote products derived // contributors may be used to endorse or promote products derived
// from this software without specific prior written permission. // 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 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
// //
// Author: John Kessenich, LunarG // Author: John Kessenich, LunarG
@ -52,8 +52,8 @@
#include "spvIR.h" #include "spvIR.h"
#include <algorithm> #include <algorithm>
#include <stack>
#include <map> #include <map>
#include <stack>
namespace spv { namespace spv {
@ -78,10 +78,8 @@ public:
} }
void addCapability(spv::Capability cap) { capabilities.push_back(cap); } void addCapability(spv::Capability cap) { capabilities.push_back(cap); }
// To get a new <id> for anything needing a new one. // To get a new <id> for anything needing a new one.
Id getUniqueId() { return ++uniqueId; } Id getUniqueId() { return ++uniqueId; }
// To get a set of new <id>s, e.g., for a set of function parameters // To get a set of new <id>s, e.g., for a set of function parameters
Id getUniqueIds(int numIds) Id getUniqueIds(int numIds)
{ {
@ -94,7 +92,7 @@ public:
Id makeVoidType(); Id makeVoidType();
Id makeBoolType(); Id makeBoolType();
Id makePointer(StorageClass, Id type); 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 makeIntType(int width) { return makeIntegerType(width, true); }
Id makeUintType(int width) { return makeIntegerType(width, false); } Id makeUintType(int width) { return makeIntegerType(width, false); }
Id makeFloatType(int width); Id makeFloatType(int width);
@ -105,7 +103,8 @@ public:
Id makeArrayType(Id element, unsigned size, int stride); // 0 means no stride decoration Id makeArrayType(Id element, unsigned size, int stride); // 0 means no stride decoration
Id makeRuntimeArray(Id element); Id makeRuntimeArray(Id element);
Id makeFunctionType(Id returnType, std::vector<Id>& paramTypes); 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 makeSamplerType();
Id makeSampledImageType(Id imageType); Id makeSampledImageType(Id imageType);
@ -122,31 +121,42 @@ public:
Id getContainedTypeId(Id typeId) const; Id getContainedTypeId(Id typeId) const;
Id getContainedTypeId(Id typeId, int) const; Id getContainedTypeId(Id typeId, int) const;
StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); }
bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); }
bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
bool isBoolType(Id typeId) const
bool isBoolType(Id typeId) const { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } {
bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } return groupedTypes[OpTypeBool].size() > 0 &&
bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; } typeId == groupedTypes[OpTypeBool].back()->getResultId();
bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } }
bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } bool isScalarType(Id typeId) const
bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } {
bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId); } return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt ||
bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } getTypeClass(typeId) == OpTypeBool;
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } }
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 isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
bool isConstantOpCode(Op opcode) const; bool isConstantOpCode(Op opcode) const;
bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); } unsigned int getConstantScalar(Id resultId) const
StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } {
return module.getInstruction(resultId)->getImmediateOperand(0);
}
StorageClass getStorageClass(Id resultId) const
{
return getTypeStorageClass(getTypeId(resultId));
}
int getTypeNumColumns(Id typeId) const int getTypeNumColumns(Id typeId) const
{ {
@ -160,7 +170,6 @@ public:
return getNumTypeComponents(getContainedTypeId(typeId)); return getNumTypeComponents(getContainedTypeId(typeId));
} }
int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
Dim getTypeDimensionality(Id typeId) const Dim getTypeDimensionality(Id typeId) const
{ {
assert(isImageType(typeId)); assert(isImageType(typeId));
@ -180,8 +189,14 @@ public:
// For making new constants (will return old constant if the requested one was already made). // For making new constants (will return old constant if the requested one was already made).
Id makeBoolConstant(bool b, bool specConstant = false); Id makeBoolConstant(bool b, bool specConstant = false);
Id makeIntConstant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } Id makeIntConstant(int i, bool specConstant = false)
Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); } {
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 makeFloatConstant(float f, bool specConstant = false);
Id makeDoubleConstant(double d, bool specConstant = false); Id makeDoubleConstant(double d, bool specConstant = false);
@ -190,7 +205,8 @@ public:
// Methods for adding information outside the CFG. // Methods for adding information outside the CFG.
Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); 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 addName(Id, const char* name);
void addMemberName(Id, int member, const char* name); void addMemberName(Id, int member, const char* name);
void addLine(Id target, Id fileName, int line, int column); void addLine(Id target, Id fileName, int line, int column);
@ -200,13 +216,13 @@ public:
// At the end of what block do the next create*() instructions go? // At the end of what block do the next create*() instructions go?
void setBuildPoint(Block* bp) { buildPoint = bp; } void setBuildPoint(Block* bp) { buildPoint = bp; }
Block* getBuildPoint() const { return buildPoint; } Block* getBuildPoint() const { return buildPoint; }
// Make the main function. // Make the main function.
Function* makeMain(); Function* makeMain();
// Make a shader-style function, and create its entry block if entry is non-zero. // Make a shader-style function, and create its entry block if entry is non-zero.
// Return the function, pass back the entry. // 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 // 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. // code. In the case of an implicit return, no post-return block is inserted.
@ -271,7 +287,7 @@ public:
void setPrecision(Id /* value */, Decoration precision) void setPrecision(Id /* value */, Decoration precision)
{ {
if (precision != NoPrecision) { if (precision != NoPrecision) {
;// TODO ; // TODO
} }
} }
@ -282,7 +298,8 @@ public:
// - promoteScalar(scalar, scalar) // do nothing // - promoteScalar(scalar, scalar) // do nothing
// Other forms are not allowed. // 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. // 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
@ -295,7 +312,8 @@ public:
Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); Id smearScalar(Decoration precision, Id scalarVal, Id vectorType);
// Create a call to a built-in function. // 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 // List of parameters used to create a texture operation
struct TextureParameters { struct TextureParameters {
@ -313,7 +331,8 @@ public:
}; };
// Select the correct texture operation based on all inputs, and emit the correct instruction // 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. // 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.
@ -325,7 +344,8 @@ public:
Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id);
// Reduction comparision for composites: For equal and not-equal resulting in a scalar. // 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 // OpCompositeConstruct
Id createCompositeConstruct(Id typeId, std::vector<Id>& constituents); Id createCompositeConstruct(Id typeId, std::vector<Id>& constituents);
@ -334,14 +354,14 @@ public:
Id createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId); Id createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId);
// matrix constructor // 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. // Helper to use for building nested control flow with if-then-else.
class If { class If {
public: public:
If(Id condition, Builder& builder); If(Id condition, Builder& builder);
~If() {} ~If() {}
void makeBeginElse(); void makeBeginElse();
void makeEndIf(); void makeEndIf();
@ -370,7 +390,8 @@ public:
// Returns the right set of basic blocks to start each code segment with, so that the caller's // 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. // 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 std::vector<Block*>& segmentBB); // return argument
// Add a branch to the innermost switch's merge block. // Add a branch to the innermost switch's merge block.
@ -440,13 +461,16 @@ public:
// //
struct AccessChain { 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; std::vector<Id> indexChain;
Id instr; // cache the instruction that generates this access chain Id instr; // cache the instruction that generates this access chain
std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number std::vector<unsigned>
Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present swizzle; // each std::vector element selects the next GLSL component number
Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present Id component; // a dynamic component index, can coexist with a swizzle, done after the
bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value // 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
}; };
// //
@ -457,7 +481,6 @@ public:
// for external save and restore // for external save and restore
AccessChain getAccessChain() { return accessChain; } AccessChain getAccessChain() { return accessChain; }
void setAccessChain(AccessChain newChain) { accessChain = newChain; } void setAccessChain(AccessChain newChain) { accessChain = newChain; }
// clear accessChain // clear accessChain
void clearAccessChain(); void clearAccessChain();
@ -476,11 +499,7 @@ public:
} }
// push offset onto the end of the chain // push offset onto the end of the chain
void accessChainPush(Id offset) void accessChainPush(Id offset) { accessChain.indexChain.push_back(offset); }
{
accessChain.indexChain.push_back(offset);
}
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle // push new swizzle onto the end of any existing swizzle, merging into a single swizzle
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType); void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType);
@ -518,7 +537,7 @@ protected:
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;
struct Loop; // Defined below. struct Loop; // Defined below.
void createBranchToLoopHeaderFromInside(const Loop& loop); void createBranchToLoopHeaderFromInside(const Loop& loop);
SourceLanguage source; SourceLanguage source;
@ -544,7 +563,7 @@ protected:
std::vector<Instruction*> constantsTypesGlobals; std::vector<Instruction*> constantsTypesGlobals;
std::vector<Instruction*> externals; 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*> groupedConstants[OpConstant]; // all types appear before OpConstant
std::vector<Instruction*> groupedTypes[OpConstant]; std::vector<Instruction*> groupedTypes[OpConstant];
@ -602,4 +621,4 @@ void MissingFunctionality(const char*);
}; // end spv namespace }; // end spv namespace
#endif // SpvBuilder_H #endif // SpvBuilder_H