//
//Copyright (C) 2014 LunarG, Inc.
//
//All rights reserved.
//
//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.
//
//    Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the following
//    disclaimer in the documentation and/or other materials provided
//    with the distribution.
//
//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
//    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
//"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.

//
// Author: John Kessenich, LunarG
//

//
// Helper for making SPIR-V IR.  Generally, this is documented in the header
// SpvBuilder.h.
//

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#include <unordered_set>

#include "SpvBuilder.h"

#ifndef _WIN32
    #include <cstdio>
#endif

namespace spv {

const int SpvBuilderMagic = 0xBB;

Builder::Builder(unsigned int userNumber) :
    source(SourceLanguageUnknown),
    sourceVersion(0),
    addressModel(AddressingModelLogical),
    memoryModel(MemoryModelGLSL450),
    builderNumber(userNumber << 16 | SpvBuilderMagic),
    buildPoint(0),
    uniqueId(0),
    mainFunction(0),
    stageExit(0)
{
    clearAccessChain();
}

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();
}

// For creating new groupedTypes (will return old type if the requested one was already made).
Id Builder::makeVoidType()
{
    Instruction* type;
    if (groupedTypes[OpTypeVoid].size() == 0) {
        type = new Instruction(getUniqueId(), NoType, OpTypeVoid);
        groupedTypes[OpTypeVoid].push_back(type);
        constantsTypesGlobals.push_back(type);
        module.mapInstruction(type);
    } else
        type = groupedTypes[OpTypeVoid].back();

    return type->getResultId();
}

Id Builder::makeBoolType()
{
    Instruction* type;
    if (groupedTypes[OpTypeBool].size() == 0) {
        type = new Instruction(getUniqueId(), NoType, OpTypeBool);
        groupedTypes[OpTypeBool].push_back(type);
        constantsTypesGlobals.push_back(type);
        module.mapInstruction(type);
    } else
        type = groupedTypes[OpTypeBool].back();

    return type->getResultId();
}

Id Builder::makePointer(StorageClass storageClass, Id pointee)
{
    // try to find it
    Instruction* type;
    for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
        type = groupedTypes[OpTypePointer][t];
        if (type->getImmediateOperand(0) == (unsigned)storageClass &&
            type->getIdOperand(1) == pointee)
            return type->getResultId();
    }

    // not found, make it
    type = new Instruction(getUniqueId(), NoType, OpTypePointer);
    type->addImmediateOperand(storageClass);
    type->addIdOperand(pointee);
    groupedTypes[OpTypePointer].push_back(type);
    constantsTypesGlobals.push_back(type);
    module.mapInstruction(type);

    return type->getResultId();
}

Id Builder::makeIntegerType(int width, bool hasSign)
{
    // try to find it
    Instruction* type;
    for (int t = 0; t < (int)groupedTypes[OpTypeInt].size(); ++t) {
        type = groupedTypes[OpTypeInt][t];
        if (type->getImmediateOperand(0) == (unsigned)width &&
            type->getImmediateOperand(1) == (hasSign ? 1u : 0u))
            return type->getResultId();
    }

    // not found, make it
    type = new Instruction(getUniqueId(), NoType, OpTypeInt);
    type->addImmediateOperand(width);
    type->addImmediateOperand(hasSign ? 1 : 0);
    groupedTypes[OpTypeInt].push_back(type);
    constantsTypesGlobals.push_back(type);
    module.mapInstruction(type);

    return type->getResultId();
}

Id Builder::makeFloatType(int width)
{
    // try to find it
    Instruction* type;
    for (int t = 0; t < (int)groupedTypes[OpTypeFloat].size(); ++t) {
        type = groupedTypes[OpTypeFloat][t];
        if (type->getImmediateOperand(0) == (unsigned)width)
            return type->getResultId();
    }

    // not found, make it
    type = new Instruction(getUniqueId(), NoType, OpTypeFloat);
    type->addImmediateOperand(width);
    groupedTypes[OpTypeFloat].push_back(type);
    constantsTypesGlobals.push_back(type);
    module.mapInstruction(type);

    return type->getResultId();
}

Id Builder::makeStructType(std::vector<Id>& members, const char* name)
{
    // not found, make it
    Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeStruct);
    for (int op = 0; op < (int)members.size(); ++op)
        type->addIdOperand(members[op]);
    groupedTypes[OpTypeStruct].push_back(type);
    constantsTypesGlobals.push_back(type);
    module.mapInstruction(type);
    addName(type->getResultId(), name);

    return type->getResultId();
}

Id Builder::makeVectorType(Id component, int size)
{
    // try to find it
    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)
            return type->getResultId();
    }

    // not found, make it
    type = new Instruction(getUniqueId(), NoType, OpTypeVector);
    type->addIdOperand(component);
    type->addImmediateOperand(size);
    groupedTypes[OpTypeVector].push_back(type);
    constantsTypesGlobals.push_back(type);
    module.mapInstruction(type);

    return type->getResultId();
}

Id Builder::makeMatrixType(Id component, int cols, int rows)
{
    assert(cols <= maxMatrixSize && rows <= maxMatrixSize);

    Id column = makeVectorType(component, rows);

    // try to find it
    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)
            return type->getResultId();
    }

    // not found, make it
    type = new Instruction(getUniqueId(), NoType, OpTypeMatrix);
    type->addIdOperand(column);
    type->addImmediateOperand(cols);
    groupedTypes[OpTypeMatrix].push_back(type);
    constantsTypesGlobals.push_back(type);
    module.mapInstruction(type);

    return type->getResultId();
}

Id Builder::makeArrayType(Id element, unsigned size)
{
    // First, we need a constant instruction for the size
    Id sizeId = makeUintConstant(size);

    // try to find existing type
    Instruction* type;
    for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) {
        type = groupedTypes[OpTypeArray][t];
        if (type->getIdOperand(0) == element &&
            type->getIdOperand(1) == sizeId)
            return type->getResultId();
    }

    // not found, make it
    type = new Instruction(getUniqueId(), NoType, OpTypeArray);
    type->addIdOperand(element);
    type->addIdOperand(sizeId);
    groupedTypes[OpTypeArray].push_back(type);
    constantsTypesGlobals.push_back(type);
    module.mapInstruction(type);

    return type->getResultId();
}

Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
{
    // try to find it
    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)
            continue;
        bool mismatch = false;
        for (int p = 0; p < (int)paramTypes.size(); ++p) {
            if (paramTypes[p] != type->getIdOperand(p + 1)) {
                mismatch = true;
                break;
            }
        }
        if (! mismatch)
            return type->getResultId();            
    }

    // not found, make it
    type = new Instruction(getUniqueId(), NoType, OpTypeFunction);
    type->addIdOperand(returnType);
    for (int p = 0; p < (int)paramTypes.size(); ++p)
        type->addIdOperand(paramTypes[p]);
    groupedTypes[OpTypeFunction].push_back(type);
    constantsTypesGlobals.push_back(type);
    module.mapInstruction(type);

    return type->getResultId();
}

Id Builder::makeSampler(Id sampledType, Dim dim, samplerContent content, bool arrayed, bool shadow, bool ms)
{
    // try to find it
    Instruction* type;
    for (int t = 0; t < (int)groupedTypes[OpTypeSampler].size(); ++t) {
        type = groupedTypes[OpTypeSampler][t];
        if (type->getIdOperand(0) == sampledType &&
            type->getImmediateOperand(1) == (unsigned int)dim &&
            type->getImmediateOperand(2) == (unsigned int)content &&
            type->getImmediateOperand(3) == (arrayed ? 1u : 0u) &&
            type->getImmediateOperand(4) == ( shadow ? 1u : 0u) &&
            type->getImmediateOperand(5) == (     ms ? 1u : 0u))
            return type->getResultId();
    }

    // not found, make it
    type = new Instruction(getUniqueId(), NoType, OpTypeSampler);
    type->addIdOperand(sampledType);
    type->addImmediateOperand(   dim);
    type->addImmediateOperand(content);
    type->addImmediateOperand(arrayed ? 1 : 0);
    type->addImmediateOperand( shadow ? 1 : 0);
    type->addImmediateOperand(     ms ? 1 : 0);

    groupedTypes[OpTypeSampler].push_back(type);
    constantsTypesGlobals.push_back(type);
    module.mapInstruction(type);

    return type->getResultId();
}

Id Builder::getDerefTypeId(Id resultId) const
{
    Id typeId = getTypeId(resultId);
    assert(isPointerType(typeId));

    return module.getInstruction(typeId)->getImmediateOperand(1);
}

Op Builder::getMostBasicTypeClass(Id typeId) const
{
    Instruction* instr = module.getInstruction(typeId);

    Op typeClass = instr->getOpCode();
    switch (typeClass)
    {
    case OpTypeVoid:
    case OpTypeBool:
    case OpTypeInt:
    case OpTypeFloat:
    case OpTypeStruct:
        return typeClass;
    case OpTypeVector:
    case OpTypeMatrix:
    case OpTypeArray:
    case OpTypeRuntimeArray:
        return getMostBasicTypeClass(instr->getIdOperand(0));
    case OpTypePointer:
        return getMostBasicTypeClass(instr->getIdOperand(1));
    default:
        MissingFunctionality("getMostBasicTypeClass");
        return OpTypeFloat;
    }
}

int Builder::getNumTypeComponents(Id typeId) const
{
    Instruction* instr = module.getInstruction(typeId);

    switch (instr->getOpCode())
    {
    case OpTypeBool:
    case OpTypeInt:
    case OpTypeFloat:
        return 1;
    case OpTypeVector:
    case OpTypeMatrix:
        return instr->getImmediateOperand(1);
    default:
        MissingFunctionality("getNumTypeComponents on non bool/int/float/vector/matrix");
        return 1;
    }
}

// Return the lowest-level type of scalar that an homogeneous composite is made out of.
// Typically, this is just to find out if something is made out of ints or floats.
// However, it includes returning a structure, if say, it is an array of structure.
Id Builder::getScalarTypeId(Id typeId) const
{
    Instruction* instr = module.getInstruction(typeId);

    Op typeClass = instr->getOpCode();
    switch (typeClass)
    {
    case OpTypeVoid:
    case OpTypeBool:
    case OpTypeInt:
    case OpTypeFloat:
    case OpTypeStruct:
        return instr->getResultId();
    case OpTypeVector:
    case OpTypeMatrix:
    case OpTypeArray:
    case OpTypeRuntimeArray:
    case OpTypePointer:
        return getScalarTypeId(getContainedTypeId(typeId));
    default:
        MissingFunctionality("getScalarTypeId");
        return NoResult;
    }
}

// Return the type of 'member' of a composite.
Id Builder::getContainedTypeId(Id typeId, int member) const
{
    Instruction* instr = module.getInstruction(typeId);

    Op typeClass = instr->getOpCode();
    switch (typeClass)
    {
    case OpTypeVector:
    case OpTypeMatrix:
    case OpTypeArray:
    case OpTypeRuntimeArray:
        return instr->getIdOperand(0);
    case OpTypePointer:
        return instr->getIdOperand(1);
    case OpTypeStruct:
        return instr->getIdOperand(member);
    default:
        MissingFunctionality("getContainedTypeId");
        return NoResult;
    }
}

// Return the immediately contained type of a given composite type.
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, Id typeId, unsigned value) const
{
    Instruction* constant;
    for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
        constant = groupedConstants[typeClass][i];
        if (constant->getNumOperands() == 1 &&
            constant->getTypeId() == typeId &&
            constant->getImmediateOperand(0) == value)
            return constant->getResultId();
    }

    return 0;
}

// Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double').
Id Builder::findScalarConstant(Op typeClass, Id typeId, unsigned v1, unsigned v2) const
{
    Instruction* constant;
    for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
        constant = groupedConstants[typeClass][i];
        if (constant->getNumOperands() == 2 &&
            constant->getTypeId() == typeId &&
            constant->getImmediateOperand(0) == v1 &&
            constant->getImmediateOperand(1) == v2)
            return constant->getResultId();
    }

    return 0;
}

Id Builder::makeBoolConstant(bool b)
{
    Id typeId = makeBoolType();
    Instruction* constant;

    // See if we already made it
    Id existing = 0;
    for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) {
        constant = groupedConstants[OpTypeBool][i];
        if (constant->getTypeId() == typeId &&
            (b ? (constant->getOpCode() == OpConstantTrue) : 
                 (constant->getOpCode() == OpConstantFalse)))
            existing = constant->getResultId();
    }

    if (existing)
        return existing;

    // Make it
    Instruction* c = new Instruction(getUniqueId(), typeId, b ? OpConstantTrue : OpConstantFalse);
    constantsTypesGlobals.push_back(c);
    groupedConstants[OpTypeBool].push_back(c);
    module.mapInstruction(c);

    return c->getResultId();
}

Id Builder::makeIntConstant(Id typeId, unsigned value)
{
    Id existing = findScalarConstant(OpTypeInt, typeId, value);
    if (existing)
        return existing;

    Instruction* c = new Instruction(getUniqueId(), typeId, OpConstant);
    c->addImmediateOperand(value);
    constantsTypesGlobals.push_back(c);
    groupedConstants[OpTypeInt].push_back(c);
    module.mapInstruction(c);

    return c->getResultId();
}

Id Builder::makeFloatConstant(float f)
{
    Id typeId = makeFloatType(32);
    unsigned value = *(unsigned int*)&f;
    Id existing = findScalarConstant(OpTypeFloat, typeId, value);
    if (existing)
        return existing;

    Instruction* c = new Instruction(getUniqueId(), typeId, OpConstant);
    c->addImmediateOperand(value);
    constantsTypesGlobals.push_back(c);
    groupedConstants[OpTypeFloat].push_back(c);
    module.mapInstruction(c);

    return c->getResultId();
}

Id Builder::makeDoubleConstant(double d)
{
    Id typeId = makeFloatType(64);
    unsigned long long value = *(unsigned long long*)&d;
    unsigned op1 = value & 0xFFFFFFFF;
    unsigned op2 = value >> 32;
    Id existing = findScalarConstant(OpTypeFloat, typeId, op1, op2);
    if (existing)
        return existing;

    Instruction* c = new Instruction(getUniqueId(), typeId, OpConstant);
    c->addImmediateOperand(op1);
    c->addImmediateOperand(op2);
    constantsTypesGlobals.push_back(c);
    groupedConstants[OpTypeFloat].push_back(c);
    module.mapInstruction(c);

    return c->getResultId();
}

Id Builder::findCompositeConstant(Op typeClass, std::vector<Id>& comps) const
{
    Instruction* constant = 0;
    bool found = false;
    for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
        constant = groupedConstants[typeClass][i];

        // same shape?
        if (constant->getNumOperands() != (int)comps.size())
            continue;

        // same contents?
        bool mismatch = false;
        for (int op = 0; op < constant->getNumOperands(); ++op) {
            if (constant->getIdOperand(op) != comps[op]) {
                mismatch = true;
                break;
            }
        }
        if (! mismatch) {
            found = true;
            break;
        }
    }

    return found ? constant->getResultId() : NoResult;
}

// Comments in header
Id Builder::makeCompositeConstant(Id typeId, std::vector<Id>& members)
{
    assert(typeId);
    Op typeClass = getTypeClass(typeId);

    switch (typeClass) {
    case OpTypeVector:
    case OpTypeArray:
    case OpTypeStruct:
    case OpTypeMatrix:
        break;
    default:
        MissingFunctionality("Constant composite type in Builder");
        return makeFloatConstant(0.0);
    }

    Id existing = findCompositeConstant(typeClass, members);
    if (existing)
        return existing;

    Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantComposite);
    for (int op = 0; op < (int)members.size(); ++op)
        c->addIdOperand(members[op]);
    constantsTypesGlobals.push_back(c);
    groupedConstants[typeClass].push_back(c);
    module.mapInstruction(c);

    return c->getResultId();
}

void Builder::addEntryPoint(ExecutionModel model, Function* function)
{
    Instruction* entryPoint = new Instruction(OpEntryPoint);
    entryPoint->addImmediateOperand(model);
    entryPoint->addIdOperand(function->getId());

    entryPoints.push_back(entryPoint);
}

void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value)
{
    // TODO: handle multiple optional arguments
    Instruction* instr = new Instruction(OpExecutionMode);
    instr->addIdOperand(entryPoint->getId());
    instr->addImmediateOperand(mode);
    if (value >= 0)
        instr->addImmediateOperand(value);

    executionModes.push_back(instr);
}

void Builder::addName(Id id, const char* string)
{
    Instruction* name = new Instruction(OpName);
    name->addIdOperand(id);
    name->addStringOperand(string);

    names.push_back(name);
}

void Builder::addMemberName(Id id, int memberNumber, const char* string)
{
    Instruction* name = new Instruction(OpMemberName);
    name->addIdOperand(id);
    name->addImmediateOperand(memberNumber);
    name->addStringOperand(string);

    names.push_back(name);
}

void Builder::addLine(Id target, Id fileName, int lineNum, int column)
{
    Instruction* line = new Instruction(OpLine);
    line->addIdOperand(target);
    line->addIdOperand(fileName);
    line->addImmediateOperand(lineNum);
    line->addImmediateOperand(column);

    lines.push_back(line);
}

void Builder::addDecoration(Id id, Decoration decoration, int num)
{
    Instruction* dec = new Instruction(OpDecorate);
    dec->addIdOperand(id);
    dec->addImmediateOperand(decoration);
    if (num >= 0)
        dec->addImmediateOperand(num);

    decorations.push_back(dec);
}

void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
{
    Instruction* dec = new Instruction(OpMemberDecorate);
    dec->addIdOperand(id);
    dec->addImmediateOperand(member);
    dec->addImmediateOperand(decoration);
    if (num >= 0)
        dec->addImmediateOperand(num);

    decorations.push_back(dec);
}

// Comments in header
Function* Builder::makeMain()
{
    assert(! mainFunction);

    Block* entry;
    std::vector<Id> params;

    mainFunction = makeFunctionEntry(makeVoidType(), "main", params, &entry);
    stageExit = new Block(getUniqueId(), *mainFunction);

    return mainFunction;
}

// Comments in header
void Builder::closeMain()
{
    setBuildPoint(stageExit);
    stageExit->addInstruction(new Instruction(NoResult, NoType, OpReturn));
    mainFunction->addBlock(stageExit);
}

// Comments in header
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());
    Function* function = new Function(getUniqueId(), returnType, typeId, firstParamId, module);

    if (entry) {
        *entry = new Block(getUniqueId(), *function);
        function->addBlock(*entry);
        setBuildPoint(*entry);
    }

    if (name)
        addName(function->getId(), name);

    return function;
}

// Comments in header
void Builder::makeReturn(bool implicit, Id retVal, bool isMain)
{
    if (isMain && retVal)
        MissingFunctionality("return value from main()");

    if (isMain)
        createBranch(stageExit);
    else if (retVal) {
        Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue);
        inst->addIdOperand(retVal);
        buildPoint->addInstruction(inst);
    } else
        buildPoint->addInstruction(new Instruction(NoResult, NoType, OpReturn));

    if (! implicit)
        createAndSetNoPredecessorBlock("post-return");
}

// Comments in header
void Builder::leaveFunction(bool main)
{
    Block* block = buildPoint;
    Function& function = buildPoint->getParent();
    assert(block);

    // If our function did not contain a return, add a return void now.
    if (! block->isTerminated()) {

        // Whether we're in an unreachable (non-entry) block.
        bool unreachable = function.getEntryBlock() != block && block->getNumPredecessors() == 0;

        if (unreachable) {
            // Given that this block is at the end of a function, it must be right after an
            // explicit return, just remove it.
            function.popBlock(block);
        } else if (main)
            makeMainReturn(true);
        else {
            // We're get a return instruction at the end of the current block,
            // which for a non-void function is really error recovery (?), as the source
            // being translated should have had an explicit return, which would have been
            // followed by an unreachable block, which was handled above.
            if (function.getReturnType() == makeVoidType())
                makeReturn(true);
            else {
                Id retStorage = createVariable(StorageClassFunction, function.getReturnType(), "dummyReturn");
                Id retValue = createLoad(retStorage);
                makeReturn(true, retValue);
            }
        }
    }

    if (main)
        closeMain();
}

// Comments in header
void Builder::makeDiscard()
{
    buildPoint->addInstruction(new Instruction(OpKill));
    createAndSetNoPredecessorBlock("post-discard");
}

// Comments in header
Id Builder::createVariable(StorageClass storageClass, Id type, const char* name)
{
    Id pointerType = makePointer(storageClass, type);
    Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
    inst->addImmediateOperand(storageClass);

    switch (storageClass) {
    case StorageClassUniformConstant:
    case StorageClassUniform:
    case StorageClassInput:
    case StorageClassOutput:
    case StorageClassWorkgroupLocal:
    case StorageClassPrivateGlobal:
    case StorageClassWorkgroupGlobal:
        constantsTypesGlobals.push_back(inst);
        module.mapInstruction(inst);
        break;

    case StorageClassFunction:
        // Validation rules require the declaration in the entry block
        buildPoint->getParent().addLocalVariable(inst);
        break;

    default:
        MissingFunctionality("storage class in createVariable");
        break;
    }

    if (name)
        addName(inst->getResultId(), name);

    return inst->getResultId();
}

// Comments in header
void Builder::createStore(Id rValue, Id lValue)
{
    Instruction* store = new Instruction(OpStore);
    store->addIdOperand(lValue);
    store->addIdOperand(rValue);
    buildPoint->addInstruction(store);
}

// Comments in header
Id Builder::createLoad(Id lValue)
{
    Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
    load->addIdOperand(lValue);
    buildPoint->addInstruction(load);

    return load->getResultId();
}

// Comments in header
Id Builder::createAccessChain(StorageClass storageClass, Id base, std::vector<Id>& offsets)
{
    // Figure out the final resulting type.
    spv::Id typeId = getTypeId(base);
    assert(isPointerType(typeId) && offsets.size() > 0);
    typeId = getContainedTypeId(typeId);
    for (int i = 0; i < (int)offsets.size(); ++i) {
        if (isStructType(typeId)) {
            assert(isConstantScalar(offsets[i]));
            typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i]));
        } else
            typeId = getContainedTypeId(typeId, offsets[i]);
    }
    typeId = makePointer(storageClass, typeId);

    // Make the instruction
    Instruction* chain = new Instruction(getUniqueId(), typeId, OpAccessChain);
    chain->addIdOperand(base);
    for (int i = 0; i < (int)offsets.size(); ++i)
        chain->addIdOperand(offsets[i]);
    buildPoint->addInstruction(chain);

    return chain->getResultId();
}

Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
{
    Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
    extract->addIdOperand(composite);
    extract->addImmediateOperand(index);
    buildPoint->addInstruction(extract);

    return extract->getResultId();
}

Id Builder::createCompositeExtract(Id composite, Id typeId, std::vector<unsigned>& indexes)
{
    Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
    extract->addIdOperand(composite);
    for (int i = 0; i < (int)indexes.size(); ++i)
        extract->addImmediateOperand(indexes[i]);
    buildPoint->addInstruction(extract);

    return extract->getResultId();
}

Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned index)
{
    Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert);
    insert->addIdOperand(object);
    insert->addIdOperand(composite);
    insert->addImmediateOperand(index);
    buildPoint->addInstruction(insert);

    return insert->getResultId();
}

Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, std::vector<unsigned>& indexes)
{
    Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert);
    insert->addIdOperand(object);
    insert->addIdOperand(composite);
    for (int i = 0; i < (int)indexes.size(); ++i)
        insert->addImmediateOperand(indexes[i]);
    buildPoint->addInstruction(insert);

    return insert->getResultId();
}

Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex)
{
    Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic);
    extract->addIdOperand(vector);
    extract->addIdOperand(componentIndex);
    buildPoint->addInstruction(extract);

    return extract->getResultId();
}

Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex)
{
    Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic);
    insert->addIdOperand(vector);
    insert->addIdOperand(component);
    insert->addIdOperand(componentIndex);
    buildPoint->addInstruction(insert);

    return insert->getResultId();
}

// An opcode that has no operands, no result id, and no type
void Builder::createNoResultOp(Op opCode)
{
    Instruction* op = new Instruction(opCode);
    buildPoint->addInstruction(op);
}

// An opcode that has one operand, no result id, and no type
void Builder::createNoResultOp(Op opCode, Id operand)
{
    Instruction* op = new Instruction(opCode);
    op->addIdOperand(operand);
    buildPoint->addInstruction(op);
}

void Builder::createControlBarrier(unsigned executionScope)
{
    Instruction* op = new Instruction(OpControlBarrier);
    op->addImmediateOperand(executionScope);
    buildPoint->addInstruction(op);
}

void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics)
{
    Instruction* op = new Instruction(OpMemoryBarrier);
    op->addImmediateOperand(executionScope);
    op->addImmediateOperand(memorySemantics);
    buildPoint->addInstruction(op);
}

// An opcode that has one operands, a result id, and a type
Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
{
    Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
    op->addIdOperand(operand);
    buildPoint->addInstruction(op);

    return op->getResultId();
}

Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
{
    Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
    op->addIdOperand(left);
    op->addIdOperand(right);
    buildPoint->addInstruction(op);

    return op->getResultId();
}

Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
{
    Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
    op->addIdOperand(op1);
    op->addIdOperand(op2);
    op->addIdOperand(op3);
    buildPoint->addInstruction(op);

    return op->getResultId();
}

Id Builder::createOp(Op opCode, Id typeId, std::vector<Id>& operands)
{
    Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
    for (auto operand : operands)
        op->addIdOperand(operand);
    buildPoint->addInstruction(op);

    return op->getResultId();
}

Id Builder::createFunctionCall(spv::Function* function, std::vector<spv::Id>& args)
{
    Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall);
    op->addIdOperand(function->getId());
    for (int a = 0; a < (int)args.size(); ++a)
        op->addIdOperand(args[a]);
    buildPoint->addInstruction(op);

    return op->getResultId();
}

// Comments in header
Id Builder::createRvalueSwizzle(Id typeId, Id source, std::vector<unsigned>& channels)
{
    if (channels.size() == 1)
        return createCompositeExtract(source, typeId, channels.front());

    Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
    assert(isVector(source));
    swizzle->addIdOperand(source);
    swizzle->addIdOperand(source);
    for (int i = 0; i < (int)channels.size(); ++i)
        swizzle->addImmediateOperand(channels[i]);
    buildPoint->addInstruction(swizzle);

    return swizzle->getResultId();
}

// Comments in header
Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<unsigned>& channels)
{
    assert(getNumComponents(source) == (int)channels.size());
    if (channels.size() == 1 && getNumComponents(source) == 1)
        return createCompositeInsert(source, target, typeId, channels.front());

    Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
    assert(isVector(source));
    assert(isVector(target));
    swizzle->addIdOperand(target);
    swizzle->addIdOperand(source);

    // Set up an identity shuffle from the base value to the result value
    unsigned int components[4];
    int numTargetComponents = getNumComponents(target);
    for (int i = 0; i < numTargetComponents; ++i)
        components[i] = i;

    // Punch in the l-value swizzle
    for (int i = 0; i < (int)channels.size(); ++i)
        components[channels[i]] = numTargetComponents + i;

    // finish the instruction with these components selectors
    for (int i = 0; i < numTargetComponents; ++i)
        swizzle->addImmediateOperand(components[i]);
    buildPoint->addInstruction(swizzle);

    return swizzle->getResultId();
}

// Comments in header
void Builder::promoteScalar(Decoration precision, Id& left, Id& right)
{
    int direction = getNumComponents(right) - getNumComponents(left);

    if (direction > 0)
        left = smearScalar(precision, left, getTypeId(right));
    else if (direction < 0)
        right = smearScalar(precision, right, getTypeId(left));

    return;
}

// Comments in header
Id Builder::smearScalar(Decoration /*precision*/, Id scalar, Id vectorType)
{
    assert(getNumComponents(scalar) == 1);

    int numComponents = getNumTypeComponents(vectorType);
    if (numComponents == 1)
        return scalar;

    Instruction* smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
    for (int c = 0; c < numComponents; ++c)
        smear->addIdOperand(scalar);
    buildPoint->addInstruction(smear);

    return smear->getResultId();
}

// Comments in header
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);
    inst->addImmediateOperand(entryPoint);
    for (int arg = 0; arg < (int)args.size(); ++arg)
        inst->addIdOperand(args[arg]);

    buildPoint->addInstruction(inst);
    return inst->getResultId();
}

// 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 proj, const TextureParameters& parameters)
{
    static const int maxTextureArgs = 5;
    Id texArgs[maxTextureArgs] = {};

    //
    // Set up the arguments
    //

    int numArgs = 0;
    texArgs[numArgs++] = parameters.sampler;
    texArgs[numArgs++] = parameters.coords;

    if (parameters.gradX) {
        texArgs[numArgs++] = parameters.gradX;
        texArgs[numArgs++] = parameters.gradY;
    }
    if (parameters.lod)
        texArgs[numArgs++] = parameters.lod;
    if (parameters.offset)
        texArgs[numArgs++] = parameters.offset;
    if (parameters.bias)
        texArgs[numArgs++] = parameters.bias;
    if (parameters.Dref)
        texArgs[numArgs++] = parameters.Dref;

    //
    // Set up the instruction
    //

    Op opCode;
    if (proj && parameters.gradX && parameters.offset)
        opCode = OpTextureSampleProjGradOffset;
    else if (proj && parameters.lod && parameters.offset)
        opCode = OpTextureSampleProjLodOffset;
    else if (parameters.gradX && parameters.offset)
        opCode = OpTextureSampleGradOffset;
    else if (proj && parameters.offset)
        opCode = OpTextureSampleProjOffset;
    else if (parameters.lod && parameters.offset)
        opCode = OpTextureSampleLodOffset;
    else if (proj && parameters.gradX)
        opCode = OpTextureSampleProjGrad;
    else if (proj && parameters.lod)
        opCode = OpTextureSampleProjLod;
    else if (parameters.offset)
        opCode = OpTextureSampleOffset;
    else if (parameters.gradX)
        opCode = OpTextureSampleGrad;
    else if (proj)
        opCode = OpTextureSampleProj;
    else if (parameters.lod)
        opCode = OpTextureSampleLod;
    else if (parameters.Dref)
        opCode = OpTextureSampleDref;
    else
        opCode = OpTextureSample;

    Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode);
    for (int op = 0; op < numArgs; ++op)
        textureInst->addIdOperand(texArgs[op]);
    setPrecision(textureInst->getResultId(), precision);
    buildPoint->addInstruction(textureInst);

    return textureInst->getResultId();
}

// Comments in header
Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters)
{
    // Figure out the result type
    Id resultType = NoType;
    switch (opCode) {
    case OpTextureQuerySize:
    case OpTextureQuerySizeLod:
    {
        int numComponents;
        switch (getDimensionality(parameters.sampler)) {
        case Dim1D:
        case DimBuffer:
            numComponents = 1;
            break;
        case Dim2D:
        case DimCube:
        case DimRect:
            numComponents = 2;
            break;
        case Dim3D:
            numComponents = 3;
            break;
        default:
            MissingFunctionality("texture query dimensionality");
            break;
        }
        if (isArrayedSampler(parameters.sampler))
            ++numComponents;
        if (numComponents == 1)
            resultType = makeIntType(32);
        else
            resultType = makeVectorType(makeIntType(32), numComponents);

        break;
    }
    case OpTextureQueryLod:
        resultType = makeVectorType(makeFloatType(32), 2);
        break;
    case OpTextureQueryLevels:
    case OpTextureQuerySamples:
        resultType = makeIntType(32);
        break;
    default:
        MissingFunctionality("Texture query op code");
    }

    Instruction* query = new Instruction(getUniqueId(), resultType, opCode);
    query->addIdOperand(parameters.sampler);
    if (parameters.coords)
        query->addIdOperand(parameters.coords);
    if (parameters.lod)
        query->addIdOperand(parameters.lod);
    buildPoint->addInstruction(query);

    return query->getResultId();
}

// Comments in header
//Id Builder::createSamplePositionCall(Decoration precision, Id returnType, Id sampleIdx)
//{
//    // Return type is only flexible type
//    Function* opCode = (fSamplePosition, returnType);
//
//    Instruction* instr = (opCode, sampleIdx);
//    setPrecision(instr, precision);
//
//    return instr;
//}

// Comments in header
//Id Builder::createBitFieldExtractCall(Decoration precision, Id id, Id offset, Id bits, bool isSigned)
//{
//    Op opCode = isSigned ? sBitFieldExtract
//                                               : uBitFieldExtract;
//
//    if (isScalar(offset) == false || isScalar(bits) == false)
//        MissingFunctionality("bitFieldExtract operand types");
//
//    // Dest and value are matching flexible types
//    Function* opCode = (opCode, id->getType(), id->getType());
//
//    assert(opCode);
//
//    Instruction* instr = (opCode, id, offset, bits);
//    setPrecision(instr, precision);
//
//    return instr;
//}

// Comments in header
//Id Builder::createBitFieldInsertCall(Decoration precision, Id base, Id insert, Id offset, Id bits)
//{
//    Op opCode = bitFieldInsert;
//
//    if (isScalar(offset) == false || isScalar(bits) == false)
//        MissingFunctionality("bitFieldInsert operand types");
//
//    // Dest, base, and insert are matching flexible types
//    Function* opCode = (opCode, base->getType(), base->getType(), base->getType());
//
//    assert(opCode);
//
//    Instruction* instr = (opCode, base, insert, offset, bits);
//    setPrecision(instr, precision);
//
//    return instr;
//}

// Comments in header
Id Builder::createCompare(Decoration precision, Id value1, Id value2, bool equal)
{
    Id boolType = makeBoolType();
    Id valueType = getTypeId(value1);

    assert(valueType == getTypeId(value2));
    assert(! isScalar(value1));

    // Vectors

    if (isVectorType(valueType)) {
        Id boolVectorType = makeVectorType(boolType, getNumTypeComponents(valueType));
        Id boolVector;
        Op op;
        if (getMostBasicTypeClass(valueType) == OpTypeFloat)
            op = equal ? OpFOrdEqual : OpFOrdNotEqual;
        else
            op = equal ? OpIEqual : OpINotEqual;

        boolVector = createBinOp(op, boolVectorType, value1, value2);
        setPrecision(boolVector, precision);

        // Reduce vector compares with any() and all().

        op = equal ? OpAll : OpAny;

        return createUnaryOp(op, boolType, boolVector);
    }

    spv::MissingFunctionality("Composite comparison of non-vectors");

    return NoResult;

    // Recursively handle aggregates, which include matrices, arrays, and structures
    // and accumulate the results.

    // Matrices

    // Arrays

    //int numElements;
    //const llvm::ArrayType* arrayType = llvm::dyn_cast<llvm::ArrayType>(value1->getType());
    //if (arrayType)
    //    numElements = (int)arrayType->getNumElements();
    //else {
    //    // better be structure
    //    const llvm::StructType* structType = llvm::dyn_cast<llvm::StructType>(value1->getType());
    //    assert(structType);
    //    numElements = structType->getNumElements();
    //}

    //assert(numElements > 0);

    //for (int element = 0; element < numElements; ++element) {
    //    // Get intermediate comparison values
    //    llvm::Value* element1 = builder.CreateExtractValue(value1, element, "element1");
    //    setInstructionPrecision(element1, precision);
    //    llvm::Value* element2 = builder.CreateExtractValue(value2, element, "element2");
    //    setInstructionPrecision(element2, precision);

    //    llvm::Value* subResult = createCompare(precision, element1, element2, equal, "comp");

    //    // Accumulate intermediate comparison
    //    if (element == 0)
    //        result = subResult;
    //    else {
    //        if (equal)
    //            result = builder.CreateAnd(result, subResult);
    //        else
    //            result = builder.CreateOr(result, subResult);
    //        setInstructionPrecision(result, precision);
    //    }
    //}

    //return result;
}

// Comments in header
//Id Builder::createOperation(Decoration precision, Op opCode, Id operand)
//{
//    Op* opCode = 0;
//
//    // Handle special return types here.  Things that don't have same result type as parameter
//    switch (opCode) {
//    case fIsNan:
//    case fIsInf:
//        break;
//    case fFloatBitsToInt:
//        break;
//    case fIntBitsTofloat:
//        break;
//    case fPackSnorm2x16:
//    case fPackUnorm2x16:
//    case fPackHalf2x16:
//        break;
//    case fUnpackUnorm2x16:
//    case fUnpackSnorm2x16:
//    case fUnpackHalf2x16:
//        break;
//
//    case fFrexp:
//    case fLdexp:
//    case fPackUnorm4x8:
//    case fPackSnorm4x8:
//    case fUnpackUnorm4x8:
//    case fUnpackSnorm4x8:
//    case fPackDouble2x32:
//    case fUnpackDouble2x32:
//        break;
//    case fLength:
//       // scalar result type
//       break;
//    case any:
//    case all:
//        // fixed result type
//        break;
//    case fModF:
//        // modf() will return a struct that the caller must decode
//        break;
//    default:
//        // Unary operations that have operand and dest with same flexible type
//        break;
//    }
//
//    assert(opCode);
//
//    Instruction* instr = (opCode, operand);
//    setPrecision(instr, precision);
//
//    return instr;
//}
//
//// Comments in header
//Id Builder::createOperation(Decoration precision, Op opCode, Id operand0, Id operand1)
//{
//    Function* opCode = 0;
//
//    // Handle special return types here.  Things that don't have same result type as parameter
//    switch (opCode) {
//    case fDistance:
//    case fDot2:
//    case fDot3:
//    case fDot4:
//        // scalar result type
//        break;
//    case fStep:
//        // first argument can be scalar, return and second argument match
//        break;
//    case fSmoothStep:
//        // first argument can be scalar, return and second argument match
//        break;
//    default:
//        // Binary operations that have operand and dest with same flexible type
//        break;
//    }
//
//    assert(opCode);
//
//    Instruction* instr = (opCode, operand0, operand1);
//    setPrecision(instr, precision);
//
//    return instr;
//}
//
//Id Builder::createOperation(Decoration precision, Op opCode, Id operand0, Id operand1, Id operand2)
//{
//    Function* opCode;
//
//    // Handle special return types here.  Things that don't have same result type as parameter
//    switch (opCode) {
//    case fSmoothStep:
//        // first argument can be scalar, return and second argument match
//        break;
//    default:
//        // Use operand0 type as result type
//        break;
//    }
//
//    assert(opCode);
//
//    Instruction* instr = (opCode, operand0, operand1, operand2);
//    setPrecision(instr, precision);
//
//    return instr;
//}

// OpCompositeConstruct
Id Builder::createCompositeConstruct(Id typeId, std::vector<Id>& constituents)
{
    assert(isAggregateType(typeId) || (getNumTypeComponents(typeId) > 1 && getNumTypeComponents(typeId) == (int)constituents.size()));

    Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
    for (int c = 0; c < (int)constituents.size(); ++c)
        op->addIdOperand(constituents[c]);
    buildPoint->addInstruction(op);

    return op->getResultId();
}

// Vector or scalar constructor
Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
{
    Id result = 0;
    unsigned int numTargetComponents = getNumTypeComponents(resultTypeId);
    unsigned int targetComponent = 0;

    // Special case: when calling a vector constructor with a single scalar
    // argument, smear the scalar
    if (sources.size() == 1 && isScalar(sources[0]) && numTargetComponents > 1)
        return smearScalar(precision, sources[0], resultTypeId);

    Id scalarTypeId = getScalarTypeId(resultTypeId);
    std::vector<Id> constituents;  // accumulate the arguments for OpCompositeConstruct
    for (unsigned int i = 0; i < sources.size(); ++i) {
        if (isAggregate(sources[i]))
            MissingFunctionality("aggregate in vector constructor");

        unsigned int sourceSize = getNumComponents(sources[i]);

        unsigned int sourcesToUse = sourceSize;
        if (sourcesToUse + targetComponent > numTargetComponents)
            sourcesToUse = numTargetComponents - targetComponent;

        for (unsigned int s = 0; s < sourcesToUse; ++s) {
            Id arg = sources[i];
            if (sourceSize > 1) {
                std::vector<unsigned> swiz;
                swiz.push_back(s);
                arg = createRvalueSwizzle(scalarTypeId, arg, swiz);
            }

            if (numTargetComponents > 1)
                constituents.push_back(arg);
            else
                result = arg;
            ++targetComponent;
        }

        if (targetComponent >= numTargetComponents)
            break;
    }

    if (constituents.size() > 0)
        result = createCompositeConstruct(resultTypeId, constituents);

    setPrecision(result, precision);

    return result;
}

// Comments in header
Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
{
    Id componentTypeId = getScalarTypeId(resultTypeId);
    int numCols = getTypeNumColumns(resultTypeId);
    int numRows = getTypeNumRows(resultTypeId);

    // Will use a two step process
    // 1. make a compile-time 2D array of values
    // 2. construct a matrix from that array

    // Step 1.

    // initialize the array to the identity matrix
    Id ids[maxMatrixSize][maxMatrixSize];
    Id  one = makeFloatConstant(1.0);
    Id zero = makeFloatConstant(0.0);
    for (int col = 0; col < 4; ++col) {
        for (int row = 0; row < 4; ++row) {
            if (col == row)
                ids[col][row] = one;
            else
                ids[col][row] = zero;
        }
    }

    // modify components as dictated by the arguments
    if (sources.size() == 1 && isScalar(sources[0])) {
        // a single scalar; resets the diagonals
        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
        Id matrix = sources[0];
        int minCols = std::min(numCols, getNumColumns(matrix));
        int minRows = std::min(numRows, getNumRows(matrix));
        for (int col = 0; col < minCols; ++col) {
            std::vector<unsigned> indexes;
            indexes.push_back(col);
            for (int row = 0; row < minRows; ++row) {
                indexes.push_back(row);
                ids[col][row] = createCompositeExtract(matrix, componentTypeId, indexes);
                indexes.pop_back();
                setPrecision(ids[col][row], precision);
            }
        }
    } else {
        // fill in the matrix in column-major order with whatever argument components are available
        int row = 0;
        int col = 0;

        for (int arg = 0; arg < (int)sources.size(); ++arg) {
            Id argComp = sources[arg];
            for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) {
                if (getNumComponents(sources[arg]) > 1) {
                    argComp = createCompositeExtract(sources[arg], componentTypeId, comp);
                    setPrecision(argComp, precision);
                }
                ids[col][row++] = argComp;
                if (row == numRows) {
                    row = 0;
                    col++;
                }
            }
        }
    }


    // Step 2:  Construct a matrix from that array.
    // First make the column vectors, then make the matrix.

    // make the column vectors
    Id columnTypeId = getContainedTypeId(resultTypeId);
    std::vector<Id> matrixColumns;
    for (int col = 0; col < numCols; ++col) {
        std::vector<Id> vectorComponents;
        for (int row = 0; row < numRows; ++row)
            vectorComponents.push_back(ids[col][row]);
        matrixColumns.push_back(createCompositeConstruct(columnTypeId, vectorComponents));
    }

    // make the matrix
    return createCompositeConstruct(resultTypeId, matrixColumns);
}

// Comments in header
Builder::If::If(Id cond, Builder& gb) :
    builder(gb),
    condition(cond),
    elseBlock(0)
{
    function = &builder.getBuildPoint()->getParent();

    // make the blocks, but only put the then-block into the function,
    // the else-block and merge-block will be added later, in order, after
    // earlier code is emitted
    thenBlock = new Block(builder.getUniqueId(), *function);
    mergeBlock = new Block(builder.getUniqueId(), *function);

    // Save the current block, so that we can add in the flow control split when
    // makeEndIf is called.
    headerBlock = builder.getBuildPoint();

    function->addBlock(thenBlock);
    builder.setBuildPoint(thenBlock);
}

// Comments in header
void Builder::If::makeBeginElse()
{
    // Close out the "then" by having it jump to the mergeBlock
    builder.createBranch(mergeBlock);

    // Make the first else block and add it to the function
    elseBlock = new Block(builder.getUniqueId(), *function);
    function->addBlock(elseBlock);

    // Start building the else block
    builder.setBuildPoint(elseBlock);
}

// Comments in header
void Builder::If::makeEndIf()
{
    // jump to the merge block
    builder.createBranch(mergeBlock);

    // Go back to the headerBlock and make the flow control split
    builder.setBuildPoint(headerBlock);
    builder.createMerge(OpSelectionMerge, mergeBlock, SelectionControlMaskNone);
    if (elseBlock)
        builder.createConditionalBranch(condition, thenBlock, elseBlock);
    else
        builder.createConditionalBranch(condition, thenBlock, mergeBlock);

    // add the merge block to the function
    function->addBlock(mergeBlock);
    builder.setBuildPoint(mergeBlock);
}

// Comments in header
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 all the blocks
    for (int s = 0; s < numSegments; ++s)
        segmentBlocks.push_back(new Block(getUniqueId(), function));

    Block* mergeBlock = new Block(getUniqueId(), function);

    // make and insert the switch's selection-merge instruction
    createMerge(OpSelectionMerge, mergeBlock, SelectionControlMaskNone);

    // make the switch instruction
    Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
    switchInst->addIdOperand(selector);
    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());
    }
    buildPoint->addInstruction(switchInst);

    // push the merge block
    switchMerges.push(mergeBlock);
}

// Comments in header
void Builder::addSwitchBreak()
{
    // branch to the top of the merge block stack
    createBranch(switchMerges.top());
    createAndSetNoPredecessorBlock("post-switch-break");
}

// Comments in header
void Builder::nextSwitchSegment(std::vector<Block*>& segmentBlock, int nextSegment)
{
    int lastSegment = nextSegment - 1;
    if (lastSegment >= 0) {
        // Close out previous segment by jumping, if necessary, to next segment
        if (! buildPoint->isTerminated())
            createBranch(segmentBlock[nextSegment]);
    }
    Block* block = segmentBlock[nextSegment];
    block->getParent().addBlock(block);
    setBuildPoint(block);
}

// Comments in header
void Builder::endSwitch(std::vector<Block*>& /*segmentBlock*/)
{
    // Close out previous segment by jumping, if necessary, to next segment
    if (! buildPoint->isTerminated())
        addSwitchBreak();

    switchMerges.top()->getParent().addBlock(switchMerges.top());
    setBuildPoint(switchMerges.top());

    switchMerges.pop();
}

// Comments in header
void Builder::makeNewLoop(bool loopTestFirst)
{
    loops.push(Loop(*this, loopTestFirst));
    const Loop& loop = loops.top();

    // The loop test is always emitted before the loop body.
    // But if the loop test executes at the bottom of the loop, then
    // execute the test only on the second and subsequent iterations.

    // Remember the block that branches to the loop header.  This
    // is required for the test-after-body case.
    Block* preheader = getBuildPoint();

    // Branch into the loop
    createBranch(loop.header);

    // Set ourselves inside the loop
    loop.function->addBlock(loop.header);
    setBuildPoint(loop.header);

    if (!loopTestFirst) {
        // Generate code to defer the loop test until the second and
        // subsequent iterations.

        // It's always the first iteration when coming from the preheader.
        // All other branches to this loop header will need to indicate "false",
        // but we don't yet know where they will come from.
        loop.isFirstIteration->addIdOperand(makeBoolConstant(true));
        loop.isFirstIteration->addIdOperand(preheader->getId());
        getBuildPoint()->addInstruction(loop.isFirstIteration);

        // Mark the end of the structured loop. This must exist in the loop header block.
        createMerge(OpLoopMerge, loop.merge, LoopControlMaskNone);

        // Generate code to see if this is the first iteration of the loop.
        // It needs to be in its own block, since the loop merge and
        // the selection merge instructions can't both be in the same
        // (header) block.
        Block* firstIterationCheck = new Block(getUniqueId(), *loop.function);
        createBranch(firstIterationCheck);
        loop.function->addBlock(firstIterationCheck);
        setBuildPoint(firstIterationCheck);

        // Control flow after this "if" normally reconverges at the loop body.
        // However, the loop test has a "break branch" out of this selection
        // construct because it can transfer control to the loop merge block.
        createMerge(OpSelectionMerge, loop.body, SelectionControlMaskNone);

        Block* loopTest = new Block(getUniqueId(), *loop.function);
        createConditionalBranch(loop.isFirstIteration->getResultId(), loop.body, loopTest);

        loop.function->addBlock(loopTest);
        setBuildPoint(loopTest);
    }
}

void Builder::createLoopTestBranch(Id condition)
{
    const Loop& loop = loops.top();

    // Generate the merge instruction. If the loop test executes before
    // the body, then this is a loop merge.  Otherwise the loop merge
    // has already been generated and this is a conditional merge.
    if (loop.testFirst) {
        createMerge(OpLoopMerge, loop.merge, LoopControlMaskNone);
        // Branching to the "body" block will keep control inside
        // the loop.
        createConditionalBranch(condition, loop.body, loop.merge);
        loop.function->addBlock(loop.body);
        setBuildPoint(loop.body);
    } else {
        // The branch to the loop merge block is the allowed exception
        // to the structured control flow.  Otherwise, control flow will
        // continue to loop.body block.  Since that is already the target
        // of a merge instruction, and a block can't be the target of more
        // than one merge instruction, we need to make an intermediate block.
        Block* stayInLoopBlock = new Block(getUniqueId(), *loop.function);
        createMerge(OpSelectionMerge, stayInLoopBlock, SelectionControlMaskNone);

        // This is the loop test.
        createConditionalBranch(condition, stayInLoopBlock, loop.merge);

        // The dummy block just branches to the real loop body.
        loop.function->addBlock(stayInLoopBlock);
        setBuildPoint(stayInLoopBlock);
        createBranchToBody();
    }
}

void Builder::createBranchToBody()
{
    const Loop& loop = loops.top();
    assert(loop.body);

    // This is a reconvergence of control flow, so no merge instruction
    // is required.
    createBranch(loop.body);
    loop.function->addBlock(loop.body);
    setBuildPoint(loop.body);
}

void Builder::createLoopContinue()
{
    createBranchToLoopHeaderFromInside(loops.top());
    // Set up a block for dead code.
    createAndSetNoPredecessorBlock("post-loop-continue");
}

// Add an exit (e.g. "break") for the innermost loop that you're in
void Builder::createLoopExit()
{
    createBranch(loops.top().merge);
    // Set up a block for dead code.
    createAndSetNoPredecessorBlock("post-loop-break");
}

// Close the innermost loop
void Builder::closeLoop()
{
    const Loop& loop = loops.top();

    // Branch back to the top
    createBranchToLoopHeaderFromInside(loop);

    // Add the merge block and set the build point to it
    loop.function->addBlock(loop.merge);
    setBuildPoint(loop.merge);

    loops.pop();
}

// Create a branch to the header of the given loop, from inside
// the loop body.
// Adjusts the phi node for the first-iteration value if needeed.
void Builder::createBranchToLoopHeaderFromInside(const Loop& loop)
{
    createBranch(loop.header);
    if (loop.isFirstIteration) {
        loop.isFirstIteration->addIdOperand(makeBoolConstant(false));
        loop.isFirstIteration->addIdOperand(getBuildPoint()->getId());
    }
}

void Builder::clearAccessChain()
{
    accessChain.base = 0;
    accessChain.indexChain.clear();
    accessChain.instr = 0;
    accessChain.swizzle.clear();
    accessChain.component = 0;
    accessChain.resultType = NoType;
    accessChain.isRValue = false;
}

// Comments in header
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle)
{
    // if needed, propagate the swizzle for the current access chain
    if (accessChain.swizzle.size()) {
        std::vector<unsigned> oldSwizzle = accessChain.swizzle;
        accessChain.swizzle.resize(0);
        for (unsigned int i = 0; i < swizzle.size(); ++i) {
            accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]);
        }
    } else
        accessChain.swizzle = swizzle;

    // determine if we need to track this swizzle anymore
    simplifyAccessChainSwizzle();
}

// Comments in header
void Builder::accessChainStore(Id rvalue)
{
    assert(accessChain.isRValue == false);

    Id base = collapseAccessChain();

    if (accessChain.swizzle.size() && accessChain.component)
        MissingFunctionality("simultaneous l-value swizzle and dynamic component selection");

    // If swizzle exists, it is out-of-order or not full, we must load the target vector,
    // extract and insert elements to perform writeMask and/or swizzle.
    Id source = NoResult;
    if (accessChain.swizzle.size()) {
        Id tempBaseId = createLoad(base);
        source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, rvalue, accessChain.swizzle);
    }

    // dynamic component selection
    if (accessChain.component) {
        Id tempBaseId = (source == NoResult) ? createLoad(base) : source;
        source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue, accessChain.component);
    }

    if (source == NoResult)
        source = rvalue;

    createStore(source, base);
}

// Comments in header
Id Builder::accessChainLoad(Decoration /*precision*/)
{
    Id id;

    if (accessChain.isRValue) {
        if (accessChain.indexChain.size() > 0) {
            mergeAccessChainSwizzle();  // TODO: optimization: look at applying this optimization more widely
            // if all the accesses are constants, we can use OpCompositeExtract
            std::vector<unsigned> indexes;
            bool constant = true;
            for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) {
                if (isConstantScalar(accessChain.indexChain[i]))
                    indexes.push_back(getConstantScalar(accessChain.indexChain[i]));
                else {
                    constant = false;
                    break;
                }
            }

            if (constant)
                id = createCompositeExtract(accessChain.base, accessChain.resultType, indexes);
            else {
                // make a new function variable for this r-value
                Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");

                // store into it
                createStore(accessChain.base, lValue);

                // move base to the new variable
                accessChain.base = lValue;
                accessChain.isRValue = false;

                // load through the access chain
                id = createLoad(collapseAccessChain());
            }
        } else
            id = accessChain.base;
    } else {
        // load through the access chain
        id = createLoad(collapseAccessChain());
    }

    // Done, unless there are swizzles to do
    if (accessChain.swizzle.size() == 0 && accessChain.component == 0)
        return id;

    Id componentType = getScalarTypeId(accessChain.resultType);

    // Do remaining swizzling
    // First, static swizzling
    if (accessChain.swizzle.size()) {
        // static swizzle
        Id resultType = componentType;
        if (accessChain.swizzle.size() > 1)
            resultType = makeVectorType(componentType, (int)accessChain.swizzle.size());
        id = createRvalueSwizzle(resultType, id, accessChain.swizzle);
    }

    // dynamic single-component selection
    if (accessChain.component)
        id = createVectorExtractDynamic(id, componentType, accessChain.component);

    return id;
}

Id Builder::accessChainGetLValue()
{
    assert(accessChain.isRValue == false);

    Id lvalue = collapseAccessChain();

    // If swizzle exists, it is out-of-order or not full, we must load the target vector,
    // extract and insert elements to perform writeMask and/or swizzle.  This does not
    // go with getting a direct l-value pointer.
    assert(accessChain.swizzle.size() == 0);
    assert(accessChain.component == spv::NoResult);

    return lvalue;
}

void Builder::dump(std::vector<unsigned int>& out) const
{
    // Header, before first instructions:
    out.push_back(MagicNumber);
    out.push_back(Version);
    out.push_back(builderNumber);
    out.push_back(uniqueId + 1);
    out.push_back(0);

    // First instructions, some created on the spot here:
    if (source != SourceLanguageUnknown) {
        Instruction sourceInst(0, 0, OpSource);
        sourceInst.addImmediateOperand(source);
        sourceInst.addImmediateOperand(sourceVersion);
        sourceInst.dump(out);
    }
    for (int e = 0; e < (int)extensions.size(); ++e) {
        Instruction extInst(0, 0, OpSourceExtension);
        extInst.addStringOperand(extensions[e]);
        extInst.dump(out);
    }
    // TBD: OpExtension ...
    dumpInstructions(out, imports);
    Instruction memInst(0, 0, OpMemoryModel);
    memInst.addImmediateOperand(addressModel);
    memInst.addImmediateOperand(memoryModel);
    memInst.dump(out);

    // Instructions saved up while building:
    dumpInstructions(out, entryPoints);
    dumpInstructions(out, executionModes);
    dumpInstructions(out, names);
    dumpInstructions(out, lines);
    dumpInstructions(out, decorations);
    dumpInstructions(out, constantsTypesGlobals);
    dumpInstructions(out, externals);

    // The functions
    module.dump(out);
}

//
// Protected methods.
//

Id Builder::collapseAccessChain()
{
    // TODO: bring in an individual component swizzle here, so that a pointer 
    // all the way to the component level can be created.
    assert(accessChain.isRValue == false);

    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);
        }

        return accessChain.instr;
    } else
        return accessChain.base;
}

// clear out swizzle if it is redundant
void Builder::simplifyAccessChainSwizzle()
{
    // If the swizzle has fewer components than the vector, it is subsetting, and must stay
    // to preserve that fact.
    if (getNumTypeComponents(accessChain.resultType) > (int)accessChain.swizzle.size())
        return;

    // if components are out of order, it is a swizzle
    for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) {
        if (i != accessChain.swizzle[i])
            return;
    }

    // otherwise, there is no need to track this swizzle
    accessChain.swizzle.clear();
}

// clear out swizzle if it can become part of the indexes
void Builder::mergeAccessChainSwizzle()
{
    // is there even a chance of doing something?  Need a single-component swizzle
    if ((accessChain.swizzle.size() > 1) ||
        (accessChain.swizzle.size() == 0 && accessChain.component == 0))
        return;

    // TODO: optimization: remove this, but for now confine this to non-dynamic accesses
    // (the above test is correct when this is removed.)
    if (accessChain.component)
        return;

    // move the swizzle over to the indexes
    if (accessChain.swizzle.size() == 1)
        accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
    else
        accessChain.indexChain.push_back(accessChain.component);
    accessChain.resultType = getScalarTypeId(accessChain.resultType);

    // now there is no need to track this swizzle
    accessChain.component = NoResult;
    accessChain.swizzle.clear();
}

// Utility method for creating a new block and setting the insert point to
// be in it. This is useful for flow-control operations that need a "dummy"
// block proceeding them (e.g. instructions after a discard, etc).
void Builder::createAndSetNoPredecessorBlock(const char* /*name*/)
{
    Block* block = new Block(getUniqueId(), buildPoint->getParent());
    block->setUnreachable();
    buildPoint->getParent().addBlock(block);
    setBuildPoint(block);

    //if (name)
    //    addName(block->getId(), name);
}

// Comments in header
void Builder::createBranch(Block* block)
{
    Instruction* branch = new Instruction(OpBranch);
    branch->addIdOperand(block->getId());
    buildPoint->addInstruction(branch);
    block->addPredecessor(buildPoint);
}

void Builder::createMerge(Op mergeCode, Block* mergeBlock, unsigned int control)
{
    Instruction* merge = new Instruction(mergeCode);
    merge->addIdOperand(mergeBlock->getId());
    merge->addImmediateOperand(control);
    buildPoint->addInstruction(merge);
}

void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock)
{
    Instruction* branch = new Instruction(OpBranchConditional);
    branch->addIdOperand(condition);
    branch->addIdOperand(thenBlock->getId());
    branch->addIdOperand(elseBlock->getId());
    buildPoint->addInstruction(branch);
    thenBlock->addPredecessor(buildPoint);
    elseBlock->addPredecessor(buildPoint);
}

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 TbdFunctionality(const char* tbd)
{
    static std::unordered_set<const char*> issued;

    if (issued.find(tbd) == issued.end()) {
        printf("TBD functionality: %s\n", tbd);
        issued.insert(tbd);
    }
}

void MissingFunctionality(const char* fun)
{
    printf("Missing functionality: %s\n", fun);
    exit(1);
}

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(testFirst
                     ? nullptr
                     : new Instruction(builder.getUniqueId(), builder.makeBoolType(), OpPhi))
  {}

}; // end spv namespace
