1617a3babSopenharmony_ci// 2617a3babSopenharmony_ci// Copyright (C) 2014-2015 LunarG, Inc. 3617a3babSopenharmony_ci// Copyright (C) 2015-2018 Google, Inc. 4617a3babSopenharmony_ci// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. 5617a3babSopenharmony_ci// 6617a3babSopenharmony_ci// All rights reserved. 7617a3babSopenharmony_ci// 8617a3babSopenharmony_ci// Redistribution and use in source and binary forms, with or without 9617a3babSopenharmony_ci// modification, are permitted provided that the following conditions 10617a3babSopenharmony_ci// are met: 11617a3babSopenharmony_ci// 12617a3babSopenharmony_ci// Redistributions of source code must retain the above copyright 13617a3babSopenharmony_ci// notice, this list of conditions and the following disclaimer. 14617a3babSopenharmony_ci// 15617a3babSopenharmony_ci// Redistributions in binary form must reproduce the above 16617a3babSopenharmony_ci// copyright notice, this list of conditions and the following 17617a3babSopenharmony_ci// disclaimer in the documentation and/or other materials provided 18617a3babSopenharmony_ci// with the distribution. 19617a3babSopenharmony_ci// 20617a3babSopenharmony_ci// Neither the name of 3Dlabs Inc. Ltd. nor the names of its 21617a3babSopenharmony_ci// contributors may be used to endorse or promote products derived 22617a3babSopenharmony_ci// from this software without specific prior written permission. 23617a3babSopenharmony_ci// 24617a3babSopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25617a3babSopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26617a3babSopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27617a3babSopenharmony_ci// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28617a3babSopenharmony_ci// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29617a3babSopenharmony_ci// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 30617a3babSopenharmony_ci// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31617a3babSopenharmony_ci// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32617a3babSopenharmony_ci// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33617a3babSopenharmony_ci// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 34617a3babSopenharmony_ci// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35617a3babSopenharmony_ci// POSSIBILITY OF SUCH DAMAGE. 36617a3babSopenharmony_ci 37617a3babSopenharmony_ci// 38617a3babSopenharmony_ci// Helper for making SPIR-V IR. Generally, this is documented in the header 39617a3babSopenharmony_ci// SpvBuilder.h. 40617a3babSopenharmony_ci// 41617a3babSopenharmony_ci 42617a3babSopenharmony_ci#include <cassert> 43617a3babSopenharmony_ci#include <cstdlib> 44617a3babSopenharmony_ci 45617a3babSopenharmony_ci#include <unordered_set> 46617a3babSopenharmony_ci#include <algorithm> 47617a3babSopenharmony_ci 48617a3babSopenharmony_ci#include "SpvBuilder.h" 49617a3babSopenharmony_ci#include "hex_float.h" 50617a3babSopenharmony_ci 51617a3babSopenharmony_ci#ifndef _WIN32 52617a3babSopenharmony_ci #include <cstdio> 53617a3babSopenharmony_ci#endif 54617a3babSopenharmony_ci 55617a3babSopenharmony_cinamespace spv { 56617a3babSopenharmony_ci 57617a3babSopenharmony_ciBuilder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogger* buildLogger) : 58617a3babSopenharmony_ci spvVersion(spvVersion), 59617a3babSopenharmony_ci sourceLang(SourceLanguageUnknown), 60617a3babSopenharmony_ci sourceVersion(0), 61617a3babSopenharmony_ci sourceFileStringId(NoResult), 62617a3babSopenharmony_ci currentLine(0), 63617a3babSopenharmony_ci currentFile(nullptr), 64617a3babSopenharmony_ci currentFileId(NoResult), 65617a3babSopenharmony_ci lastDebugScopeId(NoResult), 66617a3babSopenharmony_ci emitOpLines(false), 67617a3babSopenharmony_ci emitNonSemanticShaderDebugInfo(false), 68617a3babSopenharmony_ci addressModel(AddressingModelLogical), 69617a3babSopenharmony_ci memoryModel(MemoryModelGLSL450), 70617a3babSopenharmony_ci builderNumber(magicNumber), 71617a3babSopenharmony_ci buildPoint(nullptr), 72617a3babSopenharmony_ci uniqueId(0), 73617a3babSopenharmony_ci entryPointFunction(nullptr), 74617a3babSopenharmony_ci generatingOpCodeForSpecConst(false), 75617a3babSopenharmony_ci logger(buildLogger) 76617a3babSopenharmony_ci{ 77617a3babSopenharmony_ci clearAccessChain(); 78617a3babSopenharmony_ci} 79617a3babSopenharmony_ci 80617a3babSopenharmony_ciBuilder::~Builder() 81617a3babSopenharmony_ci{ 82617a3babSopenharmony_ci} 83617a3babSopenharmony_ci 84617a3babSopenharmony_ciId Builder::import(const char* name) 85617a3babSopenharmony_ci{ 86617a3babSopenharmony_ci Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport); 87617a3babSopenharmony_ci import->addStringOperand(name); 88617a3babSopenharmony_ci module.mapInstruction(import); 89617a3babSopenharmony_ci 90617a3babSopenharmony_ci imports.push_back(std::unique_ptr<Instruction>(import)); 91617a3babSopenharmony_ci return import->getResultId(); 92617a3babSopenharmony_ci} 93617a3babSopenharmony_ci 94617a3babSopenharmony_ci// Emit instruction for non-filename-based #line directives (ie. no filename 95617a3babSopenharmony_ci// seen yet): emit an OpLine if we've been asked to emit OpLines and the line 96617a3babSopenharmony_ci// number has changed since the last time, and is a valid line number. 97617a3babSopenharmony_civoid Builder::setLine(int lineNum) 98617a3babSopenharmony_ci{ 99617a3babSopenharmony_ci if (lineNum != 0 && lineNum != currentLine) { 100617a3babSopenharmony_ci currentLine = lineNum; 101617a3babSopenharmony_ci if (emitOpLines) { 102617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 103617a3babSopenharmony_ci addDebugScopeAndLine(currentFileId, currentLine, 0); 104617a3babSopenharmony_ci else 105617a3babSopenharmony_ci addLine(sourceFileStringId, currentLine, 0); 106617a3babSopenharmony_ci } 107617a3babSopenharmony_ci } 108617a3babSopenharmony_ci} 109617a3babSopenharmony_ci 110617a3babSopenharmony_ci// If no filename, do non-filename-based #line emit. Else do filename-based emit. 111617a3babSopenharmony_ci// Emit OpLine if we've been asked to emit OpLines and the line number or filename 112617a3babSopenharmony_ci// has changed since the last time, and line number is valid. 113617a3babSopenharmony_civoid Builder::setLine(int lineNum, const char* filename) 114617a3babSopenharmony_ci{ 115617a3babSopenharmony_ci if (filename == nullptr) { 116617a3babSopenharmony_ci setLine(lineNum); 117617a3babSopenharmony_ci return; 118617a3babSopenharmony_ci } 119617a3babSopenharmony_ci if ((lineNum != 0 && lineNum != currentLine) || currentFile == nullptr || 120617a3babSopenharmony_ci strncmp(filename, currentFile, strlen(currentFile) + 1) != 0) { 121617a3babSopenharmony_ci currentLine = lineNum; 122617a3babSopenharmony_ci currentFile = filename; 123617a3babSopenharmony_ci if (emitOpLines) { 124617a3babSopenharmony_ci spv::Id strId = getStringId(filename); 125617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 126617a3babSopenharmony_ci addDebugScopeAndLine(strId, currentLine, 0); 127617a3babSopenharmony_ci else 128617a3babSopenharmony_ci addLine(strId, currentLine, 0); 129617a3babSopenharmony_ci } 130617a3babSopenharmony_ci } 131617a3babSopenharmony_ci} 132617a3babSopenharmony_ci 133617a3babSopenharmony_civoid Builder::addLine(Id fileName, int lineNum, int column) 134617a3babSopenharmony_ci{ 135617a3babSopenharmony_ci Instruction* line = new Instruction(OpLine); 136617a3babSopenharmony_ci line->addIdOperand(fileName); 137617a3babSopenharmony_ci line->addImmediateOperand(lineNum); 138617a3babSopenharmony_ci line->addImmediateOperand(column); 139617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(line)); 140617a3babSopenharmony_ci} 141617a3babSopenharmony_ci 142617a3babSopenharmony_civoid Builder::addDebugScopeAndLine(Id fileName, int lineNum, int column) 143617a3babSopenharmony_ci{ 144617a3babSopenharmony_ci assert(!currentDebugScopeId.empty()); 145617a3babSopenharmony_ci if (currentDebugScopeId.top() != lastDebugScopeId) { 146617a3babSopenharmony_ci spv::Id resultId = getUniqueId(); 147617a3babSopenharmony_ci Instruction* scopeInst = new Instruction(resultId, makeVoidType(), OpExtInst); 148617a3babSopenharmony_ci scopeInst->addIdOperand(nonSemanticShaderDebugInfo); 149617a3babSopenharmony_ci scopeInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugScope); 150617a3babSopenharmony_ci scopeInst->addIdOperand(currentDebugScopeId.top()); 151617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(scopeInst)); 152617a3babSopenharmony_ci lastDebugScopeId = currentDebugScopeId.top(); 153617a3babSopenharmony_ci } 154617a3babSopenharmony_ci spv::Id resultId = getUniqueId(); 155617a3babSopenharmony_ci Instruction* lineInst = new Instruction(resultId, makeVoidType(), OpExtInst); 156617a3babSopenharmony_ci lineInst->addIdOperand(nonSemanticShaderDebugInfo); 157617a3babSopenharmony_ci lineInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLine); 158617a3babSopenharmony_ci lineInst->addIdOperand(makeDebugSource(fileName)); 159617a3babSopenharmony_ci lineInst->addIdOperand(makeUintConstant(lineNum)); 160617a3babSopenharmony_ci lineInst->addIdOperand(makeUintConstant(lineNum)); 161617a3babSopenharmony_ci lineInst->addIdOperand(makeUintConstant(column)); 162617a3babSopenharmony_ci lineInst->addIdOperand(makeUintConstant(column)); 163617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(lineInst)); 164617a3babSopenharmony_ci} 165617a3babSopenharmony_ci 166617a3babSopenharmony_ci// For creating new groupedTypes (will return old type if the requested one was already made). 167617a3babSopenharmony_ciId Builder::makeVoidType() 168617a3babSopenharmony_ci{ 169617a3babSopenharmony_ci Instruction* type; 170617a3babSopenharmony_ci if (groupedTypes[OpTypeVoid].size() == 0) { 171617a3babSopenharmony_ci Id typeId = getUniqueId(); 172617a3babSopenharmony_ci type = new Instruction(typeId, NoType, OpTypeVoid); 173617a3babSopenharmony_ci groupedTypes[OpTypeVoid].push_back(type); 174617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 175617a3babSopenharmony_ci module.mapInstruction(type); 176617a3babSopenharmony_ci // Core OpTypeVoid used for debug void type 177617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 178617a3babSopenharmony_ci debugId[typeId] = typeId; 179617a3babSopenharmony_ci } else 180617a3babSopenharmony_ci type = groupedTypes[OpTypeVoid].back(); 181617a3babSopenharmony_ci 182617a3babSopenharmony_ci return type->getResultId(); 183617a3babSopenharmony_ci} 184617a3babSopenharmony_ci 185617a3babSopenharmony_ciId Builder::makeBoolType() 186617a3babSopenharmony_ci{ 187617a3babSopenharmony_ci Instruction* type; 188617a3babSopenharmony_ci if (groupedTypes[OpTypeBool].size() == 0) { 189617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeBool); 190617a3babSopenharmony_ci groupedTypes[OpTypeBool].push_back(type); 191617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 192617a3babSopenharmony_ci module.mapInstruction(type); 193617a3babSopenharmony_ci 194617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) { 195617a3babSopenharmony_ci auto const debugResultId = makeBoolDebugType(32); 196617a3babSopenharmony_ci debugId[type->getResultId()] = debugResultId; 197617a3babSopenharmony_ci } 198617a3babSopenharmony_ci 199617a3babSopenharmony_ci } else 200617a3babSopenharmony_ci type = groupedTypes[OpTypeBool].back(); 201617a3babSopenharmony_ci 202617a3babSopenharmony_ci 203617a3babSopenharmony_ci return type->getResultId(); 204617a3babSopenharmony_ci} 205617a3babSopenharmony_ci 206617a3babSopenharmony_ciId Builder::makeSamplerType() 207617a3babSopenharmony_ci{ 208617a3babSopenharmony_ci Instruction* type; 209617a3babSopenharmony_ci if (groupedTypes[OpTypeSampler].size() == 0) { 210617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeSampler); 211617a3babSopenharmony_ci groupedTypes[OpTypeSampler].push_back(type); 212617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 213617a3babSopenharmony_ci module.mapInstruction(type); 214617a3babSopenharmony_ci } else 215617a3babSopenharmony_ci type = groupedTypes[OpTypeSampler].back(); 216617a3babSopenharmony_ci 217617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 218617a3babSopenharmony_ci { 219617a3babSopenharmony_ci auto const debugResultId = makeCompositeDebugType({}, "type.sampler", NonSemanticShaderDebugInfo100Structure, true); 220617a3babSopenharmony_ci debugId[type->getResultId()] = debugResultId; 221617a3babSopenharmony_ci } 222617a3babSopenharmony_ci 223617a3babSopenharmony_ci return type->getResultId(); 224617a3babSopenharmony_ci} 225617a3babSopenharmony_ci 226617a3babSopenharmony_ciId Builder::makePointer(StorageClass storageClass, Id pointee) 227617a3babSopenharmony_ci{ 228617a3babSopenharmony_ci // try to find it 229617a3babSopenharmony_ci Instruction* type; 230617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) { 231617a3babSopenharmony_ci type = groupedTypes[OpTypePointer][t]; 232617a3babSopenharmony_ci if (type->getImmediateOperand(0) == (unsigned)storageClass && 233617a3babSopenharmony_ci type->getIdOperand(1) == pointee) 234617a3babSopenharmony_ci return type->getResultId(); 235617a3babSopenharmony_ci } 236617a3babSopenharmony_ci 237617a3babSopenharmony_ci // not found, make it 238617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypePointer); 239617a3babSopenharmony_ci type->addImmediateOperand(storageClass); 240617a3babSopenharmony_ci type->addIdOperand(pointee); 241617a3babSopenharmony_ci groupedTypes[OpTypePointer].push_back(type); 242617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 243617a3babSopenharmony_ci module.mapInstruction(type); 244617a3babSopenharmony_ci 245617a3babSopenharmony_ci return type->getResultId(); 246617a3babSopenharmony_ci} 247617a3babSopenharmony_ci 248617a3babSopenharmony_ciId Builder::makeForwardPointer(StorageClass storageClass) 249617a3babSopenharmony_ci{ 250617a3babSopenharmony_ci // Caching/uniquifying doesn't work here, because we don't know the 251617a3babSopenharmony_ci // pointee type and there can be multiple forward pointers of the same 252617a3babSopenharmony_ci // storage type. Somebody higher up in the stack must keep track. 253617a3babSopenharmony_ci Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeForwardPointer); 254617a3babSopenharmony_ci type->addImmediateOperand(storageClass); 255617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 256617a3babSopenharmony_ci module.mapInstruction(type); 257617a3babSopenharmony_ci 258617a3babSopenharmony_ci return type->getResultId(); 259617a3babSopenharmony_ci} 260617a3babSopenharmony_ci 261617a3babSopenharmony_ciId Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardPointerType, Id pointee) 262617a3babSopenharmony_ci{ 263617a3babSopenharmony_ci // try to find it 264617a3babSopenharmony_ci Instruction* type; 265617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) { 266617a3babSopenharmony_ci type = groupedTypes[OpTypePointer][t]; 267617a3babSopenharmony_ci if (type->getImmediateOperand(0) == (unsigned)storageClass && 268617a3babSopenharmony_ci type->getIdOperand(1) == pointee) 269617a3babSopenharmony_ci return type->getResultId(); 270617a3babSopenharmony_ci } 271617a3babSopenharmony_ci 272617a3babSopenharmony_ci type = new Instruction(forwardPointerType, NoType, OpTypePointer); 273617a3babSopenharmony_ci type->addImmediateOperand(storageClass); 274617a3babSopenharmony_ci type->addIdOperand(pointee); 275617a3babSopenharmony_ci groupedTypes[OpTypePointer].push_back(type); 276617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 277617a3babSopenharmony_ci module.mapInstruction(type); 278617a3babSopenharmony_ci 279617a3babSopenharmony_ci return type->getResultId(); 280617a3babSopenharmony_ci} 281617a3babSopenharmony_ci 282617a3babSopenharmony_ciId Builder::makeIntegerType(int width, bool hasSign) 283617a3babSopenharmony_ci{ 284617a3babSopenharmony_ci // try to find it 285617a3babSopenharmony_ci Instruction* type; 286617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypeInt].size(); ++t) { 287617a3babSopenharmony_ci type = groupedTypes[OpTypeInt][t]; 288617a3babSopenharmony_ci if (type->getImmediateOperand(0) == (unsigned)width && 289617a3babSopenharmony_ci type->getImmediateOperand(1) == (hasSign ? 1u : 0u)) 290617a3babSopenharmony_ci return type->getResultId(); 291617a3babSopenharmony_ci } 292617a3babSopenharmony_ci 293617a3babSopenharmony_ci // not found, make it 294617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeInt); 295617a3babSopenharmony_ci type->addImmediateOperand(width); 296617a3babSopenharmony_ci type->addImmediateOperand(hasSign ? 1 : 0); 297617a3babSopenharmony_ci groupedTypes[OpTypeInt].push_back(type); 298617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 299617a3babSopenharmony_ci module.mapInstruction(type); 300617a3babSopenharmony_ci 301617a3babSopenharmony_ci // deal with capabilities 302617a3babSopenharmony_ci switch (width) { 303617a3babSopenharmony_ci case 8: 304617a3babSopenharmony_ci case 16: 305617a3babSopenharmony_ci // these are currently handled by storage-type declarations and post processing 306617a3babSopenharmony_ci break; 307617a3babSopenharmony_ci case 64: 308617a3babSopenharmony_ci addCapability(CapabilityInt64); 309617a3babSopenharmony_ci break; 310617a3babSopenharmony_ci default: 311617a3babSopenharmony_ci break; 312617a3babSopenharmony_ci } 313617a3babSopenharmony_ci 314617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 315617a3babSopenharmony_ci { 316617a3babSopenharmony_ci auto const debugResultId = makeIntegerDebugType(width, hasSign); 317617a3babSopenharmony_ci debugId[type->getResultId()] = debugResultId; 318617a3babSopenharmony_ci } 319617a3babSopenharmony_ci 320617a3babSopenharmony_ci return type->getResultId(); 321617a3babSopenharmony_ci} 322617a3babSopenharmony_ci 323617a3babSopenharmony_ciId Builder::makeFloatType(int width) 324617a3babSopenharmony_ci{ 325617a3babSopenharmony_ci // try to find it 326617a3babSopenharmony_ci Instruction* type; 327617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypeFloat].size(); ++t) { 328617a3babSopenharmony_ci type = groupedTypes[OpTypeFloat][t]; 329617a3babSopenharmony_ci if (type->getImmediateOperand(0) == (unsigned)width) 330617a3babSopenharmony_ci return type->getResultId(); 331617a3babSopenharmony_ci } 332617a3babSopenharmony_ci 333617a3babSopenharmony_ci // not found, make it 334617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeFloat); 335617a3babSopenharmony_ci type->addImmediateOperand(width); 336617a3babSopenharmony_ci groupedTypes[OpTypeFloat].push_back(type); 337617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 338617a3babSopenharmony_ci module.mapInstruction(type); 339617a3babSopenharmony_ci 340617a3babSopenharmony_ci // deal with capabilities 341617a3babSopenharmony_ci switch (width) { 342617a3babSopenharmony_ci case 16: 343617a3babSopenharmony_ci // currently handled by storage-type declarations and post processing 344617a3babSopenharmony_ci break; 345617a3babSopenharmony_ci case 64: 346617a3babSopenharmony_ci addCapability(CapabilityFloat64); 347617a3babSopenharmony_ci break; 348617a3babSopenharmony_ci default: 349617a3babSopenharmony_ci break; 350617a3babSopenharmony_ci } 351617a3babSopenharmony_ci 352617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 353617a3babSopenharmony_ci { 354617a3babSopenharmony_ci auto const debugResultId = makeFloatDebugType(width); 355617a3babSopenharmony_ci debugId[type->getResultId()] = debugResultId; 356617a3babSopenharmony_ci } 357617a3babSopenharmony_ci 358617a3babSopenharmony_ci return type->getResultId(); 359617a3babSopenharmony_ci} 360617a3babSopenharmony_ci 361617a3babSopenharmony_ci// Make a struct without checking for duplication. 362617a3babSopenharmony_ci// See makeStructResultType() for non-decorated structs 363617a3babSopenharmony_ci// needed as the result of some instructions, which does 364617a3babSopenharmony_ci// check for duplicates. 365617a3babSopenharmony_ciId Builder::makeStructType(const std::vector<Id>& members, const char* name, bool const compilerGenerated) 366617a3babSopenharmony_ci{ 367617a3babSopenharmony_ci // Don't look for previous one, because in the general case, 368617a3babSopenharmony_ci // structs can be duplicated except for decorations. 369617a3babSopenharmony_ci 370617a3babSopenharmony_ci // not found, make it 371617a3babSopenharmony_ci Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeStruct); 372617a3babSopenharmony_ci for (int op = 0; op < (int)members.size(); ++op) 373617a3babSopenharmony_ci type->addIdOperand(members[op]); 374617a3babSopenharmony_ci groupedTypes[OpTypeStruct].push_back(type); 375617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 376617a3babSopenharmony_ci module.mapInstruction(type); 377617a3babSopenharmony_ci addName(type->getResultId(), name); 378617a3babSopenharmony_ci 379617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo && !compilerGenerated) 380617a3babSopenharmony_ci { 381617a3babSopenharmony_ci auto const debugResultId = makeCompositeDebugType(members, name, NonSemanticShaderDebugInfo100Structure); 382617a3babSopenharmony_ci debugId[type->getResultId()] = debugResultId; 383617a3babSopenharmony_ci } 384617a3babSopenharmony_ci 385617a3babSopenharmony_ci return type->getResultId(); 386617a3babSopenharmony_ci} 387617a3babSopenharmony_ci 388617a3babSopenharmony_ci// Make a struct for the simple results of several instructions, 389617a3babSopenharmony_ci// checking for duplication. 390617a3babSopenharmony_ciId Builder::makeStructResultType(Id type0, Id type1) 391617a3babSopenharmony_ci{ 392617a3babSopenharmony_ci // try to find it 393617a3babSopenharmony_ci Instruction* type; 394617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypeStruct].size(); ++t) { 395617a3babSopenharmony_ci type = groupedTypes[OpTypeStruct][t]; 396617a3babSopenharmony_ci if (type->getNumOperands() != 2) 397617a3babSopenharmony_ci continue; 398617a3babSopenharmony_ci if (type->getIdOperand(0) != type0 || 399617a3babSopenharmony_ci type->getIdOperand(1) != type1) 400617a3babSopenharmony_ci continue; 401617a3babSopenharmony_ci return type->getResultId(); 402617a3babSopenharmony_ci } 403617a3babSopenharmony_ci 404617a3babSopenharmony_ci // not found, make it 405617a3babSopenharmony_ci std::vector<spv::Id> members; 406617a3babSopenharmony_ci members.push_back(type0); 407617a3babSopenharmony_ci members.push_back(type1); 408617a3babSopenharmony_ci 409617a3babSopenharmony_ci return makeStructType(members, "ResType"); 410617a3babSopenharmony_ci} 411617a3babSopenharmony_ci 412617a3babSopenharmony_ciId Builder::makeVectorType(Id component, int size) 413617a3babSopenharmony_ci{ 414617a3babSopenharmony_ci // try to find it 415617a3babSopenharmony_ci Instruction* type; 416617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypeVector].size(); ++t) { 417617a3babSopenharmony_ci type = groupedTypes[OpTypeVector][t]; 418617a3babSopenharmony_ci if (type->getIdOperand(0) == component && 419617a3babSopenharmony_ci type->getImmediateOperand(1) == (unsigned)size) 420617a3babSopenharmony_ci return type->getResultId(); 421617a3babSopenharmony_ci } 422617a3babSopenharmony_ci 423617a3babSopenharmony_ci // not found, make it 424617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeVector); 425617a3babSopenharmony_ci type->addIdOperand(component); 426617a3babSopenharmony_ci type->addImmediateOperand(size); 427617a3babSopenharmony_ci groupedTypes[OpTypeVector].push_back(type); 428617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 429617a3babSopenharmony_ci module.mapInstruction(type); 430617a3babSopenharmony_ci 431617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 432617a3babSopenharmony_ci { 433617a3babSopenharmony_ci auto const debugResultId = makeVectorDebugType(component, size); 434617a3babSopenharmony_ci debugId[type->getResultId()] = debugResultId; 435617a3babSopenharmony_ci } 436617a3babSopenharmony_ci 437617a3babSopenharmony_ci return type->getResultId(); 438617a3babSopenharmony_ci} 439617a3babSopenharmony_ci 440617a3babSopenharmony_ciId Builder::makeMatrixType(Id component, int cols, int rows) 441617a3babSopenharmony_ci{ 442617a3babSopenharmony_ci assert(cols <= maxMatrixSize && rows <= maxMatrixSize); 443617a3babSopenharmony_ci 444617a3babSopenharmony_ci Id column = makeVectorType(component, rows); 445617a3babSopenharmony_ci 446617a3babSopenharmony_ci // try to find it 447617a3babSopenharmony_ci Instruction* type; 448617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypeMatrix].size(); ++t) { 449617a3babSopenharmony_ci type = groupedTypes[OpTypeMatrix][t]; 450617a3babSopenharmony_ci if (type->getIdOperand(0) == column && 451617a3babSopenharmony_ci type->getImmediateOperand(1) == (unsigned)cols) 452617a3babSopenharmony_ci return type->getResultId(); 453617a3babSopenharmony_ci } 454617a3babSopenharmony_ci 455617a3babSopenharmony_ci // not found, make it 456617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeMatrix); 457617a3babSopenharmony_ci type->addIdOperand(column); 458617a3babSopenharmony_ci type->addImmediateOperand(cols); 459617a3babSopenharmony_ci groupedTypes[OpTypeMatrix].push_back(type); 460617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 461617a3babSopenharmony_ci module.mapInstruction(type); 462617a3babSopenharmony_ci 463617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 464617a3babSopenharmony_ci { 465617a3babSopenharmony_ci auto const debugResultId = makeMatrixDebugType(column, cols); 466617a3babSopenharmony_ci debugId[type->getResultId()] = debugResultId; 467617a3babSopenharmony_ci } 468617a3babSopenharmony_ci 469617a3babSopenharmony_ci return type->getResultId(); 470617a3babSopenharmony_ci} 471617a3babSopenharmony_ci 472617a3babSopenharmony_ciId Builder::makeCooperativeMatrixTypeKHR(Id component, Id scope, Id rows, Id cols, Id use) 473617a3babSopenharmony_ci{ 474617a3babSopenharmony_ci // try to find it 475617a3babSopenharmony_ci Instruction* type; 476617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypeCooperativeMatrixKHR].size(); ++t) { 477617a3babSopenharmony_ci type = groupedTypes[OpTypeCooperativeMatrixKHR][t]; 478617a3babSopenharmony_ci if (type->getIdOperand(0) == component && 479617a3babSopenharmony_ci type->getIdOperand(1) == scope && 480617a3babSopenharmony_ci type->getIdOperand(2) == rows && 481617a3babSopenharmony_ci type->getIdOperand(3) == cols && 482617a3babSopenharmony_ci type->getIdOperand(4) == use) 483617a3babSopenharmony_ci return type->getResultId(); 484617a3babSopenharmony_ci } 485617a3babSopenharmony_ci 486617a3babSopenharmony_ci // not found, make it 487617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeCooperativeMatrixKHR); 488617a3babSopenharmony_ci type->addIdOperand(component); 489617a3babSopenharmony_ci type->addIdOperand(scope); 490617a3babSopenharmony_ci type->addIdOperand(rows); 491617a3babSopenharmony_ci type->addIdOperand(cols); 492617a3babSopenharmony_ci type->addIdOperand(use); 493617a3babSopenharmony_ci groupedTypes[OpTypeCooperativeMatrixKHR].push_back(type); 494617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 495617a3babSopenharmony_ci module.mapInstruction(type); 496617a3babSopenharmony_ci 497617a3babSopenharmony_ci return type->getResultId(); 498617a3babSopenharmony_ci} 499617a3babSopenharmony_ci 500617a3babSopenharmony_ciId Builder::makeCooperativeMatrixTypeNV(Id component, Id scope, Id rows, Id cols) 501617a3babSopenharmony_ci{ 502617a3babSopenharmony_ci // try to find it 503617a3babSopenharmony_ci Instruction* type; 504617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypeCooperativeMatrixNV].size(); ++t) { 505617a3babSopenharmony_ci type = groupedTypes[OpTypeCooperativeMatrixNV][t]; 506617a3babSopenharmony_ci if (type->getIdOperand(0) == component && type->getIdOperand(1) == scope && type->getIdOperand(2) == rows && 507617a3babSopenharmony_ci type->getIdOperand(3) == cols) 508617a3babSopenharmony_ci return type->getResultId(); 509617a3babSopenharmony_ci } 510617a3babSopenharmony_ci 511617a3babSopenharmony_ci // not found, make it 512617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeCooperativeMatrixNV); 513617a3babSopenharmony_ci type->addIdOperand(component); 514617a3babSopenharmony_ci type->addIdOperand(scope); 515617a3babSopenharmony_ci type->addIdOperand(rows); 516617a3babSopenharmony_ci type->addIdOperand(cols); 517617a3babSopenharmony_ci groupedTypes[OpTypeCooperativeMatrixNV].push_back(type); 518617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 519617a3babSopenharmony_ci module.mapInstruction(type); 520617a3babSopenharmony_ci 521617a3babSopenharmony_ci return type->getResultId(); 522617a3babSopenharmony_ci} 523617a3babSopenharmony_ci 524617a3babSopenharmony_ciId Builder::makeCooperativeMatrixTypeWithSameShape(Id component, Id otherType) 525617a3babSopenharmony_ci{ 526617a3babSopenharmony_ci Instruction* instr = module.getInstruction(otherType); 527617a3babSopenharmony_ci if (instr->getOpCode() == OpTypeCooperativeMatrixNV) { 528617a3babSopenharmony_ci return makeCooperativeMatrixTypeNV(component, instr->getIdOperand(1), instr->getIdOperand(2), instr->getIdOperand(3)); 529617a3babSopenharmony_ci } else { 530617a3babSopenharmony_ci assert(instr->getOpCode() == OpTypeCooperativeMatrixKHR); 531617a3babSopenharmony_ci return makeCooperativeMatrixTypeKHR(component, instr->getIdOperand(1), instr->getIdOperand(2), instr->getIdOperand(3), instr->getIdOperand(4)); 532617a3babSopenharmony_ci } 533617a3babSopenharmony_ci} 534617a3babSopenharmony_ci 535617a3babSopenharmony_ciId Builder::makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands) 536617a3babSopenharmony_ci{ 537617a3babSopenharmony_ci // try to find it 538617a3babSopenharmony_ci Instruction* type; 539617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[opcode].size(); ++t) { 540617a3babSopenharmony_ci type = groupedTypes[opcode][t]; 541617a3babSopenharmony_ci if (static_cast<size_t>(type->getNumOperands()) != operands.size()) 542617a3babSopenharmony_ci continue; // Number mismatch, find next 543617a3babSopenharmony_ci 544617a3babSopenharmony_ci bool match = true; 545617a3babSopenharmony_ci for (int op = 0; match && op < (int)operands.size(); ++op) { 546617a3babSopenharmony_ci match = (operands[op].isId ? type->getIdOperand(op) : type->getImmediateOperand(op)) == operands[op].word; 547617a3babSopenharmony_ci } 548617a3babSopenharmony_ci if (match) 549617a3babSopenharmony_ci return type->getResultId(); 550617a3babSopenharmony_ci } 551617a3babSopenharmony_ci 552617a3babSopenharmony_ci // not found, make it 553617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, opcode); 554617a3babSopenharmony_ci for (size_t op = 0; op < operands.size(); ++op) { 555617a3babSopenharmony_ci if (operands[op].isId) 556617a3babSopenharmony_ci type->addIdOperand(operands[op].word); 557617a3babSopenharmony_ci else 558617a3babSopenharmony_ci type->addImmediateOperand(operands[op].word); 559617a3babSopenharmony_ci } 560617a3babSopenharmony_ci groupedTypes[opcode].push_back(type); 561617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 562617a3babSopenharmony_ci module.mapInstruction(type); 563617a3babSopenharmony_ci 564617a3babSopenharmony_ci return type->getResultId(); 565617a3babSopenharmony_ci} 566617a3babSopenharmony_ci 567617a3babSopenharmony_ci// TODO: performance: track arrays per stride 568617a3babSopenharmony_ci// If a stride is supplied (non-zero) make an array. 569617a3babSopenharmony_ci// If no stride (0), reuse previous array types. 570617a3babSopenharmony_ci// 'size' is an Id of a constant or specialization constant of the array size 571617a3babSopenharmony_ciId Builder::makeArrayType(Id element, Id sizeId, int stride) 572617a3babSopenharmony_ci{ 573617a3babSopenharmony_ci Instruction* type; 574617a3babSopenharmony_ci if (stride == 0) { 575617a3babSopenharmony_ci // try to find existing type 576617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) { 577617a3babSopenharmony_ci type = groupedTypes[OpTypeArray][t]; 578617a3babSopenharmony_ci if (type->getIdOperand(0) == element && 579617a3babSopenharmony_ci type->getIdOperand(1) == sizeId) 580617a3babSopenharmony_ci return type->getResultId(); 581617a3babSopenharmony_ci } 582617a3babSopenharmony_ci } 583617a3babSopenharmony_ci 584617a3babSopenharmony_ci // not found, make it 585617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeArray); 586617a3babSopenharmony_ci type->addIdOperand(element); 587617a3babSopenharmony_ci type->addIdOperand(sizeId); 588617a3babSopenharmony_ci groupedTypes[OpTypeArray].push_back(type); 589617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 590617a3babSopenharmony_ci module.mapInstruction(type); 591617a3babSopenharmony_ci 592617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 593617a3babSopenharmony_ci { 594617a3babSopenharmony_ci auto const debugResultId = makeArrayDebugType(element, sizeId); 595617a3babSopenharmony_ci debugId[type->getResultId()] = debugResultId; 596617a3babSopenharmony_ci } 597617a3babSopenharmony_ci 598617a3babSopenharmony_ci return type->getResultId(); 599617a3babSopenharmony_ci} 600617a3babSopenharmony_ci 601617a3babSopenharmony_ciId Builder::makeRuntimeArray(Id element) 602617a3babSopenharmony_ci{ 603617a3babSopenharmony_ci Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray); 604617a3babSopenharmony_ci type->addIdOperand(element); 605617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 606617a3babSopenharmony_ci module.mapInstruction(type); 607617a3babSopenharmony_ci 608617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 609617a3babSopenharmony_ci { 610617a3babSopenharmony_ci auto const debugResultId = makeArrayDebugType(element, makeUintConstant(0)); 611617a3babSopenharmony_ci debugId[type->getResultId()] = debugResultId; 612617a3babSopenharmony_ci } 613617a3babSopenharmony_ci 614617a3babSopenharmony_ci return type->getResultId(); 615617a3babSopenharmony_ci} 616617a3babSopenharmony_ci 617617a3babSopenharmony_ciId Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes) 618617a3babSopenharmony_ci{ 619617a3babSopenharmony_ci // try to find it 620617a3babSopenharmony_ci Instruction* type; 621617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypeFunction].size(); ++t) { 622617a3babSopenharmony_ci type = groupedTypes[OpTypeFunction][t]; 623617a3babSopenharmony_ci if (type->getIdOperand(0) != returnType || (int)paramTypes.size() != type->getNumOperands() - 1) 624617a3babSopenharmony_ci continue; 625617a3babSopenharmony_ci bool mismatch = false; 626617a3babSopenharmony_ci for (int p = 0; p < (int)paramTypes.size(); ++p) { 627617a3babSopenharmony_ci if (paramTypes[p] != type->getIdOperand(p + 1)) { 628617a3babSopenharmony_ci mismatch = true; 629617a3babSopenharmony_ci break; 630617a3babSopenharmony_ci } 631617a3babSopenharmony_ci } 632617a3babSopenharmony_ci if (! mismatch) 633617a3babSopenharmony_ci { 634617a3babSopenharmony_ci // If compiling HLSL, glslang will create a wrapper function around the entrypoint. Accordingly, a void(void) 635617a3babSopenharmony_ci // function type is created for the wrapper function. However, nonsemantic shader debug information is disabled 636617a3babSopenharmony_ci // while creating the HLSL wrapper. Consequently, if we encounter another void(void) function, we need to create 637617a3babSopenharmony_ci // the associated debug function type if it hasn't been created yet. 638617a3babSopenharmony_ci if(emitNonSemanticShaderDebugInfo && debugId[type->getResultId()] == 0) { 639617a3babSopenharmony_ci assert(sourceLang == spv::SourceLanguageHLSL); 640617a3babSopenharmony_ci assert(getTypeClass(returnType) == OpTypeVoid && paramTypes.size() == 0); 641617a3babSopenharmony_ci 642617a3babSopenharmony_ci Id debugTypeId = makeDebugFunctionType(returnType, {}); 643617a3babSopenharmony_ci debugId[type->getResultId()] = debugTypeId; 644617a3babSopenharmony_ci } 645617a3babSopenharmony_ci return type->getResultId(); 646617a3babSopenharmony_ci } 647617a3babSopenharmony_ci } 648617a3babSopenharmony_ci 649617a3babSopenharmony_ci // not found, make it 650617a3babSopenharmony_ci Id typeId = getUniqueId(); 651617a3babSopenharmony_ci type = new Instruction(typeId, NoType, OpTypeFunction); 652617a3babSopenharmony_ci type->addIdOperand(returnType); 653617a3babSopenharmony_ci for (int p = 0; p < (int)paramTypes.size(); ++p) 654617a3babSopenharmony_ci type->addIdOperand(paramTypes[p]); 655617a3babSopenharmony_ci groupedTypes[OpTypeFunction].push_back(type); 656617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 657617a3babSopenharmony_ci module.mapInstruction(type); 658617a3babSopenharmony_ci 659617a3babSopenharmony_ci // make debug type and map it 660617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) { 661617a3babSopenharmony_ci Id debugTypeId = makeDebugFunctionType(returnType, paramTypes); 662617a3babSopenharmony_ci debugId[typeId] = debugTypeId; 663617a3babSopenharmony_ci } 664617a3babSopenharmony_ci 665617a3babSopenharmony_ci return type->getResultId(); 666617a3babSopenharmony_ci} 667617a3babSopenharmony_ci 668617a3babSopenharmony_ciId Builder::makeDebugFunctionType(Id returnType, const std::vector<Id>& paramTypes) 669617a3babSopenharmony_ci{ 670617a3babSopenharmony_ci assert(debugId[returnType] != 0); 671617a3babSopenharmony_ci 672617a3babSopenharmony_ci Id typeId = getUniqueId(); 673617a3babSopenharmony_ci auto type = new Instruction(typeId, makeVoidType(), OpExtInst); 674617a3babSopenharmony_ci type->addIdOperand(nonSemanticShaderDebugInfo); 675617a3babSopenharmony_ci type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeFunction); 676617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); 677617a3babSopenharmony_ci type->addIdOperand(debugId[returnType]); 678617a3babSopenharmony_ci for (auto const paramType : paramTypes) { 679617a3babSopenharmony_ci if (isPointerType(paramType) || isArrayType(paramType)) { 680617a3babSopenharmony_ci type->addIdOperand(debugId[getContainedTypeId(paramType)]); 681617a3babSopenharmony_ci } 682617a3babSopenharmony_ci else { 683617a3babSopenharmony_ci type->addIdOperand(debugId[paramType]); 684617a3babSopenharmony_ci } 685617a3babSopenharmony_ci } 686617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 687617a3babSopenharmony_ci module.mapInstruction(type); 688617a3babSopenharmony_ci return typeId; 689617a3babSopenharmony_ci} 690617a3babSopenharmony_ci 691617a3babSopenharmony_ciId Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, 692617a3babSopenharmony_ci ImageFormat format) 693617a3babSopenharmony_ci{ 694617a3babSopenharmony_ci assert(sampled == 1 || sampled == 2); 695617a3babSopenharmony_ci 696617a3babSopenharmony_ci // try to find it 697617a3babSopenharmony_ci Instruction* type; 698617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypeImage].size(); ++t) { 699617a3babSopenharmony_ci type = groupedTypes[OpTypeImage][t]; 700617a3babSopenharmony_ci if (type->getIdOperand(0) == sampledType && 701617a3babSopenharmony_ci type->getImmediateOperand(1) == (unsigned int)dim && 702617a3babSopenharmony_ci type->getImmediateOperand(2) == ( depth ? 1u : 0u) && 703617a3babSopenharmony_ci type->getImmediateOperand(3) == (arrayed ? 1u : 0u) && 704617a3babSopenharmony_ci type->getImmediateOperand(4) == ( ms ? 1u : 0u) && 705617a3babSopenharmony_ci type->getImmediateOperand(5) == sampled && 706617a3babSopenharmony_ci type->getImmediateOperand(6) == (unsigned int)format) 707617a3babSopenharmony_ci return type->getResultId(); 708617a3babSopenharmony_ci } 709617a3babSopenharmony_ci 710617a3babSopenharmony_ci // not found, make it 711617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeImage); 712617a3babSopenharmony_ci type->addIdOperand(sampledType); 713617a3babSopenharmony_ci type->addImmediateOperand( dim); 714617a3babSopenharmony_ci type->addImmediateOperand( depth ? 1 : 0); 715617a3babSopenharmony_ci type->addImmediateOperand(arrayed ? 1 : 0); 716617a3babSopenharmony_ci type->addImmediateOperand( ms ? 1 : 0); 717617a3babSopenharmony_ci type->addImmediateOperand(sampled); 718617a3babSopenharmony_ci type->addImmediateOperand((unsigned int)format); 719617a3babSopenharmony_ci 720617a3babSopenharmony_ci groupedTypes[OpTypeImage].push_back(type); 721617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 722617a3babSopenharmony_ci module.mapInstruction(type); 723617a3babSopenharmony_ci 724617a3babSopenharmony_ci // deal with capabilities 725617a3babSopenharmony_ci switch (dim) { 726617a3babSopenharmony_ci case DimBuffer: 727617a3babSopenharmony_ci if (sampled == 1) 728617a3babSopenharmony_ci addCapability(CapabilitySampledBuffer); 729617a3babSopenharmony_ci else 730617a3babSopenharmony_ci addCapability(CapabilityImageBuffer); 731617a3babSopenharmony_ci break; 732617a3babSopenharmony_ci case Dim1D: 733617a3babSopenharmony_ci if (sampled == 1) 734617a3babSopenharmony_ci addCapability(CapabilitySampled1D); 735617a3babSopenharmony_ci else 736617a3babSopenharmony_ci addCapability(CapabilityImage1D); 737617a3babSopenharmony_ci break; 738617a3babSopenharmony_ci case DimCube: 739617a3babSopenharmony_ci if (arrayed) { 740617a3babSopenharmony_ci if (sampled == 1) 741617a3babSopenharmony_ci addCapability(CapabilitySampledCubeArray); 742617a3babSopenharmony_ci else 743617a3babSopenharmony_ci addCapability(CapabilityImageCubeArray); 744617a3babSopenharmony_ci } 745617a3babSopenharmony_ci break; 746617a3babSopenharmony_ci case DimRect: 747617a3babSopenharmony_ci if (sampled == 1) 748617a3babSopenharmony_ci addCapability(CapabilitySampledRect); 749617a3babSopenharmony_ci else 750617a3babSopenharmony_ci addCapability(CapabilityImageRect); 751617a3babSopenharmony_ci break; 752617a3babSopenharmony_ci case DimSubpassData: 753617a3babSopenharmony_ci addCapability(CapabilityInputAttachment); 754617a3babSopenharmony_ci break; 755617a3babSopenharmony_ci default: 756617a3babSopenharmony_ci break; 757617a3babSopenharmony_ci } 758617a3babSopenharmony_ci 759617a3babSopenharmony_ci if (ms) { 760617a3babSopenharmony_ci if (sampled == 2) { 761617a3babSopenharmony_ci // Images used with subpass data are not storage 762617a3babSopenharmony_ci // images, so don't require the capability for them. 763617a3babSopenharmony_ci if (dim != Dim::DimSubpassData) 764617a3babSopenharmony_ci addCapability(CapabilityStorageImageMultisample); 765617a3babSopenharmony_ci if (arrayed) 766617a3babSopenharmony_ci addCapability(CapabilityImageMSArray); 767617a3babSopenharmony_ci } 768617a3babSopenharmony_ci } 769617a3babSopenharmony_ci 770617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 771617a3babSopenharmony_ci { 772617a3babSopenharmony_ci auto TypeName = [&dim]() -> char const* { 773617a3babSopenharmony_ci switch (dim) { 774617a3babSopenharmony_ci case Dim1D: return "type.1d.image"; 775617a3babSopenharmony_ci case Dim2D: return "type.2d.image"; 776617a3babSopenharmony_ci case Dim3D: return "type.3d.image"; 777617a3babSopenharmony_ci case DimCube: return "type.cube.image"; 778617a3babSopenharmony_ci default: return "type.image"; 779617a3babSopenharmony_ci } 780617a3babSopenharmony_ci }; 781617a3babSopenharmony_ci 782617a3babSopenharmony_ci auto const debugResultId = makeCompositeDebugType({}, TypeName(), NonSemanticShaderDebugInfo100Class, true); 783617a3babSopenharmony_ci debugId[type->getResultId()] = debugResultId; 784617a3babSopenharmony_ci } 785617a3babSopenharmony_ci 786617a3babSopenharmony_ci return type->getResultId(); 787617a3babSopenharmony_ci} 788617a3babSopenharmony_ci 789617a3babSopenharmony_ciId Builder::makeSampledImageType(Id imageType) 790617a3babSopenharmony_ci{ 791617a3babSopenharmony_ci // try to find it 792617a3babSopenharmony_ci Instruction* type; 793617a3babSopenharmony_ci for (int t = 0; t < (int)groupedTypes[OpTypeSampledImage].size(); ++t) { 794617a3babSopenharmony_ci type = groupedTypes[OpTypeSampledImage][t]; 795617a3babSopenharmony_ci if (type->getIdOperand(0) == imageType) 796617a3babSopenharmony_ci return type->getResultId(); 797617a3babSopenharmony_ci } 798617a3babSopenharmony_ci 799617a3babSopenharmony_ci // not found, make it 800617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeSampledImage); 801617a3babSopenharmony_ci type->addIdOperand(imageType); 802617a3babSopenharmony_ci 803617a3babSopenharmony_ci groupedTypes[OpTypeSampledImage].push_back(type); 804617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 805617a3babSopenharmony_ci module.mapInstruction(type); 806617a3babSopenharmony_ci 807617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 808617a3babSopenharmony_ci { 809617a3babSopenharmony_ci auto const debugResultId = makeCompositeDebugType({}, "type.sampled.image", NonSemanticShaderDebugInfo100Class, true); 810617a3babSopenharmony_ci debugId[type->getResultId()] = debugResultId; 811617a3babSopenharmony_ci } 812617a3babSopenharmony_ci 813617a3babSopenharmony_ci return type->getResultId(); 814617a3babSopenharmony_ci} 815617a3babSopenharmony_ci 816617a3babSopenharmony_ciId Builder::makeDebugInfoNone() 817617a3babSopenharmony_ci{ 818617a3babSopenharmony_ci if (debugInfoNone != 0) 819617a3babSopenharmony_ci return debugInfoNone; 820617a3babSopenharmony_ci 821617a3babSopenharmony_ci Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 822617a3babSopenharmony_ci inst->addIdOperand(nonSemanticShaderDebugInfo); 823617a3babSopenharmony_ci inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugInfoNone); 824617a3babSopenharmony_ci 825617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst)); 826617a3babSopenharmony_ci module.mapInstruction(inst); 827617a3babSopenharmony_ci 828617a3babSopenharmony_ci debugInfoNone = inst->getResultId(); 829617a3babSopenharmony_ci 830617a3babSopenharmony_ci return debugInfoNone; 831617a3babSopenharmony_ci} 832617a3babSopenharmony_ci 833617a3babSopenharmony_ciId Builder::makeBoolDebugType(int const size) 834617a3babSopenharmony_ci{ 835617a3babSopenharmony_ci // try to find it 836617a3babSopenharmony_ci Instruction* type; 837617a3babSopenharmony_ci for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) { 838617a3babSopenharmony_ci type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t]; 839617a3babSopenharmony_ci if (type->getIdOperand(0) == getStringId("bool") && 840617a3babSopenharmony_ci type->getIdOperand(1) == static_cast<unsigned int>(size) && 841617a3babSopenharmony_ci type->getIdOperand(2) == NonSemanticShaderDebugInfo100Boolean) 842617a3babSopenharmony_ci return type->getResultId(); 843617a3babSopenharmony_ci } 844617a3babSopenharmony_ci 845617a3babSopenharmony_ci type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 846617a3babSopenharmony_ci type->addIdOperand(nonSemanticShaderDebugInfo); 847617a3babSopenharmony_ci type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic); 848617a3babSopenharmony_ci 849617a3babSopenharmony_ci type->addIdOperand(getStringId("bool")); // name id 850617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(size)); // size id 851617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Boolean)); // encoding id 852617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id 853617a3babSopenharmony_ci 854617a3babSopenharmony_ci groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type); 855617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 856617a3babSopenharmony_ci module.mapInstruction(type); 857617a3babSopenharmony_ci 858617a3babSopenharmony_ci return type->getResultId(); 859617a3babSopenharmony_ci} 860617a3babSopenharmony_ci 861617a3babSopenharmony_ciId Builder::makeIntegerDebugType(int const width, bool const hasSign) 862617a3babSopenharmony_ci{ 863617a3babSopenharmony_ci const char* typeName = nullptr; 864617a3babSopenharmony_ci switch (width) { 865617a3babSopenharmony_ci case 8: typeName = hasSign ? "int8_t" : "uint8_t"; break; 866617a3babSopenharmony_ci case 16: typeName = hasSign ? "int16_t" : "uint16_t"; break; 867617a3babSopenharmony_ci case 64: typeName = hasSign ? "int64_t" : "uint64_t"; break; 868617a3babSopenharmony_ci default: typeName = hasSign ? "int" : "uint"; 869617a3babSopenharmony_ci } 870617a3babSopenharmony_ci auto nameId = getStringId(typeName); 871617a3babSopenharmony_ci // try to find it 872617a3babSopenharmony_ci Instruction* type; 873617a3babSopenharmony_ci for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) { 874617a3babSopenharmony_ci type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t]; 875617a3babSopenharmony_ci if (type->getIdOperand(0) == nameId && 876617a3babSopenharmony_ci type->getIdOperand(1) == static_cast<unsigned int>(width) && 877617a3babSopenharmony_ci type->getIdOperand(2) == (hasSign ? NonSemanticShaderDebugInfo100Signed : NonSemanticShaderDebugInfo100Unsigned)) 878617a3babSopenharmony_ci return type->getResultId(); 879617a3babSopenharmony_ci } 880617a3babSopenharmony_ci 881617a3babSopenharmony_ci // not found, make it 882617a3babSopenharmony_ci type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 883617a3babSopenharmony_ci type->addIdOperand(nonSemanticShaderDebugInfo); 884617a3babSopenharmony_ci type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic); 885617a3babSopenharmony_ci type->addIdOperand(nameId); // name id 886617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(width)); // size id 887617a3babSopenharmony_ci if(hasSign == true) { 888617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Signed)); // encoding id 889617a3babSopenharmony_ci } else { 890617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Unsigned)); // encoding id 891617a3babSopenharmony_ci } 892617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id 893617a3babSopenharmony_ci 894617a3babSopenharmony_ci groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type); 895617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 896617a3babSopenharmony_ci module.mapInstruction(type); 897617a3babSopenharmony_ci 898617a3babSopenharmony_ci return type->getResultId(); 899617a3babSopenharmony_ci} 900617a3babSopenharmony_ci 901617a3babSopenharmony_ciId Builder::makeFloatDebugType(int const width) 902617a3babSopenharmony_ci{ 903617a3babSopenharmony_ci const char* typeName = nullptr; 904617a3babSopenharmony_ci switch (width) { 905617a3babSopenharmony_ci case 16: typeName = "float16_t"; break; 906617a3babSopenharmony_ci case 64: typeName = "double"; break; 907617a3babSopenharmony_ci default: typeName = "float"; break; 908617a3babSopenharmony_ci } 909617a3babSopenharmony_ci auto nameId = getStringId(typeName); 910617a3babSopenharmony_ci // try to find it 911617a3babSopenharmony_ci Instruction* type; 912617a3babSopenharmony_ci for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) { 913617a3babSopenharmony_ci type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t]; 914617a3babSopenharmony_ci if (type->getIdOperand(0) == nameId && 915617a3babSopenharmony_ci type->getIdOperand(1) == static_cast<unsigned int>(width) && 916617a3babSopenharmony_ci type->getIdOperand(2) == NonSemanticShaderDebugInfo100Float) 917617a3babSopenharmony_ci return type->getResultId(); 918617a3babSopenharmony_ci } 919617a3babSopenharmony_ci 920617a3babSopenharmony_ci // not found, make it 921617a3babSopenharmony_ci type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 922617a3babSopenharmony_ci type->addIdOperand(nonSemanticShaderDebugInfo); 923617a3babSopenharmony_ci type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic); 924617a3babSopenharmony_ci type->addIdOperand(nameId); // name id 925617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(width)); // size id 926617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Float)); // encoding id 927617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id 928617a3babSopenharmony_ci 929617a3babSopenharmony_ci groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type); 930617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 931617a3babSopenharmony_ci module.mapInstruction(type); 932617a3babSopenharmony_ci 933617a3babSopenharmony_ci return type->getResultId(); 934617a3babSopenharmony_ci} 935617a3babSopenharmony_ci 936617a3babSopenharmony_ciId Builder::makeSequentialDebugType(Id const baseType, Id const componentCount, NonSemanticShaderDebugInfo100Instructions const sequenceType) 937617a3babSopenharmony_ci{ 938617a3babSopenharmony_ci assert(sequenceType == NonSemanticShaderDebugInfo100DebugTypeArray || 939617a3babSopenharmony_ci sequenceType == NonSemanticShaderDebugInfo100DebugTypeVector); 940617a3babSopenharmony_ci 941617a3babSopenharmony_ci // try to find it 942617a3babSopenharmony_ci Instruction* type; 943617a3babSopenharmony_ci for (int t = 0; t < (int)groupedDebugTypes[sequenceType].size(); ++t) { 944617a3babSopenharmony_ci type = groupedDebugTypes[sequenceType][t]; 945617a3babSopenharmony_ci if (type->getIdOperand(0) == baseType && 946617a3babSopenharmony_ci type->getIdOperand(1) == makeUintConstant(componentCount)) 947617a3babSopenharmony_ci return type->getResultId(); 948617a3babSopenharmony_ci } 949617a3babSopenharmony_ci 950617a3babSopenharmony_ci // not found, make it 951617a3babSopenharmony_ci type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 952617a3babSopenharmony_ci type->addIdOperand(nonSemanticShaderDebugInfo); 953617a3babSopenharmony_ci type->addImmediateOperand(sequenceType); 954617a3babSopenharmony_ci type->addIdOperand(debugId[baseType]); // base type 955617a3babSopenharmony_ci type->addIdOperand(componentCount); // component count 956617a3babSopenharmony_ci 957617a3babSopenharmony_ci groupedDebugTypes[sequenceType].push_back(type); 958617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 959617a3babSopenharmony_ci module.mapInstruction(type); 960617a3babSopenharmony_ci 961617a3babSopenharmony_ci return type->getResultId(); 962617a3babSopenharmony_ci} 963617a3babSopenharmony_ci 964617a3babSopenharmony_ciId Builder::makeArrayDebugType(Id const baseType, Id const componentCount) 965617a3babSopenharmony_ci{ 966617a3babSopenharmony_ci return makeSequentialDebugType(baseType, componentCount, NonSemanticShaderDebugInfo100DebugTypeArray); 967617a3babSopenharmony_ci} 968617a3babSopenharmony_ci 969617a3babSopenharmony_ciId Builder::makeVectorDebugType(Id const baseType, int const componentCount) 970617a3babSopenharmony_ci{ 971617a3babSopenharmony_ci return makeSequentialDebugType(baseType, makeUintConstant(componentCount), NonSemanticShaderDebugInfo100DebugTypeVector); 972617a3babSopenharmony_ci} 973617a3babSopenharmony_ci 974617a3babSopenharmony_ciId Builder::makeMatrixDebugType(Id const vectorType, int const vectorCount, bool columnMajor) 975617a3babSopenharmony_ci{ 976617a3babSopenharmony_ci // try to find it 977617a3babSopenharmony_ci Instruction* type; 978617a3babSopenharmony_ci for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix].size(); ++t) { 979617a3babSopenharmony_ci type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix][t]; 980617a3babSopenharmony_ci if (type->getIdOperand(0) == vectorType && 981617a3babSopenharmony_ci type->getIdOperand(1) == makeUintConstant(vectorCount)) 982617a3babSopenharmony_ci return type->getResultId(); 983617a3babSopenharmony_ci } 984617a3babSopenharmony_ci 985617a3babSopenharmony_ci // not found, make it 986617a3babSopenharmony_ci type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 987617a3babSopenharmony_ci type->addIdOperand(nonSemanticShaderDebugInfo); 988617a3babSopenharmony_ci type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMatrix); 989617a3babSopenharmony_ci type->addIdOperand(debugId[vectorType]); // vector type id 990617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(vectorCount)); // component count id 991617a3babSopenharmony_ci type->addIdOperand(makeBoolConstant(columnMajor)); // column-major id 992617a3babSopenharmony_ci 993617a3babSopenharmony_ci groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix].push_back(type); 994617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 995617a3babSopenharmony_ci module.mapInstruction(type); 996617a3babSopenharmony_ci 997617a3babSopenharmony_ci return type->getResultId(); 998617a3babSopenharmony_ci} 999617a3babSopenharmony_ci 1000617a3babSopenharmony_ciId Builder::makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTypeLoc) 1001617a3babSopenharmony_ci{ 1002617a3babSopenharmony_ci assert(debugId[memberType] != 0); 1003617a3babSopenharmony_ci 1004617a3babSopenharmony_ci Instruction* type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 1005617a3babSopenharmony_ci type->addIdOperand(nonSemanticShaderDebugInfo); 1006617a3babSopenharmony_ci type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMember); 1007617a3babSopenharmony_ci type->addIdOperand(getStringId(debugTypeLoc.name)); // name id 1008617a3babSopenharmony_ci type->addIdOperand(debugId[memberType]); // type id 1009617a3babSopenharmony_ci type->addIdOperand(makeDebugSource(sourceFileStringId)); // source id TODO: verify this works across include directives 1010617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(debugTypeLoc.line)); // line id TODO: currentLine is always zero 1011617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(debugTypeLoc.column)); // TODO: column id 1012617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(0)); // TODO: offset id 1013617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(0)); // TODO: size id 1014617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); // flags id 1015617a3babSopenharmony_ci 1016617a3babSopenharmony_ci groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMember].push_back(type); 1017617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 1018617a3babSopenharmony_ci module.mapInstruction(type); 1019617a3babSopenharmony_ci 1020617a3babSopenharmony_ci return type->getResultId(); 1021617a3babSopenharmony_ci} 1022617a3babSopenharmony_ci 1023617a3babSopenharmony_ci// Note: To represent a source language opaque type, this instruction must have no Members operands, Size operand must be 1024617a3babSopenharmony_ci// DebugInfoNone, and Name must start with @ to avoid clashes with user defined names. 1025617a3babSopenharmony_ciId Builder::makeCompositeDebugType(std::vector<Id> const& memberTypes, char const*const name, 1026617a3babSopenharmony_ci NonSemanticShaderDebugInfo100DebugCompositeType const tag, bool const isOpaqueType) 1027617a3babSopenharmony_ci{ 1028617a3babSopenharmony_ci // Create the debug member types. 1029617a3babSopenharmony_ci std::vector<Id> memberDebugTypes; 1030617a3babSopenharmony_ci for(auto const memberType : memberTypes) { 1031617a3babSopenharmony_ci assert(debugTypeLocs.find(memberType) != debugTypeLocs.end()); 1032617a3babSopenharmony_ci 1033617a3babSopenharmony_ci // There _should_ be debug types for all the member types but currently buffer references 1034617a3babSopenharmony_ci // do not have member debug info generated. 1035617a3babSopenharmony_ci if (debugId[memberType]) 1036617a3babSopenharmony_ci memberDebugTypes.emplace_back(makeMemberDebugType(memberType, debugTypeLocs[memberType])); 1037617a3babSopenharmony_ci 1038617a3babSopenharmony_ci // TODO: Need to rethink this method of passing location information. 1039617a3babSopenharmony_ci // debugTypeLocs.erase(memberType); 1040617a3babSopenharmony_ci } 1041617a3babSopenharmony_ci 1042617a3babSopenharmony_ci // Create The structure debug type. 1043617a3babSopenharmony_ci Instruction* type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 1044617a3babSopenharmony_ci type->addIdOperand(nonSemanticShaderDebugInfo); 1045617a3babSopenharmony_ci type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeComposite); 1046617a3babSopenharmony_ci type->addIdOperand(getStringId(name)); // name id 1047617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(tag)); // tag id 1048617a3babSopenharmony_ci type->addIdOperand(makeDebugSource(sourceFileStringId)); // source id TODO: verify this works across include directives 1049617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero? 1050617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(0)); // TODO: column id 1051617a3babSopenharmony_ci type->addIdOperand(makeDebugCompilationUnit()); // scope id 1052617a3babSopenharmony_ci if(isOpaqueType == true) { 1053617a3babSopenharmony_ci // Prepend '@' to opaque types. 1054617a3babSopenharmony_ci type->addIdOperand(getStringId('@' + std::string(name))); // linkage name id 1055617a3babSopenharmony_ci type->addIdOperand(makeDebugInfoNone()); // size id 1056617a3babSopenharmony_ci } else { 1057617a3babSopenharmony_ci type->addIdOperand(getStringId(name)); // linkage name id 1058617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(0)); // TODO: size id 1059617a3babSopenharmony_ci } 1060617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); // flags id 1061617a3babSopenharmony_ci assert(isOpaqueType == false || (isOpaqueType == true && memberDebugTypes.empty())); 1062617a3babSopenharmony_ci for(auto const memberDebugType : memberDebugTypes) { 1063617a3babSopenharmony_ci type->addIdOperand(memberDebugType); 1064617a3babSopenharmony_ci } 1065617a3babSopenharmony_ci 1066617a3babSopenharmony_ci groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeComposite].push_back(type); 1067617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 1068617a3babSopenharmony_ci module.mapInstruction(type); 1069617a3babSopenharmony_ci 1070617a3babSopenharmony_ci return type->getResultId(); 1071617a3babSopenharmony_ci} 1072617a3babSopenharmony_ci 1073617a3babSopenharmony_ciId Builder::makeDebugSource(const Id fileName) { 1074617a3babSopenharmony_ci if (debugSourceId.find(fileName) != debugSourceId.end()) 1075617a3babSopenharmony_ci return debugSourceId[fileName]; 1076617a3babSopenharmony_ci spv::Id resultId = getUniqueId(); 1077617a3babSopenharmony_ci Instruction* sourceInst = new Instruction(resultId, makeVoidType(), OpExtInst); 1078617a3babSopenharmony_ci sourceInst->addIdOperand(nonSemanticShaderDebugInfo); 1079617a3babSopenharmony_ci sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugSource); 1080617a3babSopenharmony_ci sourceInst->addIdOperand(fileName); 1081617a3babSopenharmony_ci if (emitNonSemanticShaderDebugSource) { 1082617a3babSopenharmony_ci spv::Id sourceId = 0; 1083617a3babSopenharmony_ci if (fileName == sourceFileStringId) { 1084617a3babSopenharmony_ci sourceId = getStringId(sourceText); 1085617a3babSopenharmony_ci } else { 1086617a3babSopenharmony_ci auto incItr = includeFiles.find(fileName); 1087617a3babSopenharmony_ci assert(incItr != includeFiles.end()); 1088617a3babSopenharmony_ci sourceId = getStringId(*incItr->second); 1089617a3babSopenharmony_ci } 1090617a3babSopenharmony_ci sourceInst->addIdOperand(sourceId); 1091617a3babSopenharmony_ci } 1092617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst)); 1093617a3babSopenharmony_ci module.mapInstruction(sourceInst); 1094617a3babSopenharmony_ci debugSourceId[fileName] = resultId; 1095617a3babSopenharmony_ci return resultId; 1096617a3babSopenharmony_ci} 1097617a3babSopenharmony_ci 1098617a3babSopenharmony_ciId Builder::makeDebugCompilationUnit() { 1099617a3babSopenharmony_ci if (nonSemanticShaderCompilationUnitId != 0) 1100617a3babSopenharmony_ci return nonSemanticShaderCompilationUnitId; 1101617a3babSopenharmony_ci spv::Id resultId = getUniqueId(); 1102617a3babSopenharmony_ci Instruction* sourceInst = new Instruction(resultId, makeVoidType(), OpExtInst); 1103617a3babSopenharmony_ci sourceInst->addIdOperand(nonSemanticShaderDebugInfo); 1104617a3babSopenharmony_ci sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugCompilationUnit); 1105617a3babSopenharmony_ci sourceInst->addIdOperand(makeUintConstant(1)); // TODO(greg-lunarg): Get rid of magic number 1106617a3babSopenharmony_ci sourceInst->addIdOperand(makeUintConstant(4)); // TODO(greg-lunarg): Get rid of magic number 1107617a3babSopenharmony_ci sourceInst->addIdOperand(makeDebugSource(sourceFileStringId)); 1108617a3babSopenharmony_ci sourceInst->addIdOperand(makeUintConstant(sourceLang)); 1109617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst)); 1110617a3babSopenharmony_ci module.mapInstruction(sourceInst); 1111617a3babSopenharmony_ci nonSemanticShaderCompilationUnitId = resultId; 1112617a3babSopenharmony_ci 1113617a3babSopenharmony_ci // We can reasonably assume that makeDebugCompilationUnit will be called before any of 1114617a3babSopenharmony_ci // debug-scope stack. Function scopes and lexical scopes will occur afterward. 1115617a3babSopenharmony_ci assert(currentDebugScopeId.empty()); 1116617a3babSopenharmony_ci currentDebugScopeId.push(nonSemanticShaderCompilationUnitId); 1117617a3babSopenharmony_ci 1118617a3babSopenharmony_ci return resultId; 1119617a3babSopenharmony_ci} 1120617a3babSopenharmony_ci 1121617a3babSopenharmony_ciId Builder::createDebugGlobalVariable(Id const type, char const*const name, Id const variable) 1122617a3babSopenharmony_ci{ 1123617a3babSopenharmony_ci assert(type != 0); 1124617a3babSopenharmony_ci 1125617a3babSopenharmony_ci Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 1126617a3babSopenharmony_ci inst->addIdOperand(nonSemanticShaderDebugInfo); 1127617a3babSopenharmony_ci inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugGlobalVariable); 1128617a3babSopenharmony_ci inst->addIdOperand(getStringId(name)); // name id 1129617a3babSopenharmony_ci inst->addIdOperand(type); // type id 1130617a3babSopenharmony_ci inst->addIdOperand(makeDebugSource(sourceFileStringId)); // source id 1131617a3babSopenharmony_ci inst->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero? 1132617a3babSopenharmony_ci inst->addIdOperand(makeUintConstant(0)); // TODO: column id 1133617a3babSopenharmony_ci inst->addIdOperand(makeDebugCompilationUnit()); // scope id 1134617a3babSopenharmony_ci inst->addIdOperand(getStringId(name)); // linkage name id 1135617a3babSopenharmony_ci inst->addIdOperand(variable); // variable id 1136617a3babSopenharmony_ci inst->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsDefinition)); // flags id 1137617a3babSopenharmony_ci 1138617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst)); 1139617a3babSopenharmony_ci module.mapInstruction(inst); 1140617a3babSopenharmony_ci 1141617a3babSopenharmony_ci return inst->getResultId(); 1142617a3babSopenharmony_ci} 1143617a3babSopenharmony_ci 1144617a3babSopenharmony_ciId Builder::createDebugLocalVariable(Id type, char const*const name, size_t const argNumber) 1145617a3babSopenharmony_ci{ 1146617a3babSopenharmony_ci assert(name != nullptr); 1147617a3babSopenharmony_ci assert(!currentDebugScopeId.empty()); 1148617a3babSopenharmony_ci 1149617a3babSopenharmony_ci Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 1150617a3babSopenharmony_ci inst->addIdOperand(nonSemanticShaderDebugInfo); 1151617a3babSopenharmony_ci inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLocalVariable); 1152617a3babSopenharmony_ci inst->addIdOperand(getStringId(name)); // name id 1153617a3babSopenharmony_ci inst->addIdOperand(type); // type id 1154617a3babSopenharmony_ci inst->addIdOperand(makeDebugSource(sourceFileStringId)); // source id 1155617a3babSopenharmony_ci inst->addIdOperand(makeUintConstant(currentLine)); // line id 1156617a3babSopenharmony_ci inst->addIdOperand(makeUintConstant(0)); // TODO: column id 1157617a3babSopenharmony_ci inst->addIdOperand(currentDebugScopeId.top()); // scope id 1158617a3babSopenharmony_ci inst->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsLocal)); // flags id 1159617a3babSopenharmony_ci if(argNumber != 0) { 1160617a3babSopenharmony_ci inst->addIdOperand(makeUintConstant(argNumber)); 1161617a3babSopenharmony_ci } 1162617a3babSopenharmony_ci 1163617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst)); 1164617a3babSopenharmony_ci module.mapInstruction(inst); 1165617a3babSopenharmony_ci 1166617a3babSopenharmony_ci return inst->getResultId(); 1167617a3babSopenharmony_ci} 1168617a3babSopenharmony_ci 1169617a3babSopenharmony_ciId Builder::makeDebugExpression() 1170617a3babSopenharmony_ci{ 1171617a3babSopenharmony_ci if (debugExpression != 0) 1172617a3babSopenharmony_ci return debugExpression; 1173617a3babSopenharmony_ci 1174617a3babSopenharmony_ci Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 1175617a3babSopenharmony_ci inst->addIdOperand(nonSemanticShaderDebugInfo); 1176617a3babSopenharmony_ci inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugExpression); 1177617a3babSopenharmony_ci 1178617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst)); 1179617a3babSopenharmony_ci module.mapInstruction(inst); 1180617a3babSopenharmony_ci 1181617a3babSopenharmony_ci debugExpression = inst->getResultId(); 1182617a3babSopenharmony_ci 1183617a3babSopenharmony_ci return debugExpression; 1184617a3babSopenharmony_ci} 1185617a3babSopenharmony_ci 1186617a3babSopenharmony_ciId Builder::makeDebugDeclare(Id const debugLocalVariable, Id const pointer) 1187617a3babSopenharmony_ci{ 1188617a3babSopenharmony_ci Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 1189617a3babSopenharmony_ci inst->addIdOperand(nonSemanticShaderDebugInfo); 1190617a3babSopenharmony_ci inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugDeclare); 1191617a3babSopenharmony_ci inst->addIdOperand(debugLocalVariable); // debug local variable id 1192617a3babSopenharmony_ci inst->addIdOperand(pointer); // pointer to local variable id 1193617a3babSopenharmony_ci inst->addIdOperand(makeDebugExpression()); // expression id 1194617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(inst)); 1195617a3babSopenharmony_ci 1196617a3babSopenharmony_ci return inst->getResultId(); 1197617a3babSopenharmony_ci} 1198617a3babSopenharmony_ci 1199617a3babSopenharmony_ciId Builder::makeDebugValue(Id const debugLocalVariable, Id const value) 1200617a3babSopenharmony_ci{ 1201617a3babSopenharmony_ci Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); 1202617a3babSopenharmony_ci inst->addIdOperand(nonSemanticShaderDebugInfo); 1203617a3babSopenharmony_ci inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugValue); 1204617a3babSopenharmony_ci inst->addIdOperand(debugLocalVariable); // debug local variable id 1205617a3babSopenharmony_ci inst->addIdOperand(value); // value of local variable id 1206617a3babSopenharmony_ci inst->addIdOperand(makeDebugExpression()); // expression id 1207617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(inst)); 1208617a3babSopenharmony_ci 1209617a3babSopenharmony_ci return inst->getResultId(); 1210617a3babSopenharmony_ci} 1211617a3babSopenharmony_ci 1212617a3babSopenharmony_ciId Builder::makeAccelerationStructureType() 1213617a3babSopenharmony_ci{ 1214617a3babSopenharmony_ci Instruction *type; 1215617a3babSopenharmony_ci if (groupedTypes[OpTypeAccelerationStructureKHR].size() == 0) { 1216617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureKHR); 1217617a3babSopenharmony_ci groupedTypes[OpTypeAccelerationStructureKHR].push_back(type); 1218617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 1219617a3babSopenharmony_ci module.mapInstruction(type); 1220617a3babSopenharmony_ci } else { 1221617a3babSopenharmony_ci type = groupedTypes[OpTypeAccelerationStructureKHR].back(); 1222617a3babSopenharmony_ci } 1223617a3babSopenharmony_ci 1224617a3babSopenharmony_ci return type->getResultId(); 1225617a3babSopenharmony_ci} 1226617a3babSopenharmony_ci 1227617a3babSopenharmony_ciId Builder::makeRayQueryType() 1228617a3babSopenharmony_ci{ 1229617a3babSopenharmony_ci Instruction *type; 1230617a3babSopenharmony_ci if (groupedTypes[OpTypeRayQueryKHR].size() == 0) { 1231617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryKHR); 1232617a3babSopenharmony_ci groupedTypes[OpTypeRayQueryKHR].push_back(type); 1233617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 1234617a3babSopenharmony_ci module.mapInstruction(type); 1235617a3babSopenharmony_ci } else { 1236617a3babSopenharmony_ci type = groupedTypes[OpTypeRayQueryKHR].back(); 1237617a3babSopenharmony_ci } 1238617a3babSopenharmony_ci 1239617a3babSopenharmony_ci return type->getResultId(); 1240617a3babSopenharmony_ci} 1241617a3babSopenharmony_ci 1242617a3babSopenharmony_ciId Builder::makeHitObjectNVType() 1243617a3babSopenharmony_ci{ 1244617a3babSopenharmony_ci Instruction *type; 1245617a3babSopenharmony_ci if (groupedTypes[OpTypeHitObjectNV].size() == 0) { 1246617a3babSopenharmony_ci type = new Instruction(getUniqueId(), NoType, OpTypeHitObjectNV); 1247617a3babSopenharmony_ci groupedTypes[OpTypeHitObjectNV].push_back(type); 1248617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 1249617a3babSopenharmony_ci module.mapInstruction(type); 1250617a3babSopenharmony_ci } else { 1251617a3babSopenharmony_ci type = groupedTypes[OpTypeHitObjectNV].back(); 1252617a3babSopenharmony_ci } 1253617a3babSopenharmony_ci 1254617a3babSopenharmony_ci return type->getResultId(); 1255617a3babSopenharmony_ci} 1256617a3babSopenharmony_ci 1257617a3babSopenharmony_ciId Builder::getDerefTypeId(Id resultId) const 1258617a3babSopenharmony_ci{ 1259617a3babSopenharmony_ci Id typeId = getTypeId(resultId); 1260617a3babSopenharmony_ci assert(isPointerType(typeId)); 1261617a3babSopenharmony_ci 1262617a3babSopenharmony_ci return module.getInstruction(typeId)->getIdOperand(1); 1263617a3babSopenharmony_ci} 1264617a3babSopenharmony_ci 1265617a3babSopenharmony_ciOp Builder::getMostBasicTypeClass(Id typeId) const 1266617a3babSopenharmony_ci{ 1267617a3babSopenharmony_ci Instruction* instr = module.getInstruction(typeId); 1268617a3babSopenharmony_ci 1269617a3babSopenharmony_ci Op typeClass = instr->getOpCode(); 1270617a3babSopenharmony_ci switch (typeClass) 1271617a3babSopenharmony_ci { 1272617a3babSopenharmony_ci case OpTypeVector: 1273617a3babSopenharmony_ci case OpTypeMatrix: 1274617a3babSopenharmony_ci case OpTypeArray: 1275617a3babSopenharmony_ci case OpTypeRuntimeArray: 1276617a3babSopenharmony_ci return getMostBasicTypeClass(instr->getIdOperand(0)); 1277617a3babSopenharmony_ci case OpTypePointer: 1278617a3babSopenharmony_ci return getMostBasicTypeClass(instr->getIdOperand(1)); 1279617a3babSopenharmony_ci default: 1280617a3babSopenharmony_ci return typeClass; 1281617a3babSopenharmony_ci } 1282617a3babSopenharmony_ci} 1283617a3babSopenharmony_ci 1284617a3babSopenharmony_ciint Builder::getNumTypeConstituents(Id typeId) const 1285617a3babSopenharmony_ci{ 1286617a3babSopenharmony_ci Instruction* instr = module.getInstruction(typeId); 1287617a3babSopenharmony_ci 1288617a3babSopenharmony_ci switch (instr->getOpCode()) 1289617a3babSopenharmony_ci { 1290617a3babSopenharmony_ci case OpTypeBool: 1291617a3babSopenharmony_ci case OpTypeInt: 1292617a3babSopenharmony_ci case OpTypeFloat: 1293617a3babSopenharmony_ci case OpTypePointer: 1294617a3babSopenharmony_ci return 1; 1295617a3babSopenharmony_ci case OpTypeVector: 1296617a3babSopenharmony_ci case OpTypeMatrix: 1297617a3babSopenharmony_ci return instr->getImmediateOperand(1); 1298617a3babSopenharmony_ci case OpTypeArray: 1299617a3babSopenharmony_ci { 1300617a3babSopenharmony_ci Id lengthId = instr->getIdOperand(1); 1301617a3babSopenharmony_ci return module.getInstruction(lengthId)->getImmediateOperand(0); 1302617a3babSopenharmony_ci } 1303617a3babSopenharmony_ci case OpTypeStruct: 1304617a3babSopenharmony_ci return instr->getNumOperands(); 1305617a3babSopenharmony_ci case OpTypeCooperativeMatrixKHR: 1306617a3babSopenharmony_ci case OpTypeCooperativeMatrixNV: 1307617a3babSopenharmony_ci // has only one constituent when used with OpCompositeConstruct. 1308617a3babSopenharmony_ci return 1; 1309617a3babSopenharmony_ci default: 1310617a3babSopenharmony_ci assert(0); 1311617a3babSopenharmony_ci return 1; 1312617a3babSopenharmony_ci } 1313617a3babSopenharmony_ci} 1314617a3babSopenharmony_ci 1315617a3babSopenharmony_ci// Return the lowest-level type of scalar that an homogeneous composite is made out of. 1316617a3babSopenharmony_ci// Typically, this is just to find out if something is made out of ints or floats. 1317617a3babSopenharmony_ci// However, it includes returning a structure, if say, it is an array of structure. 1318617a3babSopenharmony_ciId Builder::getScalarTypeId(Id typeId) const 1319617a3babSopenharmony_ci{ 1320617a3babSopenharmony_ci Instruction* instr = module.getInstruction(typeId); 1321617a3babSopenharmony_ci 1322617a3babSopenharmony_ci Op typeClass = instr->getOpCode(); 1323617a3babSopenharmony_ci switch (typeClass) 1324617a3babSopenharmony_ci { 1325617a3babSopenharmony_ci case OpTypeVoid: 1326617a3babSopenharmony_ci case OpTypeBool: 1327617a3babSopenharmony_ci case OpTypeInt: 1328617a3babSopenharmony_ci case OpTypeFloat: 1329617a3babSopenharmony_ci case OpTypeStruct: 1330617a3babSopenharmony_ci return instr->getResultId(); 1331617a3babSopenharmony_ci case OpTypeVector: 1332617a3babSopenharmony_ci case OpTypeMatrix: 1333617a3babSopenharmony_ci case OpTypeArray: 1334617a3babSopenharmony_ci case OpTypeRuntimeArray: 1335617a3babSopenharmony_ci case OpTypePointer: 1336617a3babSopenharmony_ci return getScalarTypeId(getContainedTypeId(typeId)); 1337617a3babSopenharmony_ci default: 1338617a3babSopenharmony_ci assert(0); 1339617a3babSopenharmony_ci return NoResult; 1340617a3babSopenharmony_ci } 1341617a3babSopenharmony_ci} 1342617a3babSopenharmony_ci 1343617a3babSopenharmony_ci// Return the type of 'member' of a composite. 1344617a3babSopenharmony_ciId Builder::getContainedTypeId(Id typeId, int member) const 1345617a3babSopenharmony_ci{ 1346617a3babSopenharmony_ci Instruction* instr = module.getInstruction(typeId); 1347617a3babSopenharmony_ci 1348617a3babSopenharmony_ci Op typeClass = instr->getOpCode(); 1349617a3babSopenharmony_ci switch (typeClass) 1350617a3babSopenharmony_ci { 1351617a3babSopenharmony_ci case OpTypeVector: 1352617a3babSopenharmony_ci case OpTypeMatrix: 1353617a3babSopenharmony_ci case OpTypeArray: 1354617a3babSopenharmony_ci case OpTypeRuntimeArray: 1355617a3babSopenharmony_ci case OpTypeCooperativeMatrixKHR: 1356617a3babSopenharmony_ci case OpTypeCooperativeMatrixNV: 1357617a3babSopenharmony_ci return instr->getIdOperand(0); 1358617a3babSopenharmony_ci case OpTypePointer: 1359617a3babSopenharmony_ci return instr->getIdOperand(1); 1360617a3babSopenharmony_ci case OpTypeStruct: 1361617a3babSopenharmony_ci return instr->getIdOperand(member); 1362617a3babSopenharmony_ci default: 1363617a3babSopenharmony_ci assert(0); 1364617a3babSopenharmony_ci return NoResult; 1365617a3babSopenharmony_ci } 1366617a3babSopenharmony_ci} 1367617a3babSopenharmony_ci 1368617a3babSopenharmony_ci// Figure out the final resulting type of the access chain. 1369617a3babSopenharmony_ciId Builder::getResultingAccessChainType() const 1370617a3babSopenharmony_ci{ 1371617a3babSopenharmony_ci assert(accessChain.base != NoResult); 1372617a3babSopenharmony_ci Id typeId = getTypeId(accessChain.base); 1373617a3babSopenharmony_ci 1374617a3babSopenharmony_ci assert(isPointerType(typeId)); 1375617a3babSopenharmony_ci typeId = getContainedTypeId(typeId); 1376617a3babSopenharmony_ci 1377617a3babSopenharmony_ci for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) { 1378617a3babSopenharmony_ci if (isStructType(typeId)) { 1379617a3babSopenharmony_ci assert(isConstantScalar(accessChain.indexChain[i])); 1380617a3babSopenharmony_ci typeId = getContainedTypeId(typeId, getConstantScalar(accessChain.indexChain[i])); 1381617a3babSopenharmony_ci } else 1382617a3babSopenharmony_ci typeId = getContainedTypeId(typeId, accessChain.indexChain[i]); 1383617a3babSopenharmony_ci } 1384617a3babSopenharmony_ci 1385617a3babSopenharmony_ci return typeId; 1386617a3babSopenharmony_ci} 1387617a3babSopenharmony_ci 1388617a3babSopenharmony_ci// Return the immediately contained type of a given composite type. 1389617a3babSopenharmony_ciId Builder::getContainedTypeId(Id typeId) const 1390617a3babSopenharmony_ci{ 1391617a3babSopenharmony_ci return getContainedTypeId(typeId, 0); 1392617a3babSopenharmony_ci} 1393617a3babSopenharmony_ci 1394617a3babSopenharmony_ci// Returns true if 'typeId' is or contains a scalar type declared with 'typeOp' 1395617a3babSopenharmony_ci// of width 'width'. The 'width' is only consumed for int and float types. 1396617a3babSopenharmony_ci// Returns false otherwise. 1397617a3babSopenharmony_cibool Builder::containsType(Id typeId, spv::Op typeOp, unsigned int width) const 1398617a3babSopenharmony_ci{ 1399617a3babSopenharmony_ci const Instruction& instr = *module.getInstruction(typeId); 1400617a3babSopenharmony_ci 1401617a3babSopenharmony_ci Op typeClass = instr.getOpCode(); 1402617a3babSopenharmony_ci switch (typeClass) 1403617a3babSopenharmony_ci { 1404617a3babSopenharmony_ci case OpTypeInt: 1405617a3babSopenharmony_ci case OpTypeFloat: 1406617a3babSopenharmony_ci return typeClass == typeOp && instr.getImmediateOperand(0) == width; 1407617a3babSopenharmony_ci case OpTypeStruct: 1408617a3babSopenharmony_ci for (int m = 0; m < instr.getNumOperands(); ++m) { 1409617a3babSopenharmony_ci if (containsType(instr.getIdOperand(m), typeOp, width)) 1410617a3babSopenharmony_ci return true; 1411617a3babSopenharmony_ci } 1412617a3babSopenharmony_ci return false; 1413617a3babSopenharmony_ci case OpTypePointer: 1414617a3babSopenharmony_ci return false; 1415617a3babSopenharmony_ci case OpTypeVector: 1416617a3babSopenharmony_ci case OpTypeMatrix: 1417617a3babSopenharmony_ci case OpTypeArray: 1418617a3babSopenharmony_ci case OpTypeRuntimeArray: 1419617a3babSopenharmony_ci return containsType(getContainedTypeId(typeId), typeOp, width); 1420617a3babSopenharmony_ci default: 1421617a3babSopenharmony_ci return typeClass == typeOp; 1422617a3babSopenharmony_ci } 1423617a3babSopenharmony_ci} 1424617a3babSopenharmony_ci 1425617a3babSopenharmony_ci// return true if the type is a pointer to PhysicalStorageBufferEXT or an 1426617a3babSopenharmony_ci// contains such a pointer. These require restrict/aliased decorations. 1427617a3babSopenharmony_cibool Builder::containsPhysicalStorageBufferOrArray(Id typeId) const 1428617a3babSopenharmony_ci{ 1429617a3babSopenharmony_ci const Instruction& instr = *module.getInstruction(typeId); 1430617a3babSopenharmony_ci 1431617a3babSopenharmony_ci Op typeClass = instr.getOpCode(); 1432617a3babSopenharmony_ci switch (typeClass) 1433617a3babSopenharmony_ci { 1434617a3babSopenharmony_ci case OpTypePointer: 1435617a3babSopenharmony_ci return getTypeStorageClass(typeId) == StorageClassPhysicalStorageBufferEXT; 1436617a3babSopenharmony_ci case OpTypeArray: 1437617a3babSopenharmony_ci return containsPhysicalStorageBufferOrArray(getContainedTypeId(typeId)); 1438617a3babSopenharmony_ci case OpTypeStruct: 1439617a3babSopenharmony_ci for (int m = 0; m < instr.getNumOperands(); ++m) { 1440617a3babSopenharmony_ci if (containsPhysicalStorageBufferOrArray(instr.getIdOperand(m))) 1441617a3babSopenharmony_ci return true; 1442617a3babSopenharmony_ci } 1443617a3babSopenharmony_ci return false; 1444617a3babSopenharmony_ci default: 1445617a3babSopenharmony_ci return false; 1446617a3babSopenharmony_ci } 1447617a3babSopenharmony_ci} 1448617a3babSopenharmony_ci 1449617a3babSopenharmony_ci// See if a scalar constant of this type has already been created, so it 1450617a3babSopenharmony_ci// can be reused rather than duplicated. (Required by the specification). 1451617a3babSopenharmony_ciId Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) 1452617a3babSopenharmony_ci{ 1453617a3babSopenharmony_ci Instruction* constant; 1454617a3babSopenharmony_ci for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { 1455617a3babSopenharmony_ci constant = groupedConstants[typeClass][i]; 1456617a3babSopenharmony_ci if (constant->getOpCode() == opcode && 1457617a3babSopenharmony_ci constant->getTypeId() == typeId && 1458617a3babSopenharmony_ci constant->getImmediateOperand(0) == value) 1459617a3babSopenharmony_ci return constant->getResultId(); 1460617a3babSopenharmony_ci } 1461617a3babSopenharmony_ci 1462617a3babSopenharmony_ci return 0; 1463617a3babSopenharmony_ci} 1464617a3babSopenharmony_ci 1465617a3babSopenharmony_ci// Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double' or 'int64'). 1466617a3babSopenharmony_ciId Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) 1467617a3babSopenharmony_ci{ 1468617a3babSopenharmony_ci Instruction* constant; 1469617a3babSopenharmony_ci for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { 1470617a3babSopenharmony_ci constant = groupedConstants[typeClass][i]; 1471617a3babSopenharmony_ci if (constant->getOpCode() == opcode && 1472617a3babSopenharmony_ci constant->getTypeId() == typeId && 1473617a3babSopenharmony_ci constant->getImmediateOperand(0) == v1 && 1474617a3babSopenharmony_ci constant->getImmediateOperand(1) == v2) 1475617a3babSopenharmony_ci return constant->getResultId(); 1476617a3babSopenharmony_ci } 1477617a3babSopenharmony_ci 1478617a3babSopenharmony_ci return 0; 1479617a3babSopenharmony_ci} 1480617a3babSopenharmony_ci 1481617a3babSopenharmony_ci// Return true if consuming 'opcode' means consuming a constant. 1482617a3babSopenharmony_ci// "constant" here means after final transform to executable code, 1483617a3babSopenharmony_ci// the value consumed will be a constant, so includes specialization. 1484617a3babSopenharmony_cibool Builder::isConstantOpCode(Op opcode) const 1485617a3babSopenharmony_ci{ 1486617a3babSopenharmony_ci switch (opcode) { 1487617a3babSopenharmony_ci case OpUndef: 1488617a3babSopenharmony_ci case OpConstantTrue: 1489617a3babSopenharmony_ci case OpConstantFalse: 1490617a3babSopenharmony_ci case OpConstant: 1491617a3babSopenharmony_ci case OpConstantComposite: 1492617a3babSopenharmony_ci case OpConstantSampler: 1493617a3babSopenharmony_ci case OpConstantNull: 1494617a3babSopenharmony_ci case OpSpecConstantTrue: 1495617a3babSopenharmony_ci case OpSpecConstantFalse: 1496617a3babSopenharmony_ci case OpSpecConstant: 1497617a3babSopenharmony_ci case OpSpecConstantComposite: 1498617a3babSopenharmony_ci case OpSpecConstantOp: 1499617a3babSopenharmony_ci return true; 1500617a3babSopenharmony_ci default: 1501617a3babSopenharmony_ci return false; 1502617a3babSopenharmony_ci } 1503617a3babSopenharmony_ci} 1504617a3babSopenharmony_ci 1505617a3babSopenharmony_ci// Return true if consuming 'opcode' means consuming a specialization constant. 1506617a3babSopenharmony_cibool Builder::isSpecConstantOpCode(Op opcode) const 1507617a3babSopenharmony_ci{ 1508617a3babSopenharmony_ci switch (opcode) { 1509617a3babSopenharmony_ci case OpSpecConstantTrue: 1510617a3babSopenharmony_ci case OpSpecConstantFalse: 1511617a3babSopenharmony_ci case OpSpecConstant: 1512617a3babSopenharmony_ci case OpSpecConstantComposite: 1513617a3babSopenharmony_ci case OpSpecConstantOp: 1514617a3babSopenharmony_ci return true; 1515617a3babSopenharmony_ci default: 1516617a3babSopenharmony_ci return false; 1517617a3babSopenharmony_ci } 1518617a3babSopenharmony_ci} 1519617a3babSopenharmony_ci 1520617a3babSopenharmony_cibool Builder::isRayTracingOpCode(Op opcode) const 1521617a3babSopenharmony_ci{ 1522617a3babSopenharmony_ci switch (opcode) { 1523617a3babSopenharmony_ci case OpTypeAccelerationStructureKHR: 1524617a3babSopenharmony_ci case OpTypeRayQueryKHR: 1525617a3babSopenharmony_ci return true; 1526617a3babSopenharmony_ci default: 1527617a3babSopenharmony_ci return false; 1528617a3babSopenharmony_ci } 1529617a3babSopenharmony_ci} 1530617a3babSopenharmony_ci 1531617a3babSopenharmony_ciId Builder::makeNullConstant(Id typeId) 1532617a3babSopenharmony_ci{ 1533617a3babSopenharmony_ci Instruction* constant; 1534617a3babSopenharmony_ci 1535617a3babSopenharmony_ci // See if we already made it. 1536617a3babSopenharmony_ci Id existing = NoResult; 1537617a3babSopenharmony_ci for (int i = 0; i < (int)nullConstants.size(); ++i) { 1538617a3babSopenharmony_ci constant = nullConstants[i]; 1539617a3babSopenharmony_ci if (constant->getTypeId() == typeId) 1540617a3babSopenharmony_ci existing = constant->getResultId(); 1541617a3babSopenharmony_ci } 1542617a3babSopenharmony_ci 1543617a3babSopenharmony_ci if (existing != NoResult) 1544617a3babSopenharmony_ci return existing; 1545617a3babSopenharmony_ci 1546617a3babSopenharmony_ci // Make it 1547617a3babSopenharmony_ci Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantNull); 1548617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c)); 1549617a3babSopenharmony_ci nullConstants.push_back(c); 1550617a3babSopenharmony_ci module.mapInstruction(c); 1551617a3babSopenharmony_ci 1552617a3babSopenharmony_ci return c->getResultId(); 1553617a3babSopenharmony_ci} 1554617a3babSopenharmony_ci 1555617a3babSopenharmony_ciId Builder::makeBoolConstant(bool b, bool specConstant) 1556617a3babSopenharmony_ci{ 1557617a3babSopenharmony_ci Id typeId = makeBoolType(); 1558617a3babSopenharmony_ci Instruction* constant; 1559617a3babSopenharmony_ci Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse) : (b ? OpConstantTrue : OpConstantFalse); 1560617a3babSopenharmony_ci 1561617a3babSopenharmony_ci // See if we already made it. Applies only to regular constants, because specialization constants 1562617a3babSopenharmony_ci // must remain distinct for the purpose of applying a SpecId decoration. 1563617a3babSopenharmony_ci if (! specConstant) { 1564617a3babSopenharmony_ci Id existing = 0; 1565617a3babSopenharmony_ci for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) { 1566617a3babSopenharmony_ci constant = groupedConstants[OpTypeBool][i]; 1567617a3babSopenharmony_ci if (constant->getTypeId() == typeId && constant->getOpCode() == opcode) 1568617a3babSopenharmony_ci existing = constant->getResultId(); 1569617a3babSopenharmony_ci } 1570617a3babSopenharmony_ci 1571617a3babSopenharmony_ci if (existing) 1572617a3babSopenharmony_ci return existing; 1573617a3babSopenharmony_ci } 1574617a3babSopenharmony_ci 1575617a3babSopenharmony_ci // Make it 1576617a3babSopenharmony_ci Instruction* c = new Instruction(getUniqueId(), typeId, opcode); 1577617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c)); 1578617a3babSopenharmony_ci groupedConstants[OpTypeBool].push_back(c); 1579617a3babSopenharmony_ci module.mapInstruction(c); 1580617a3babSopenharmony_ci 1581617a3babSopenharmony_ci return c->getResultId(); 1582617a3babSopenharmony_ci} 1583617a3babSopenharmony_ci 1584617a3babSopenharmony_ciId Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant) 1585617a3babSopenharmony_ci{ 1586617a3babSopenharmony_ci Op opcode = specConstant ? OpSpecConstant : OpConstant; 1587617a3babSopenharmony_ci 1588617a3babSopenharmony_ci // See if we already made it. Applies only to regular constants, because specialization constants 1589617a3babSopenharmony_ci // must remain distinct for the purpose of applying a SpecId decoration. 1590617a3babSopenharmony_ci if (! specConstant) { 1591617a3babSopenharmony_ci Id existing = findScalarConstant(OpTypeInt, opcode, typeId, value); 1592617a3babSopenharmony_ci if (existing) 1593617a3babSopenharmony_ci return existing; 1594617a3babSopenharmony_ci } 1595617a3babSopenharmony_ci 1596617a3babSopenharmony_ci Instruction* c = new Instruction(getUniqueId(), typeId, opcode); 1597617a3babSopenharmony_ci c->addImmediateOperand(value); 1598617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c)); 1599617a3babSopenharmony_ci groupedConstants[OpTypeInt].push_back(c); 1600617a3babSopenharmony_ci module.mapInstruction(c); 1601617a3babSopenharmony_ci 1602617a3babSopenharmony_ci return c->getResultId(); 1603617a3babSopenharmony_ci} 1604617a3babSopenharmony_ci 1605617a3babSopenharmony_ciId Builder::makeInt64Constant(Id typeId, unsigned long long value, bool specConstant) 1606617a3babSopenharmony_ci{ 1607617a3babSopenharmony_ci Op opcode = specConstant ? OpSpecConstant : OpConstant; 1608617a3babSopenharmony_ci 1609617a3babSopenharmony_ci unsigned op1 = value & 0xFFFFFFFF; 1610617a3babSopenharmony_ci unsigned op2 = value >> 32; 1611617a3babSopenharmony_ci 1612617a3babSopenharmony_ci // See if we already made it. Applies only to regular constants, because specialization constants 1613617a3babSopenharmony_ci // must remain distinct for the purpose of applying a SpecId decoration. 1614617a3babSopenharmony_ci if (! specConstant) { 1615617a3babSopenharmony_ci Id existing = findScalarConstant(OpTypeInt, opcode, typeId, op1, op2); 1616617a3babSopenharmony_ci if (existing) 1617617a3babSopenharmony_ci return existing; 1618617a3babSopenharmony_ci } 1619617a3babSopenharmony_ci 1620617a3babSopenharmony_ci Instruction* c = new Instruction(getUniqueId(), typeId, opcode); 1621617a3babSopenharmony_ci c->addImmediateOperand(op1); 1622617a3babSopenharmony_ci c->addImmediateOperand(op2); 1623617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c)); 1624617a3babSopenharmony_ci groupedConstants[OpTypeInt].push_back(c); 1625617a3babSopenharmony_ci module.mapInstruction(c); 1626617a3babSopenharmony_ci 1627617a3babSopenharmony_ci return c->getResultId(); 1628617a3babSopenharmony_ci} 1629617a3babSopenharmony_ci 1630617a3babSopenharmony_ciId Builder::makeFloatConstant(float f, bool specConstant) 1631617a3babSopenharmony_ci{ 1632617a3babSopenharmony_ci Op opcode = specConstant ? OpSpecConstant : OpConstant; 1633617a3babSopenharmony_ci Id typeId = makeFloatType(32); 1634617a3babSopenharmony_ci union { float fl; unsigned int ui; } u; 1635617a3babSopenharmony_ci u.fl = f; 1636617a3babSopenharmony_ci unsigned value = u.ui; 1637617a3babSopenharmony_ci 1638617a3babSopenharmony_ci // See if we already made it. Applies only to regular constants, because specialization constants 1639617a3babSopenharmony_ci // must remain distinct for the purpose of applying a SpecId decoration. 1640617a3babSopenharmony_ci if (! specConstant) { 1641617a3babSopenharmony_ci Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value); 1642617a3babSopenharmony_ci if (existing) 1643617a3babSopenharmony_ci return existing; 1644617a3babSopenharmony_ci } 1645617a3babSopenharmony_ci 1646617a3babSopenharmony_ci Instruction* c = new Instruction(getUniqueId(), typeId, opcode); 1647617a3babSopenharmony_ci c->addImmediateOperand(value); 1648617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c)); 1649617a3babSopenharmony_ci groupedConstants[OpTypeFloat].push_back(c); 1650617a3babSopenharmony_ci module.mapInstruction(c); 1651617a3babSopenharmony_ci 1652617a3babSopenharmony_ci return c->getResultId(); 1653617a3babSopenharmony_ci} 1654617a3babSopenharmony_ci 1655617a3babSopenharmony_ciId Builder::makeDoubleConstant(double d, bool specConstant) 1656617a3babSopenharmony_ci{ 1657617a3babSopenharmony_ci Op opcode = specConstant ? OpSpecConstant : OpConstant; 1658617a3babSopenharmony_ci Id typeId = makeFloatType(64); 1659617a3babSopenharmony_ci union { double db; unsigned long long ull; } u; 1660617a3babSopenharmony_ci u.db = d; 1661617a3babSopenharmony_ci unsigned long long value = u.ull; 1662617a3babSopenharmony_ci unsigned op1 = value & 0xFFFFFFFF; 1663617a3babSopenharmony_ci unsigned op2 = value >> 32; 1664617a3babSopenharmony_ci 1665617a3babSopenharmony_ci // See if we already made it. Applies only to regular constants, because specialization constants 1666617a3babSopenharmony_ci // must remain distinct for the purpose of applying a SpecId decoration. 1667617a3babSopenharmony_ci if (! specConstant) { 1668617a3babSopenharmony_ci Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, op1, op2); 1669617a3babSopenharmony_ci if (existing) 1670617a3babSopenharmony_ci return existing; 1671617a3babSopenharmony_ci } 1672617a3babSopenharmony_ci 1673617a3babSopenharmony_ci Instruction* c = new Instruction(getUniqueId(), typeId, opcode); 1674617a3babSopenharmony_ci c->addImmediateOperand(op1); 1675617a3babSopenharmony_ci c->addImmediateOperand(op2); 1676617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c)); 1677617a3babSopenharmony_ci groupedConstants[OpTypeFloat].push_back(c); 1678617a3babSopenharmony_ci module.mapInstruction(c); 1679617a3babSopenharmony_ci 1680617a3babSopenharmony_ci return c->getResultId(); 1681617a3babSopenharmony_ci} 1682617a3babSopenharmony_ci 1683617a3babSopenharmony_ciId Builder::makeFloat16Constant(float f16, bool specConstant) 1684617a3babSopenharmony_ci{ 1685617a3babSopenharmony_ci Op opcode = specConstant ? OpSpecConstant : OpConstant; 1686617a3babSopenharmony_ci Id typeId = makeFloatType(16); 1687617a3babSopenharmony_ci 1688617a3babSopenharmony_ci spvutils::HexFloat<spvutils::FloatProxy<float>> fVal(f16); 1689617a3babSopenharmony_ci spvutils::HexFloat<spvutils::FloatProxy<spvutils::Float16>> f16Val(0); 1690617a3babSopenharmony_ci fVal.castTo(f16Val, spvutils::kRoundToZero); 1691617a3babSopenharmony_ci 1692617a3babSopenharmony_ci unsigned value = f16Val.value().getAsFloat().get_value(); 1693617a3babSopenharmony_ci 1694617a3babSopenharmony_ci // See if we already made it. Applies only to regular constants, because specialization constants 1695617a3babSopenharmony_ci // must remain distinct for the purpose of applying a SpecId decoration. 1696617a3babSopenharmony_ci if (!specConstant) { 1697617a3babSopenharmony_ci Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value); 1698617a3babSopenharmony_ci if (existing) 1699617a3babSopenharmony_ci return existing; 1700617a3babSopenharmony_ci } 1701617a3babSopenharmony_ci 1702617a3babSopenharmony_ci Instruction* c = new Instruction(getUniqueId(), typeId, opcode); 1703617a3babSopenharmony_ci c->addImmediateOperand(value); 1704617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c)); 1705617a3babSopenharmony_ci groupedConstants[OpTypeFloat].push_back(c); 1706617a3babSopenharmony_ci module.mapInstruction(c); 1707617a3babSopenharmony_ci 1708617a3babSopenharmony_ci return c->getResultId(); 1709617a3babSopenharmony_ci} 1710617a3babSopenharmony_ci 1711617a3babSopenharmony_ciId Builder::makeFpConstant(Id type, double d, bool specConstant) 1712617a3babSopenharmony_ci{ 1713617a3babSopenharmony_ci const int width = getScalarTypeWidth(type); 1714617a3babSopenharmony_ci 1715617a3babSopenharmony_ci assert(isFloatType(type)); 1716617a3babSopenharmony_ci 1717617a3babSopenharmony_ci switch (width) { 1718617a3babSopenharmony_ci case 16: 1719617a3babSopenharmony_ci return makeFloat16Constant((float)d, specConstant); 1720617a3babSopenharmony_ci case 32: 1721617a3babSopenharmony_ci return makeFloatConstant((float)d, specConstant); 1722617a3babSopenharmony_ci case 64: 1723617a3babSopenharmony_ci return makeDoubleConstant(d, specConstant); 1724617a3babSopenharmony_ci default: 1725617a3babSopenharmony_ci break; 1726617a3babSopenharmony_ci } 1727617a3babSopenharmony_ci 1728617a3babSopenharmony_ci assert(false); 1729617a3babSopenharmony_ci return NoResult; 1730617a3babSopenharmony_ci} 1731617a3babSopenharmony_ci 1732617a3babSopenharmony_ciId Builder::importNonSemanticShaderDebugInfoInstructions() 1733617a3babSopenharmony_ci{ 1734617a3babSopenharmony_ci assert(emitNonSemanticShaderDebugInfo == true); 1735617a3babSopenharmony_ci 1736617a3babSopenharmony_ci if(nonSemanticShaderDebugInfo == 0) 1737617a3babSopenharmony_ci { 1738617a3babSopenharmony_ci this->addExtension(spv::E_SPV_KHR_non_semantic_info); 1739617a3babSopenharmony_ci nonSemanticShaderDebugInfo = this->import("NonSemantic.Shader.DebugInfo.100"); 1740617a3babSopenharmony_ci } 1741617a3babSopenharmony_ci 1742617a3babSopenharmony_ci return nonSemanticShaderDebugInfo; 1743617a3babSopenharmony_ci} 1744617a3babSopenharmony_ci 1745617a3babSopenharmony_ciId Builder::findCompositeConstant(Op typeClass, Id typeId, const std::vector<Id>& comps) 1746617a3babSopenharmony_ci{ 1747617a3babSopenharmony_ci Instruction* constant = nullptr; 1748617a3babSopenharmony_ci bool found = false; 1749617a3babSopenharmony_ci for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { 1750617a3babSopenharmony_ci constant = groupedConstants[typeClass][i]; 1751617a3babSopenharmony_ci 1752617a3babSopenharmony_ci if (constant->getTypeId() != typeId) 1753617a3babSopenharmony_ci continue; 1754617a3babSopenharmony_ci 1755617a3babSopenharmony_ci // same contents? 1756617a3babSopenharmony_ci bool mismatch = false; 1757617a3babSopenharmony_ci for (int op = 0; op < constant->getNumOperands(); ++op) { 1758617a3babSopenharmony_ci if (constant->getIdOperand(op) != comps[op]) { 1759617a3babSopenharmony_ci mismatch = true; 1760617a3babSopenharmony_ci break; 1761617a3babSopenharmony_ci } 1762617a3babSopenharmony_ci } 1763617a3babSopenharmony_ci if (! mismatch) { 1764617a3babSopenharmony_ci found = true; 1765617a3babSopenharmony_ci break; 1766617a3babSopenharmony_ci } 1767617a3babSopenharmony_ci } 1768617a3babSopenharmony_ci 1769617a3babSopenharmony_ci return found ? constant->getResultId() : NoResult; 1770617a3babSopenharmony_ci} 1771617a3babSopenharmony_ci 1772617a3babSopenharmony_ciId Builder::findStructConstant(Id typeId, const std::vector<Id>& comps) 1773617a3babSopenharmony_ci{ 1774617a3babSopenharmony_ci Instruction* constant = nullptr; 1775617a3babSopenharmony_ci bool found = false; 1776617a3babSopenharmony_ci for (int i = 0; i < (int)groupedStructConstants[typeId].size(); ++i) { 1777617a3babSopenharmony_ci constant = groupedStructConstants[typeId][i]; 1778617a3babSopenharmony_ci 1779617a3babSopenharmony_ci // same contents? 1780617a3babSopenharmony_ci bool mismatch = false; 1781617a3babSopenharmony_ci for (int op = 0; op < constant->getNumOperands(); ++op) { 1782617a3babSopenharmony_ci if (constant->getIdOperand(op) != comps[op]) { 1783617a3babSopenharmony_ci mismatch = true; 1784617a3babSopenharmony_ci break; 1785617a3babSopenharmony_ci } 1786617a3babSopenharmony_ci } 1787617a3babSopenharmony_ci if (! mismatch) { 1788617a3babSopenharmony_ci found = true; 1789617a3babSopenharmony_ci break; 1790617a3babSopenharmony_ci } 1791617a3babSopenharmony_ci } 1792617a3babSopenharmony_ci 1793617a3babSopenharmony_ci return found ? constant->getResultId() : NoResult; 1794617a3babSopenharmony_ci} 1795617a3babSopenharmony_ci 1796617a3babSopenharmony_ci// Comments in header 1797617a3babSopenharmony_ciId Builder::makeCompositeConstant(Id typeId, const std::vector<Id>& members, bool specConstant) 1798617a3babSopenharmony_ci{ 1799617a3babSopenharmony_ci Op opcode = specConstant ? OpSpecConstantComposite : OpConstantComposite; 1800617a3babSopenharmony_ci assert(typeId); 1801617a3babSopenharmony_ci Op typeClass = getTypeClass(typeId); 1802617a3babSopenharmony_ci 1803617a3babSopenharmony_ci switch (typeClass) { 1804617a3babSopenharmony_ci case OpTypeVector: 1805617a3babSopenharmony_ci case OpTypeArray: 1806617a3babSopenharmony_ci case OpTypeMatrix: 1807617a3babSopenharmony_ci case OpTypeCooperativeMatrixKHR: 1808617a3babSopenharmony_ci case OpTypeCooperativeMatrixNV: 1809617a3babSopenharmony_ci if (! specConstant) { 1810617a3babSopenharmony_ci Id existing = findCompositeConstant(typeClass, typeId, members); 1811617a3babSopenharmony_ci if (existing) 1812617a3babSopenharmony_ci return existing; 1813617a3babSopenharmony_ci } 1814617a3babSopenharmony_ci break; 1815617a3babSopenharmony_ci case OpTypeStruct: 1816617a3babSopenharmony_ci if (! specConstant) { 1817617a3babSopenharmony_ci Id existing = findStructConstant(typeId, members); 1818617a3babSopenharmony_ci if (existing) 1819617a3babSopenharmony_ci return existing; 1820617a3babSopenharmony_ci } 1821617a3babSopenharmony_ci break; 1822617a3babSopenharmony_ci default: 1823617a3babSopenharmony_ci assert(0); 1824617a3babSopenharmony_ci return makeFloatConstant(0.0); 1825617a3babSopenharmony_ci } 1826617a3babSopenharmony_ci 1827617a3babSopenharmony_ci Instruction* c = new Instruction(getUniqueId(), typeId, opcode); 1828617a3babSopenharmony_ci for (int op = 0; op < (int)members.size(); ++op) 1829617a3babSopenharmony_ci c->addIdOperand(members[op]); 1830617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c)); 1831617a3babSopenharmony_ci if (typeClass == OpTypeStruct) 1832617a3babSopenharmony_ci groupedStructConstants[typeId].push_back(c); 1833617a3babSopenharmony_ci else 1834617a3babSopenharmony_ci groupedConstants[typeClass].push_back(c); 1835617a3babSopenharmony_ci module.mapInstruction(c); 1836617a3babSopenharmony_ci 1837617a3babSopenharmony_ci return c->getResultId(); 1838617a3babSopenharmony_ci} 1839617a3babSopenharmony_ci 1840617a3babSopenharmony_ciInstruction* Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name) 1841617a3babSopenharmony_ci{ 1842617a3babSopenharmony_ci Instruction* entryPoint = new Instruction(OpEntryPoint); 1843617a3babSopenharmony_ci entryPoint->addImmediateOperand(model); 1844617a3babSopenharmony_ci entryPoint->addIdOperand(function->getId()); 1845617a3babSopenharmony_ci entryPoint->addStringOperand(name); 1846617a3babSopenharmony_ci 1847617a3babSopenharmony_ci entryPoints.push_back(std::unique_ptr<Instruction>(entryPoint)); 1848617a3babSopenharmony_ci 1849617a3babSopenharmony_ci return entryPoint; 1850617a3babSopenharmony_ci} 1851617a3babSopenharmony_ci 1852617a3babSopenharmony_ci// Currently relying on the fact that all 'value' of interest are small non-negative values. 1853617a3babSopenharmony_civoid Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2, int value3) 1854617a3babSopenharmony_ci{ 1855617a3babSopenharmony_ci // entryPoint can be null if we are in compile-only mode 1856617a3babSopenharmony_ci if (!entryPoint) 1857617a3babSopenharmony_ci return; 1858617a3babSopenharmony_ci 1859617a3babSopenharmony_ci Instruction* instr = new Instruction(OpExecutionMode); 1860617a3babSopenharmony_ci instr->addIdOperand(entryPoint->getId()); 1861617a3babSopenharmony_ci instr->addImmediateOperand(mode); 1862617a3babSopenharmony_ci if (value1 >= 0) 1863617a3babSopenharmony_ci instr->addImmediateOperand(value1); 1864617a3babSopenharmony_ci if (value2 >= 0) 1865617a3babSopenharmony_ci instr->addImmediateOperand(value2); 1866617a3babSopenharmony_ci if (value3 >= 0) 1867617a3babSopenharmony_ci instr->addImmediateOperand(value3); 1868617a3babSopenharmony_ci 1869617a3babSopenharmony_ci executionModes.push_back(std::unique_ptr<Instruction>(instr)); 1870617a3babSopenharmony_ci} 1871617a3babSopenharmony_ci 1872617a3babSopenharmony_civoid Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, const std::vector<unsigned>& literals) 1873617a3babSopenharmony_ci{ 1874617a3babSopenharmony_ci // entryPoint can be null if we are in compile-only mode 1875617a3babSopenharmony_ci if (!entryPoint) 1876617a3babSopenharmony_ci return; 1877617a3babSopenharmony_ci 1878617a3babSopenharmony_ci Instruction* instr = new Instruction(OpExecutionMode); 1879617a3babSopenharmony_ci instr->addIdOperand(entryPoint->getId()); 1880617a3babSopenharmony_ci instr->addImmediateOperand(mode); 1881617a3babSopenharmony_ci for (auto literal : literals) 1882617a3babSopenharmony_ci instr->addImmediateOperand(literal); 1883617a3babSopenharmony_ci 1884617a3babSopenharmony_ci executionModes.push_back(std::unique_ptr<Instruction>(instr)); 1885617a3babSopenharmony_ci} 1886617a3babSopenharmony_ci 1887617a3babSopenharmony_civoid Builder::addExecutionModeId(Function* entryPoint, ExecutionMode mode, const std::vector<Id>& operandIds) 1888617a3babSopenharmony_ci{ 1889617a3babSopenharmony_ci // entryPoint can be null if we are in compile-only mode 1890617a3babSopenharmony_ci if (!entryPoint) 1891617a3babSopenharmony_ci return; 1892617a3babSopenharmony_ci 1893617a3babSopenharmony_ci Instruction* instr = new Instruction(OpExecutionModeId); 1894617a3babSopenharmony_ci instr->addIdOperand(entryPoint->getId()); 1895617a3babSopenharmony_ci instr->addImmediateOperand(mode); 1896617a3babSopenharmony_ci for (auto operandId : operandIds) 1897617a3babSopenharmony_ci instr->addIdOperand(operandId); 1898617a3babSopenharmony_ci 1899617a3babSopenharmony_ci executionModes.push_back(std::unique_ptr<Instruction>(instr)); 1900617a3babSopenharmony_ci} 1901617a3babSopenharmony_ci 1902617a3babSopenharmony_civoid Builder::addName(Id id, const char* string) 1903617a3babSopenharmony_ci{ 1904617a3babSopenharmony_ci Instruction* name = new Instruction(OpName); 1905617a3babSopenharmony_ci name->addIdOperand(id); 1906617a3babSopenharmony_ci name->addStringOperand(string); 1907617a3babSopenharmony_ci 1908617a3babSopenharmony_ci names.push_back(std::unique_ptr<Instruction>(name)); 1909617a3babSopenharmony_ci} 1910617a3babSopenharmony_ci 1911617a3babSopenharmony_civoid Builder::addMemberName(Id id, int memberNumber, const char* string) 1912617a3babSopenharmony_ci{ 1913617a3babSopenharmony_ci Instruction* name = new Instruction(OpMemberName); 1914617a3babSopenharmony_ci name->addIdOperand(id); 1915617a3babSopenharmony_ci name->addImmediateOperand(memberNumber); 1916617a3babSopenharmony_ci name->addStringOperand(string); 1917617a3babSopenharmony_ci 1918617a3babSopenharmony_ci names.push_back(std::unique_ptr<Instruction>(name)); 1919617a3babSopenharmony_ci} 1920617a3babSopenharmony_ci 1921617a3babSopenharmony_civoid Builder::addDecoration(Id id, Decoration decoration, int num) 1922617a3babSopenharmony_ci{ 1923617a3babSopenharmony_ci if (decoration == spv::DecorationMax) 1924617a3babSopenharmony_ci return; 1925617a3babSopenharmony_ci 1926617a3babSopenharmony_ci Instruction* dec = new Instruction(OpDecorate); 1927617a3babSopenharmony_ci dec->addIdOperand(id); 1928617a3babSopenharmony_ci dec->addImmediateOperand(decoration); 1929617a3babSopenharmony_ci if (num >= 0) 1930617a3babSopenharmony_ci dec->addImmediateOperand(num); 1931617a3babSopenharmony_ci 1932617a3babSopenharmony_ci decorations.push_back(std::unique_ptr<Instruction>(dec)); 1933617a3babSopenharmony_ci} 1934617a3babSopenharmony_ci 1935617a3babSopenharmony_civoid Builder::addDecoration(Id id, Decoration decoration, const char* s) 1936617a3babSopenharmony_ci{ 1937617a3babSopenharmony_ci if (decoration == spv::DecorationMax) 1938617a3babSopenharmony_ci return; 1939617a3babSopenharmony_ci 1940617a3babSopenharmony_ci Instruction* dec = new Instruction(OpDecorateString); 1941617a3babSopenharmony_ci dec->addIdOperand(id); 1942617a3babSopenharmony_ci dec->addImmediateOperand(decoration); 1943617a3babSopenharmony_ci dec->addStringOperand(s); 1944617a3babSopenharmony_ci 1945617a3babSopenharmony_ci decorations.push_back(std::unique_ptr<Instruction>(dec)); 1946617a3babSopenharmony_ci} 1947617a3babSopenharmony_ci 1948617a3babSopenharmony_civoid Builder::addDecoration(Id id, Decoration decoration, const std::vector<unsigned>& literals) 1949617a3babSopenharmony_ci{ 1950617a3babSopenharmony_ci if (decoration == spv::DecorationMax) 1951617a3babSopenharmony_ci return; 1952617a3babSopenharmony_ci 1953617a3babSopenharmony_ci Instruction* dec = new Instruction(OpDecorate); 1954617a3babSopenharmony_ci dec->addIdOperand(id); 1955617a3babSopenharmony_ci dec->addImmediateOperand(decoration); 1956617a3babSopenharmony_ci for (auto literal : literals) 1957617a3babSopenharmony_ci dec->addImmediateOperand(literal); 1958617a3babSopenharmony_ci 1959617a3babSopenharmony_ci decorations.push_back(std::unique_ptr<Instruction>(dec)); 1960617a3babSopenharmony_ci} 1961617a3babSopenharmony_ci 1962617a3babSopenharmony_civoid Builder::addDecoration(Id id, Decoration decoration, const std::vector<const char*>& strings) 1963617a3babSopenharmony_ci{ 1964617a3babSopenharmony_ci if (decoration == spv::DecorationMax) 1965617a3babSopenharmony_ci return; 1966617a3babSopenharmony_ci 1967617a3babSopenharmony_ci Instruction* dec = new Instruction(OpDecorateString); 1968617a3babSopenharmony_ci dec->addIdOperand(id); 1969617a3babSopenharmony_ci dec->addImmediateOperand(decoration); 1970617a3babSopenharmony_ci for (auto string : strings) 1971617a3babSopenharmony_ci dec->addStringOperand(string); 1972617a3babSopenharmony_ci 1973617a3babSopenharmony_ci decorations.push_back(std::unique_ptr<Instruction>(dec)); 1974617a3babSopenharmony_ci} 1975617a3babSopenharmony_ci 1976617a3babSopenharmony_civoid Builder::addLinkageDecoration(Id id, const char* name, spv::LinkageType linkType) { 1977617a3babSopenharmony_ci Instruction* dec = new Instruction(OpDecorate); 1978617a3babSopenharmony_ci dec->addIdOperand(id); 1979617a3babSopenharmony_ci dec->addImmediateOperand(spv::DecorationLinkageAttributes); 1980617a3babSopenharmony_ci dec->addStringOperand(name); 1981617a3babSopenharmony_ci dec->addImmediateOperand(linkType); 1982617a3babSopenharmony_ci 1983617a3babSopenharmony_ci decorations.push_back(std::unique_ptr<Instruction>(dec)); 1984617a3babSopenharmony_ci} 1985617a3babSopenharmony_ci 1986617a3babSopenharmony_civoid Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration) 1987617a3babSopenharmony_ci{ 1988617a3babSopenharmony_ci if (decoration == spv::DecorationMax) 1989617a3babSopenharmony_ci return; 1990617a3babSopenharmony_ci 1991617a3babSopenharmony_ci Instruction* dec = new Instruction(OpDecorateId); 1992617a3babSopenharmony_ci dec->addIdOperand(id); 1993617a3babSopenharmony_ci dec->addImmediateOperand(decoration); 1994617a3babSopenharmony_ci dec->addIdOperand(idDecoration); 1995617a3babSopenharmony_ci 1996617a3babSopenharmony_ci decorations.push_back(std::unique_ptr<Instruction>(dec)); 1997617a3babSopenharmony_ci} 1998617a3babSopenharmony_ci 1999617a3babSopenharmony_civoid Builder::addDecorationId(Id id, Decoration decoration, const std::vector<Id>& operandIds) 2000617a3babSopenharmony_ci{ 2001617a3babSopenharmony_ci if(decoration == spv::DecorationMax) 2002617a3babSopenharmony_ci return; 2003617a3babSopenharmony_ci 2004617a3babSopenharmony_ci Instruction* dec = new Instruction(OpDecorateId); 2005617a3babSopenharmony_ci dec->addIdOperand(id); 2006617a3babSopenharmony_ci dec->addImmediateOperand(decoration); 2007617a3babSopenharmony_ci 2008617a3babSopenharmony_ci for (auto operandId : operandIds) 2009617a3babSopenharmony_ci dec->addIdOperand(operandId); 2010617a3babSopenharmony_ci 2011617a3babSopenharmony_ci decorations.push_back(std::unique_ptr<Instruction>(dec)); 2012617a3babSopenharmony_ci} 2013617a3babSopenharmony_ci 2014617a3babSopenharmony_civoid Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num) 2015617a3babSopenharmony_ci{ 2016617a3babSopenharmony_ci if (decoration == spv::DecorationMax) 2017617a3babSopenharmony_ci return; 2018617a3babSopenharmony_ci 2019617a3babSopenharmony_ci Instruction* dec = new Instruction(OpMemberDecorate); 2020617a3babSopenharmony_ci dec->addIdOperand(id); 2021617a3babSopenharmony_ci dec->addImmediateOperand(member); 2022617a3babSopenharmony_ci dec->addImmediateOperand(decoration); 2023617a3babSopenharmony_ci if (num >= 0) 2024617a3babSopenharmony_ci dec->addImmediateOperand(num); 2025617a3babSopenharmony_ci 2026617a3babSopenharmony_ci decorations.push_back(std::unique_ptr<Instruction>(dec)); 2027617a3babSopenharmony_ci} 2028617a3babSopenharmony_ci 2029617a3babSopenharmony_civoid Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const char *s) 2030617a3babSopenharmony_ci{ 2031617a3babSopenharmony_ci if (decoration == spv::DecorationMax) 2032617a3babSopenharmony_ci return; 2033617a3babSopenharmony_ci 2034617a3babSopenharmony_ci Instruction* dec = new Instruction(OpMemberDecorateStringGOOGLE); 2035617a3babSopenharmony_ci dec->addIdOperand(id); 2036617a3babSopenharmony_ci dec->addImmediateOperand(member); 2037617a3babSopenharmony_ci dec->addImmediateOperand(decoration); 2038617a3babSopenharmony_ci dec->addStringOperand(s); 2039617a3babSopenharmony_ci 2040617a3babSopenharmony_ci decorations.push_back(std::unique_ptr<Instruction>(dec)); 2041617a3babSopenharmony_ci} 2042617a3babSopenharmony_ci 2043617a3babSopenharmony_civoid Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<unsigned>& literals) 2044617a3babSopenharmony_ci{ 2045617a3babSopenharmony_ci if (decoration == spv::DecorationMax) 2046617a3babSopenharmony_ci return; 2047617a3babSopenharmony_ci 2048617a3babSopenharmony_ci Instruction* dec = new Instruction(OpMemberDecorate); 2049617a3babSopenharmony_ci dec->addIdOperand(id); 2050617a3babSopenharmony_ci dec->addImmediateOperand(member); 2051617a3babSopenharmony_ci dec->addImmediateOperand(decoration); 2052617a3babSopenharmony_ci for (auto literal : literals) 2053617a3babSopenharmony_ci dec->addImmediateOperand(literal); 2054617a3babSopenharmony_ci 2055617a3babSopenharmony_ci decorations.push_back(std::unique_ptr<Instruction>(dec)); 2056617a3babSopenharmony_ci} 2057617a3babSopenharmony_ci 2058617a3babSopenharmony_civoid Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<const char*>& strings) 2059617a3babSopenharmony_ci{ 2060617a3babSopenharmony_ci if (decoration == spv::DecorationMax) 2061617a3babSopenharmony_ci return; 2062617a3babSopenharmony_ci 2063617a3babSopenharmony_ci Instruction* dec = new Instruction(OpMemberDecorateString); 2064617a3babSopenharmony_ci dec->addIdOperand(id); 2065617a3babSopenharmony_ci dec->addImmediateOperand(member); 2066617a3babSopenharmony_ci dec->addImmediateOperand(decoration); 2067617a3babSopenharmony_ci for (auto string : strings) 2068617a3babSopenharmony_ci dec->addStringOperand(string); 2069617a3babSopenharmony_ci 2070617a3babSopenharmony_ci decorations.push_back(std::unique_ptr<Instruction>(dec)); 2071617a3babSopenharmony_ci} 2072617a3babSopenharmony_ci 2073617a3babSopenharmony_ci// Comments in header 2074617a3babSopenharmony_ciFunction* Builder::makeEntryPoint(const char* entryPoint) 2075617a3babSopenharmony_ci{ 2076617a3babSopenharmony_ci assert(! entryPointFunction); 2077617a3babSopenharmony_ci 2078617a3babSopenharmony_ci auto const returnType = makeVoidType(); 2079617a3babSopenharmony_ci 2080617a3babSopenharmony_ci restoreNonSemanticShaderDebugInfo = emitNonSemanticShaderDebugInfo; 2081617a3babSopenharmony_ci if(sourceLang == spv::SourceLanguageHLSL) { 2082617a3babSopenharmony_ci emitNonSemanticShaderDebugInfo = false; 2083617a3babSopenharmony_ci } 2084617a3babSopenharmony_ci 2085617a3babSopenharmony_ci Block* entry = nullptr; 2086617a3babSopenharmony_ci entryPointFunction = makeFunctionEntry(NoPrecision, returnType, entryPoint, LinkageTypeMax, {}, {}, &entry); 2087617a3babSopenharmony_ci 2088617a3babSopenharmony_ci emitNonSemanticShaderDebugInfo = restoreNonSemanticShaderDebugInfo; 2089617a3babSopenharmony_ci 2090617a3babSopenharmony_ci return entryPointFunction; 2091617a3babSopenharmony_ci} 2092617a3babSopenharmony_ci 2093617a3babSopenharmony_ci// Comments in header 2094617a3babSopenharmony_ciFunction* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, LinkageType linkType, 2095617a3babSopenharmony_ci const std::vector<Id>& paramTypes, 2096617a3babSopenharmony_ci const std::vector<std::vector<Decoration>>& decorations, Block** entry) 2097617a3babSopenharmony_ci{ 2098617a3babSopenharmony_ci // Make the function and initial instructions in it 2099617a3babSopenharmony_ci Id typeId = makeFunctionType(returnType, paramTypes); 2100617a3babSopenharmony_ci Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size()); 2101617a3babSopenharmony_ci Id funcId = getUniqueId(); 2102617a3babSopenharmony_ci Function* function = new Function(funcId, returnType, typeId, firstParamId, linkType, name, module); 2103617a3babSopenharmony_ci 2104617a3babSopenharmony_ci // Set up the precisions 2105617a3babSopenharmony_ci setPrecision(function->getId(), precision); 2106617a3babSopenharmony_ci function->setReturnPrecision(precision); 2107617a3babSopenharmony_ci for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) { 2108617a3babSopenharmony_ci for (int d = 0; d < (int)decorations[p].size(); ++d) { 2109617a3babSopenharmony_ci addDecoration(firstParamId + p, decorations[p][d]); 2110617a3babSopenharmony_ci function->addParamPrecision(p, decorations[p][d]); 2111617a3babSopenharmony_ci } 2112617a3babSopenharmony_ci } 2113617a3babSopenharmony_ci 2114617a3babSopenharmony_ci // reset last debug scope 2115617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) { 2116617a3babSopenharmony_ci lastDebugScopeId = NoResult; 2117617a3babSopenharmony_ci } 2118617a3babSopenharmony_ci 2119617a3babSopenharmony_ci // CFG 2120617a3babSopenharmony_ci assert(entry != nullptr); 2121617a3babSopenharmony_ci *entry = new Block(getUniqueId(), *function); 2122617a3babSopenharmony_ci function->addBlock(*entry); 2123617a3babSopenharmony_ci setBuildPoint(*entry); 2124617a3babSopenharmony_ci 2125617a3babSopenharmony_ci if (name) 2126617a3babSopenharmony_ci addName(function->getId(), name); 2127617a3babSopenharmony_ci 2128617a3babSopenharmony_ci functions.push_back(std::unique_ptr<Function>(function)); 2129617a3babSopenharmony_ci 2130617a3babSopenharmony_ci return function; 2131617a3babSopenharmony_ci} 2132617a3babSopenharmony_ci 2133617a3babSopenharmony_civoid Builder::setupDebugFunctionEntry(Function* function, const char* name, int line, const std::vector<Id>& paramTypes, 2134617a3babSopenharmony_ci const std::vector<char const*>& paramNames) 2135617a3babSopenharmony_ci{ 2136617a3babSopenharmony_ci 2137617a3babSopenharmony_ci if (!emitNonSemanticShaderDebugInfo) 2138617a3babSopenharmony_ci return; 2139617a3babSopenharmony_ci 2140617a3babSopenharmony_ci currentLine = line; 2141617a3babSopenharmony_ci Id nameId = getStringId(unmangleFunctionName(name)); 2142617a3babSopenharmony_ci Id funcTypeId = function->getFuncTypeId(); 2143617a3babSopenharmony_ci assert(debugId[funcTypeId] != 0); 2144617a3babSopenharmony_ci Id funcId = function->getId(); 2145617a3babSopenharmony_ci 2146617a3babSopenharmony_ci assert(funcId != 0); 2147617a3babSopenharmony_ci 2148617a3babSopenharmony_ci // Make the debug function instruction 2149617a3babSopenharmony_ci Id debugFuncId = makeDebugFunction(function, nameId, funcTypeId); 2150617a3babSopenharmony_ci debugId[funcId] = debugFuncId; 2151617a3babSopenharmony_ci currentDebugScopeId.push(debugFuncId); 2152617a3babSopenharmony_ci 2153617a3babSopenharmony_ci // DebugScope and DebugLine for parameter DebugDeclares 2154617a3babSopenharmony_ci assert(paramTypes.size() == paramNames.size()); 2155617a3babSopenharmony_ci if ((int)paramTypes.size() > 0) { 2156617a3babSopenharmony_ci addDebugScopeAndLine(currentFileId, currentLine, 0); 2157617a3babSopenharmony_ci 2158617a3babSopenharmony_ci Id firstParamId = function->getParamId(0); 2159617a3babSopenharmony_ci 2160617a3babSopenharmony_ci for (size_t p = 0; p < paramTypes.size(); ++p) { 2161617a3babSopenharmony_ci bool passByRef = false; 2162617a3babSopenharmony_ci Id paramTypeId = paramTypes[p]; 2163617a3babSopenharmony_ci 2164617a3babSopenharmony_ci // For pointer-typed parameters, they are actually passed by reference and we need unwrap the pointer to get the actual parameter type. 2165617a3babSopenharmony_ci if (isPointerType(paramTypeId) || isArrayType(paramTypeId)) { 2166617a3babSopenharmony_ci passByRef = true; 2167617a3babSopenharmony_ci paramTypeId = getContainedTypeId(paramTypeId); 2168617a3babSopenharmony_ci } 2169617a3babSopenharmony_ci 2170617a3babSopenharmony_ci auto const& paramName = paramNames[p]; 2171617a3babSopenharmony_ci auto const debugLocalVariableId = createDebugLocalVariable(debugId[paramTypeId], paramName, p + 1); 2172617a3babSopenharmony_ci auto const paramId = static_cast<Id>(firstParamId + p); 2173617a3babSopenharmony_ci debugId[paramId] = debugLocalVariableId; 2174617a3babSopenharmony_ci 2175617a3babSopenharmony_ci if (passByRef) { 2176617a3babSopenharmony_ci makeDebugDeclare(debugLocalVariableId, paramId); 2177617a3babSopenharmony_ci } else { 2178617a3babSopenharmony_ci makeDebugValue(debugLocalVariableId, paramId); 2179617a3babSopenharmony_ci } 2180617a3babSopenharmony_ci } 2181617a3babSopenharmony_ci } 2182617a3babSopenharmony_ci 2183617a3babSopenharmony_ci // Clear debug scope stack 2184617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 2185617a3babSopenharmony_ci currentDebugScopeId.pop(); 2186617a3babSopenharmony_ci} 2187617a3babSopenharmony_ci 2188617a3babSopenharmony_ciId Builder::makeDebugFunction([[maybe_unused]] Function* function, Id nameId, Id funcTypeId) 2189617a3babSopenharmony_ci{ 2190617a3babSopenharmony_ci assert(function != nullptr); 2191617a3babSopenharmony_ci assert(nameId != 0); 2192617a3babSopenharmony_ci assert(funcTypeId != 0); 2193617a3babSopenharmony_ci assert(debugId[funcTypeId] != 0); 2194617a3babSopenharmony_ci 2195617a3babSopenharmony_ci Id funcId = getUniqueId(); 2196617a3babSopenharmony_ci auto type = new Instruction(funcId, makeVoidType(), OpExtInst); 2197617a3babSopenharmony_ci type->addIdOperand(nonSemanticShaderDebugInfo); 2198617a3babSopenharmony_ci type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunction); 2199617a3babSopenharmony_ci type->addIdOperand(nameId); 2200617a3babSopenharmony_ci type->addIdOperand(debugId[funcTypeId]); 2201617a3babSopenharmony_ci type->addIdOperand(makeDebugSource(currentFileId)); // TODO: This points to file of definition instead of declaration 2202617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(currentLine)); // TODO: This points to line of definition instead of declaration 2203617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(0)); // column 2204617a3babSopenharmony_ci type->addIdOperand(makeDebugCompilationUnit()); // scope 2205617a3babSopenharmony_ci type->addIdOperand(nameId); // linkage name 2206617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); 2207617a3babSopenharmony_ci type->addIdOperand(makeUintConstant(currentLine)); 2208617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); 2209617a3babSopenharmony_ci module.mapInstruction(type); 2210617a3babSopenharmony_ci return funcId; 2211617a3babSopenharmony_ci} 2212617a3babSopenharmony_ci 2213617a3babSopenharmony_ciId Builder::makeDebugLexicalBlock(uint32_t line) { 2214617a3babSopenharmony_ci assert(!currentDebugScopeId.empty()); 2215617a3babSopenharmony_ci 2216617a3babSopenharmony_ci Id lexId = getUniqueId(); 2217617a3babSopenharmony_ci auto lex = new Instruction(lexId, makeVoidType(), OpExtInst); 2218617a3babSopenharmony_ci lex->addIdOperand(nonSemanticShaderDebugInfo); 2219617a3babSopenharmony_ci lex->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLexicalBlock); 2220617a3babSopenharmony_ci lex->addIdOperand(makeDebugSource(currentFileId)); 2221617a3babSopenharmony_ci lex->addIdOperand(makeUintConstant(line)); 2222617a3babSopenharmony_ci lex->addIdOperand(makeUintConstant(0)); // column 2223617a3babSopenharmony_ci lex->addIdOperand(currentDebugScopeId.top()); // scope 2224617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(lex)); 2225617a3babSopenharmony_ci module.mapInstruction(lex); 2226617a3babSopenharmony_ci return lexId; 2227617a3babSopenharmony_ci} 2228617a3babSopenharmony_ci 2229617a3babSopenharmony_cistd::string Builder::unmangleFunctionName(std::string const& name) const 2230617a3babSopenharmony_ci{ 2231617a3babSopenharmony_ci assert(name.length() > 0); 2232617a3babSopenharmony_ci 2233617a3babSopenharmony_ci if(name.rfind('(') != std::string::npos) { 2234617a3babSopenharmony_ci return name.substr(0, name.rfind('(')); 2235617a3babSopenharmony_ci } else { 2236617a3babSopenharmony_ci return name; 2237617a3babSopenharmony_ci } 2238617a3babSopenharmony_ci} 2239617a3babSopenharmony_ci 2240617a3babSopenharmony_ci// Comments in header 2241617a3babSopenharmony_civoid Builder::makeReturn(bool implicit, Id retVal) 2242617a3babSopenharmony_ci{ 2243617a3babSopenharmony_ci if (retVal) { 2244617a3babSopenharmony_ci Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue); 2245617a3babSopenharmony_ci inst->addIdOperand(retVal); 2246617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(inst)); 2247617a3babSopenharmony_ci } else 2248617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(NoResult, NoType, OpReturn))); 2249617a3babSopenharmony_ci 2250617a3babSopenharmony_ci if (! implicit) 2251617a3babSopenharmony_ci createAndSetNoPredecessorBlock("post-return"); 2252617a3babSopenharmony_ci} 2253617a3babSopenharmony_ci 2254617a3babSopenharmony_ci// Comments in header 2255617a3babSopenharmony_civoid Builder::enterScope(uint32_t line) 2256617a3babSopenharmony_ci{ 2257617a3babSopenharmony_ci // Generate new lexical scope debug instruction 2258617a3babSopenharmony_ci Id lexId = makeDebugLexicalBlock(line); 2259617a3babSopenharmony_ci currentDebugScopeId.push(lexId); 2260617a3babSopenharmony_ci lastDebugScopeId = NoResult; 2261617a3babSopenharmony_ci} 2262617a3babSopenharmony_ci 2263617a3babSopenharmony_ci// Comments in header 2264617a3babSopenharmony_civoid Builder::leaveScope() 2265617a3babSopenharmony_ci{ 2266617a3babSopenharmony_ci // Pop current scope from stack and clear current scope 2267617a3babSopenharmony_ci currentDebugScopeId.pop(); 2268617a3babSopenharmony_ci lastDebugScopeId = NoResult; 2269617a3babSopenharmony_ci} 2270617a3babSopenharmony_ci 2271617a3babSopenharmony_ci// Comments in header 2272617a3babSopenharmony_civoid Builder::enterFunction(Function const* function) 2273617a3babSopenharmony_ci{ 2274617a3babSopenharmony_ci // Save and disable debugInfo for HLSL entry point function. It is a wrapper 2275617a3babSopenharmony_ci // function with no user code in it. 2276617a3babSopenharmony_ci restoreNonSemanticShaderDebugInfo = emitNonSemanticShaderDebugInfo; 2277617a3babSopenharmony_ci if (sourceLang == spv::SourceLanguageHLSL && function == entryPointFunction) { 2278617a3babSopenharmony_ci emitNonSemanticShaderDebugInfo = false; 2279617a3babSopenharmony_ci } 2280617a3babSopenharmony_ci 2281617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) { 2282617a3babSopenharmony_ci // Initialize scope state 2283617a3babSopenharmony_ci Id funcId = function->getFuncId(); 2284617a3babSopenharmony_ci currentDebugScopeId.push(debugId[funcId]); 2285617a3babSopenharmony_ci // Create DebugFunctionDefinition 2286617a3babSopenharmony_ci spv::Id resultId = getUniqueId(); 2287617a3babSopenharmony_ci Instruction* defInst = new Instruction(resultId, makeVoidType(), OpExtInst); 2288617a3babSopenharmony_ci defInst->addIdOperand(nonSemanticShaderDebugInfo); 2289617a3babSopenharmony_ci defInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunctionDefinition); 2290617a3babSopenharmony_ci defInst->addIdOperand(debugId[funcId]); 2291617a3babSopenharmony_ci defInst->addIdOperand(funcId); 2292617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(defInst)); 2293617a3babSopenharmony_ci } 2294617a3babSopenharmony_ci 2295617a3babSopenharmony_ci if (auto linkType = function->getLinkType(); linkType != LinkageTypeMax) { 2296617a3babSopenharmony_ci Id funcId = function->getFuncId(); 2297617a3babSopenharmony_ci addCapability(CapabilityLinkage); 2298617a3babSopenharmony_ci addLinkageDecoration(funcId, function->getExportName(), linkType); 2299617a3babSopenharmony_ci } 2300617a3babSopenharmony_ci} 2301617a3babSopenharmony_ci 2302617a3babSopenharmony_ci// Comments in header 2303617a3babSopenharmony_civoid Builder::leaveFunction() 2304617a3babSopenharmony_ci{ 2305617a3babSopenharmony_ci Block* block = buildPoint; 2306617a3babSopenharmony_ci Function& function = buildPoint->getParent(); 2307617a3babSopenharmony_ci assert(block); 2308617a3babSopenharmony_ci 2309617a3babSopenharmony_ci // If our function did not contain a return, add a return void now. 2310617a3babSopenharmony_ci if (! block->isTerminated()) { 2311617a3babSopenharmony_ci if (function.getReturnType() == makeVoidType()) 2312617a3babSopenharmony_ci makeReturn(true); 2313617a3babSopenharmony_ci else { 2314617a3babSopenharmony_ci makeReturn(true, createUndefined(function.getReturnType())); 2315617a3babSopenharmony_ci } 2316617a3babSopenharmony_ci } 2317617a3babSopenharmony_ci 2318617a3babSopenharmony_ci // Clear function scope from debug scope stack 2319617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) 2320617a3babSopenharmony_ci currentDebugScopeId.pop(); 2321617a3babSopenharmony_ci 2322617a3babSopenharmony_ci emitNonSemanticShaderDebugInfo = restoreNonSemanticShaderDebugInfo; 2323617a3babSopenharmony_ci} 2324617a3babSopenharmony_ci 2325617a3babSopenharmony_ci// Comments in header 2326617a3babSopenharmony_civoid Builder::makeStatementTerminator(spv::Op opcode, const char *name) 2327617a3babSopenharmony_ci{ 2328617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(opcode))); 2329617a3babSopenharmony_ci createAndSetNoPredecessorBlock(name); 2330617a3babSopenharmony_ci} 2331617a3babSopenharmony_ci 2332617a3babSopenharmony_ci// Comments in header 2333617a3babSopenharmony_civoid Builder::makeStatementTerminator(spv::Op opcode, const std::vector<Id>& operands, const char* name) 2334617a3babSopenharmony_ci{ 2335617a3babSopenharmony_ci // It's assumed that the terminator instruction is always of void return type 2336617a3babSopenharmony_ci // However in future if there is a need for non void return type, new helper 2337617a3babSopenharmony_ci // methods can be created. 2338617a3babSopenharmony_ci createNoResultOp(opcode, operands); 2339617a3babSopenharmony_ci createAndSetNoPredecessorBlock(name); 2340617a3babSopenharmony_ci} 2341617a3babSopenharmony_ci 2342617a3babSopenharmony_ci// Comments in header 2343617a3babSopenharmony_ciId Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer, 2344617a3babSopenharmony_ci bool const compilerGenerated) 2345617a3babSopenharmony_ci{ 2346617a3babSopenharmony_ci Id pointerType = makePointer(storageClass, type); 2347617a3babSopenharmony_ci Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable); 2348617a3babSopenharmony_ci inst->addImmediateOperand(storageClass); 2349617a3babSopenharmony_ci if (initializer != NoResult) 2350617a3babSopenharmony_ci inst->addIdOperand(initializer); 2351617a3babSopenharmony_ci 2352617a3babSopenharmony_ci switch (storageClass) { 2353617a3babSopenharmony_ci case StorageClassFunction: 2354617a3babSopenharmony_ci // Validation rules require the declaration in the entry block 2355617a3babSopenharmony_ci buildPoint->getParent().addLocalVariable(std::unique_ptr<Instruction>(inst)); 2356617a3babSopenharmony_ci 2357617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo && !compilerGenerated) 2358617a3babSopenharmony_ci { 2359617a3babSopenharmony_ci auto const debugLocalVariableId = createDebugLocalVariable(debugId[type], name); 2360617a3babSopenharmony_ci debugId[inst->getResultId()] = debugLocalVariableId; 2361617a3babSopenharmony_ci 2362617a3babSopenharmony_ci makeDebugDeclare(debugLocalVariableId, inst->getResultId()); 2363617a3babSopenharmony_ci } 2364617a3babSopenharmony_ci 2365617a3babSopenharmony_ci break; 2366617a3babSopenharmony_ci 2367617a3babSopenharmony_ci default: 2368617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst)); 2369617a3babSopenharmony_ci module.mapInstruction(inst); 2370617a3babSopenharmony_ci 2371617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo && !isRayTracingOpCode(getOpCode(type))) 2372617a3babSopenharmony_ci { 2373617a3babSopenharmony_ci auto const debugResultId = createDebugGlobalVariable(debugId[type], name, inst->getResultId()); 2374617a3babSopenharmony_ci debugId[inst->getResultId()] = debugResultId; 2375617a3babSopenharmony_ci } 2376617a3babSopenharmony_ci break; 2377617a3babSopenharmony_ci } 2378617a3babSopenharmony_ci 2379617a3babSopenharmony_ci if (name) 2380617a3babSopenharmony_ci addName(inst->getResultId(), name); 2381617a3babSopenharmony_ci setPrecision(inst->getResultId(), precision); 2382617a3babSopenharmony_ci 2383617a3babSopenharmony_ci return inst->getResultId(); 2384617a3babSopenharmony_ci} 2385617a3babSopenharmony_ci 2386617a3babSopenharmony_ci// Comments in header 2387617a3babSopenharmony_ciId Builder::createUndefined(Id type) 2388617a3babSopenharmony_ci{ 2389617a3babSopenharmony_ci Instruction* inst = new Instruction(getUniqueId(), type, OpUndef); 2390617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(inst)); 2391617a3babSopenharmony_ci return inst->getResultId(); 2392617a3babSopenharmony_ci} 2393617a3babSopenharmony_ci 2394617a3babSopenharmony_ci// av/vis/nonprivate are unnecessary and illegal for some storage classes. 2395617a3babSopenharmony_cispv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) 2396617a3babSopenharmony_ci const 2397617a3babSopenharmony_ci{ 2398617a3babSopenharmony_ci switch (sc) { 2399617a3babSopenharmony_ci case spv::StorageClassUniform: 2400617a3babSopenharmony_ci case spv::StorageClassWorkgroup: 2401617a3babSopenharmony_ci case spv::StorageClassStorageBuffer: 2402617a3babSopenharmony_ci case spv::StorageClassPhysicalStorageBufferEXT: 2403617a3babSopenharmony_ci break; 2404617a3babSopenharmony_ci default: 2405617a3babSopenharmony_ci memoryAccess = spv::MemoryAccessMask(memoryAccess & 2406617a3babSopenharmony_ci ~(spv::MemoryAccessMakePointerAvailableKHRMask | 2407617a3babSopenharmony_ci spv::MemoryAccessMakePointerVisibleKHRMask | 2408617a3babSopenharmony_ci spv::MemoryAccessNonPrivatePointerKHRMask)); 2409617a3babSopenharmony_ci break; 2410617a3babSopenharmony_ci } 2411617a3babSopenharmony_ci return memoryAccess; 2412617a3babSopenharmony_ci} 2413617a3babSopenharmony_ci 2414617a3babSopenharmony_ci// Comments in header 2415617a3babSopenharmony_civoid Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, 2416617a3babSopenharmony_ci unsigned int alignment) 2417617a3babSopenharmony_ci{ 2418617a3babSopenharmony_ci Instruction* store = new Instruction(OpStore); 2419617a3babSopenharmony_ci store->addIdOperand(lValue); 2420617a3babSopenharmony_ci store->addIdOperand(rValue); 2421617a3babSopenharmony_ci 2422617a3babSopenharmony_ci memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue)); 2423617a3babSopenharmony_ci 2424617a3babSopenharmony_ci if (memoryAccess != MemoryAccessMaskNone) { 2425617a3babSopenharmony_ci store->addImmediateOperand(memoryAccess); 2426617a3babSopenharmony_ci if (memoryAccess & spv::MemoryAccessAlignedMask) { 2427617a3babSopenharmony_ci store->addImmediateOperand(alignment); 2428617a3babSopenharmony_ci } 2429617a3babSopenharmony_ci if (memoryAccess & spv::MemoryAccessMakePointerAvailableKHRMask) { 2430617a3babSopenharmony_ci store->addIdOperand(makeUintConstant(scope)); 2431617a3babSopenharmony_ci } 2432617a3babSopenharmony_ci } 2433617a3babSopenharmony_ci 2434617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(store)); 2435617a3babSopenharmony_ci} 2436617a3babSopenharmony_ci 2437617a3babSopenharmony_ci// Comments in header 2438617a3babSopenharmony_ciId Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMask memoryAccess, 2439617a3babSopenharmony_ci spv::Scope scope, unsigned int alignment) 2440617a3babSopenharmony_ci{ 2441617a3babSopenharmony_ci Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad); 2442617a3babSopenharmony_ci load->addIdOperand(lValue); 2443617a3babSopenharmony_ci 2444617a3babSopenharmony_ci memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue)); 2445617a3babSopenharmony_ci 2446617a3babSopenharmony_ci if (memoryAccess != MemoryAccessMaskNone) { 2447617a3babSopenharmony_ci load->addImmediateOperand(memoryAccess); 2448617a3babSopenharmony_ci if (memoryAccess & spv::MemoryAccessAlignedMask) { 2449617a3babSopenharmony_ci load->addImmediateOperand(alignment); 2450617a3babSopenharmony_ci } 2451617a3babSopenharmony_ci if (memoryAccess & spv::MemoryAccessMakePointerVisibleKHRMask) { 2452617a3babSopenharmony_ci load->addIdOperand(makeUintConstant(scope)); 2453617a3babSopenharmony_ci } 2454617a3babSopenharmony_ci } 2455617a3babSopenharmony_ci 2456617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(load)); 2457617a3babSopenharmony_ci setPrecision(load->getResultId(), precision); 2458617a3babSopenharmony_ci 2459617a3babSopenharmony_ci return load->getResultId(); 2460617a3babSopenharmony_ci} 2461617a3babSopenharmony_ci 2462617a3babSopenharmony_ci// Comments in header 2463617a3babSopenharmony_ciId Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector<Id>& offsets) 2464617a3babSopenharmony_ci{ 2465617a3babSopenharmony_ci // Figure out the final resulting type. 2466617a3babSopenharmony_ci Id typeId = getResultingAccessChainType(); 2467617a3babSopenharmony_ci typeId = makePointer(storageClass, typeId); 2468617a3babSopenharmony_ci 2469617a3babSopenharmony_ci // Make the instruction 2470617a3babSopenharmony_ci Instruction* chain = new Instruction(getUniqueId(), typeId, OpAccessChain); 2471617a3babSopenharmony_ci chain->addIdOperand(base); 2472617a3babSopenharmony_ci for (int i = 0; i < (int)offsets.size(); ++i) 2473617a3babSopenharmony_ci chain->addIdOperand(offsets[i]); 2474617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(chain)); 2475617a3babSopenharmony_ci 2476617a3babSopenharmony_ci return chain->getResultId(); 2477617a3babSopenharmony_ci} 2478617a3babSopenharmony_ci 2479617a3babSopenharmony_ciId Builder::createArrayLength(Id base, unsigned int member) 2480617a3babSopenharmony_ci{ 2481617a3babSopenharmony_ci spv::Id intType = makeUintType(32); 2482617a3babSopenharmony_ci Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength); 2483617a3babSopenharmony_ci length->addIdOperand(base); 2484617a3babSopenharmony_ci length->addImmediateOperand(member); 2485617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(length)); 2486617a3babSopenharmony_ci 2487617a3babSopenharmony_ci return length->getResultId(); 2488617a3babSopenharmony_ci} 2489617a3babSopenharmony_ci 2490617a3babSopenharmony_ciId Builder::createCooperativeMatrixLengthKHR(Id type) 2491617a3babSopenharmony_ci{ 2492617a3babSopenharmony_ci spv::Id intType = makeUintType(32); 2493617a3babSopenharmony_ci 2494617a3babSopenharmony_ci // Generate code for spec constants if in spec constant operation 2495617a3babSopenharmony_ci // generation mode. 2496617a3babSopenharmony_ci if (generatingOpCodeForSpecConst) { 2497617a3babSopenharmony_ci return createSpecConstantOp(OpCooperativeMatrixLengthKHR, intType, std::vector<Id>(1, type), std::vector<Id>()); 2498617a3babSopenharmony_ci } 2499617a3babSopenharmony_ci 2500617a3babSopenharmony_ci Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthKHR); 2501617a3babSopenharmony_ci length->addIdOperand(type); 2502617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(length)); 2503617a3babSopenharmony_ci 2504617a3babSopenharmony_ci return length->getResultId(); 2505617a3babSopenharmony_ci} 2506617a3babSopenharmony_ci 2507617a3babSopenharmony_ciId Builder::createCooperativeMatrixLengthNV(Id type) 2508617a3babSopenharmony_ci{ 2509617a3babSopenharmony_ci spv::Id intType = makeUintType(32); 2510617a3babSopenharmony_ci 2511617a3babSopenharmony_ci // Generate code for spec constants if in spec constant operation 2512617a3babSopenharmony_ci // generation mode. 2513617a3babSopenharmony_ci if (generatingOpCodeForSpecConst) { 2514617a3babSopenharmony_ci return createSpecConstantOp(OpCooperativeMatrixLengthNV, intType, std::vector<Id>(1, type), std::vector<Id>()); 2515617a3babSopenharmony_ci } 2516617a3babSopenharmony_ci 2517617a3babSopenharmony_ci Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthNV); 2518617a3babSopenharmony_ci length->addIdOperand(type); 2519617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(length)); 2520617a3babSopenharmony_ci 2521617a3babSopenharmony_ci return length->getResultId(); 2522617a3babSopenharmony_ci} 2523617a3babSopenharmony_ci 2524617a3babSopenharmony_ciId Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) 2525617a3babSopenharmony_ci{ 2526617a3babSopenharmony_ci // Generate code for spec constants if in spec constant operation 2527617a3babSopenharmony_ci // generation mode. 2528617a3babSopenharmony_ci if (generatingOpCodeForSpecConst) { 2529617a3babSopenharmony_ci return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), 2530617a3babSopenharmony_ci std::vector<Id>(1, index)); 2531617a3babSopenharmony_ci } 2532617a3babSopenharmony_ci Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); 2533617a3babSopenharmony_ci extract->addIdOperand(composite); 2534617a3babSopenharmony_ci extract->addImmediateOperand(index); 2535617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(extract)); 2536617a3babSopenharmony_ci 2537617a3babSopenharmony_ci return extract->getResultId(); 2538617a3babSopenharmony_ci} 2539617a3babSopenharmony_ci 2540617a3babSopenharmony_ciId Builder::createCompositeExtract(Id composite, Id typeId, const std::vector<unsigned>& indexes) 2541617a3babSopenharmony_ci{ 2542617a3babSopenharmony_ci // Generate code for spec constants if in spec constant operation 2543617a3babSopenharmony_ci // generation mode. 2544617a3babSopenharmony_ci if (generatingOpCodeForSpecConst) { 2545617a3babSopenharmony_ci return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), indexes); 2546617a3babSopenharmony_ci } 2547617a3babSopenharmony_ci Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); 2548617a3babSopenharmony_ci extract->addIdOperand(composite); 2549617a3babSopenharmony_ci for (int i = 0; i < (int)indexes.size(); ++i) 2550617a3babSopenharmony_ci extract->addImmediateOperand(indexes[i]); 2551617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(extract)); 2552617a3babSopenharmony_ci 2553617a3babSopenharmony_ci return extract->getResultId(); 2554617a3babSopenharmony_ci} 2555617a3babSopenharmony_ci 2556617a3babSopenharmony_ciId Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned index) 2557617a3babSopenharmony_ci{ 2558617a3babSopenharmony_ci Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert); 2559617a3babSopenharmony_ci insert->addIdOperand(object); 2560617a3babSopenharmony_ci insert->addIdOperand(composite); 2561617a3babSopenharmony_ci insert->addImmediateOperand(index); 2562617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(insert)); 2563617a3babSopenharmony_ci 2564617a3babSopenharmony_ci return insert->getResultId(); 2565617a3babSopenharmony_ci} 2566617a3babSopenharmony_ci 2567617a3babSopenharmony_ciId Builder::createCompositeInsert(Id object, Id composite, Id typeId, const std::vector<unsigned>& indexes) 2568617a3babSopenharmony_ci{ 2569617a3babSopenharmony_ci Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert); 2570617a3babSopenharmony_ci insert->addIdOperand(object); 2571617a3babSopenharmony_ci insert->addIdOperand(composite); 2572617a3babSopenharmony_ci for (int i = 0; i < (int)indexes.size(); ++i) 2573617a3babSopenharmony_ci insert->addImmediateOperand(indexes[i]); 2574617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(insert)); 2575617a3babSopenharmony_ci 2576617a3babSopenharmony_ci return insert->getResultId(); 2577617a3babSopenharmony_ci} 2578617a3babSopenharmony_ci 2579617a3babSopenharmony_ciId Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex) 2580617a3babSopenharmony_ci{ 2581617a3babSopenharmony_ci Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic); 2582617a3babSopenharmony_ci extract->addIdOperand(vector); 2583617a3babSopenharmony_ci extract->addIdOperand(componentIndex); 2584617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(extract)); 2585617a3babSopenharmony_ci 2586617a3babSopenharmony_ci return extract->getResultId(); 2587617a3babSopenharmony_ci} 2588617a3babSopenharmony_ci 2589617a3babSopenharmony_ciId Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex) 2590617a3babSopenharmony_ci{ 2591617a3babSopenharmony_ci Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic); 2592617a3babSopenharmony_ci insert->addIdOperand(vector); 2593617a3babSopenharmony_ci insert->addIdOperand(component); 2594617a3babSopenharmony_ci insert->addIdOperand(componentIndex); 2595617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(insert)); 2596617a3babSopenharmony_ci 2597617a3babSopenharmony_ci return insert->getResultId(); 2598617a3babSopenharmony_ci} 2599617a3babSopenharmony_ci 2600617a3babSopenharmony_ci// An opcode that has no operands, no result id, and no type 2601617a3babSopenharmony_civoid Builder::createNoResultOp(Op opCode) 2602617a3babSopenharmony_ci{ 2603617a3babSopenharmony_ci Instruction* op = new Instruction(opCode); 2604617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2605617a3babSopenharmony_ci} 2606617a3babSopenharmony_ci 2607617a3babSopenharmony_ci// An opcode that has one id operand, no result id, and no type 2608617a3babSopenharmony_civoid Builder::createNoResultOp(Op opCode, Id operand) 2609617a3babSopenharmony_ci{ 2610617a3babSopenharmony_ci Instruction* op = new Instruction(opCode); 2611617a3babSopenharmony_ci op->addIdOperand(operand); 2612617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2613617a3babSopenharmony_ci} 2614617a3babSopenharmony_ci 2615617a3babSopenharmony_ci// An opcode that has one or more operands, no result id, and no type 2616617a3babSopenharmony_civoid Builder::createNoResultOp(Op opCode, const std::vector<Id>& operands) 2617617a3babSopenharmony_ci{ 2618617a3babSopenharmony_ci Instruction* op = new Instruction(opCode); 2619617a3babSopenharmony_ci for (auto it = operands.cbegin(); it != operands.cend(); ++it) { 2620617a3babSopenharmony_ci op->addIdOperand(*it); 2621617a3babSopenharmony_ci } 2622617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2623617a3babSopenharmony_ci} 2624617a3babSopenharmony_ci 2625617a3babSopenharmony_ci// An opcode that has multiple operands, no result id, and no type 2626617a3babSopenharmony_civoid Builder::createNoResultOp(Op opCode, const std::vector<IdImmediate>& operands) 2627617a3babSopenharmony_ci{ 2628617a3babSopenharmony_ci Instruction* op = new Instruction(opCode); 2629617a3babSopenharmony_ci for (auto it = operands.cbegin(); it != operands.cend(); ++it) { 2630617a3babSopenharmony_ci if (it->isId) 2631617a3babSopenharmony_ci op->addIdOperand(it->word); 2632617a3babSopenharmony_ci else 2633617a3babSopenharmony_ci op->addImmediateOperand(it->word); 2634617a3babSopenharmony_ci } 2635617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2636617a3babSopenharmony_ci} 2637617a3babSopenharmony_ci 2638617a3babSopenharmony_civoid Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics) 2639617a3babSopenharmony_ci{ 2640617a3babSopenharmony_ci Instruction* op = new Instruction(OpControlBarrier); 2641617a3babSopenharmony_ci op->addIdOperand(makeUintConstant(execution)); 2642617a3babSopenharmony_ci op->addIdOperand(makeUintConstant(memory)); 2643617a3babSopenharmony_ci op->addIdOperand(makeUintConstant(semantics)); 2644617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2645617a3babSopenharmony_ci} 2646617a3babSopenharmony_ci 2647617a3babSopenharmony_civoid Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics) 2648617a3babSopenharmony_ci{ 2649617a3babSopenharmony_ci Instruction* op = new Instruction(OpMemoryBarrier); 2650617a3babSopenharmony_ci op->addIdOperand(makeUintConstant(executionScope)); 2651617a3babSopenharmony_ci op->addIdOperand(makeUintConstant(memorySemantics)); 2652617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2653617a3babSopenharmony_ci} 2654617a3babSopenharmony_ci 2655617a3babSopenharmony_ci// An opcode that has one operands, a result id, and a type 2656617a3babSopenharmony_ciId Builder::createUnaryOp(Op opCode, Id typeId, Id operand) 2657617a3babSopenharmony_ci{ 2658617a3babSopenharmony_ci // Generate code for spec constants if in spec constant operation 2659617a3babSopenharmony_ci // generation mode. 2660617a3babSopenharmony_ci if (generatingOpCodeForSpecConst) { 2661617a3babSopenharmony_ci return createSpecConstantOp(opCode, typeId, std::vector<Id>(1, operand), std::vector<Id>()); 2662617a3babSopenharmony_ci } 2663617a3babSopenharmony_ci Instruction* op = new Instruction(getUniqueId(), typeId, opCode); 2664617a3babSopenharmony_ci op->addIdOperand(operand); 2665617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2666617a3babSopenharmony_ci 2667617a3babSopenharmony_ci return op->getResultId(); 2668617a3babSopenharmony_ci} 2669617a3babSopenharmony_ci 2670617a3babSopenharmony_ciId Builder::createBinOp(Op opCode, Id typeId, Id left, Id right) 2671617a3babSopenharmony_ci{ 2672617a3babSopenharmony_ci // Generate code for spec constants if in spec constant operation 2673617a3babSopenharmony_ci // generation mode. 2674617a3babSopenharmony_ci if (generatingOpCodeForSpecConst) { 2675617a3babSopenharmony_ci std::vector<Id> operands(2); 2676617a3babSopenharmony_ci operands[0] = left; operands[1] = right; 2677617a3babSopenharmony_ci return createSpecConstantOp(opCode, typeId, operands, std::vector<Id>()); 2678617a3babSopenharmony_ci } 2679617a3babSopenharmony_ci Instruction* op = new Instruction(getUniqueId(), typeId, opCode); 2680617a3babSopenharmony_ci op->addIdOperand(left); 2681617a3babSopenharmony_ci op->addIdOperand(right); 2682617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2683617a3babSopenharmony_ci 2684617a3babSopenharmony_ci return op->getResultId(); 2685617a3babSopenharmony_ci} 2686617a3babSopenharmony_ci 2687617a3babSopenharmony_ciId Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3) 2688617a3babSopenharmony_ci{ 2689617a3babSopenharmony_ci // Generate code for spec constants if in spec constant operation 2690617a3babSopenharmony_ci // generation mode. 2691617a3babSopenharmony_ci if (generatingOpCodeForSpecConst) { 2692617a3babSopenharmony_ci std::vector<Id> operands(3); 2693617a3babSopenharmony_ci operands[0] = op1; 2694617a3babSopenharmony_ci operands[1] = op2; 2695617a3babSopenharmony_ci operands[2] = op3; 2696617a3babSopenharmony_ci return createSpecConstantOp( 2697617a3babSopenharmony_ci opCode, typeId, operands, std::vector<Id>()); 2698617a3babSopenharmony_ci } 2699617a3babSopenharmony_ci Instruction* op = new Instruction(getUniqueId(), typeId, opCode); 2700617a3babSopenharmony_ci op->addIdOperand(op1); 2701617a3babSopenharmony_ci op->addIdOperand(op2); 2702617a3babSopenharmony_ci op->addIdOperand(op3); 2703617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2704617a3babSopenharmony_ci 2705617a3babSopenharmony_ci return op->getResultId(); 2706617a3babSopenharmony_ci} 2707617a3babSopenharmony_ci 2708617a3babSopenharmony_ciId Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands) 2709617a3babSopenharmony_ci{ 2710617a3babSopenharmony_ci Instruction* op = new Instruction(getUniqueId(), typeId, opCode); 2711617a3babSopenharmony_ci for (auto it = operands.cbegin(); it != operands.cend(); ++it) 2712617a3babSopenharmony_ci op->addIdOperand(*it); 2713617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2714617a3babSopenharmony_ci 2715617a3babSopenharmony_ci return op->getResultId(); 2716617a3babSopenharmony_ci} 2717617a3babSopenharmony_ci 2718617a3babSopenharmony_ciId Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& operands) 2719617a3babSopenharmony_ci{ 2720617a3babSopenharmony_ci Instruction* op = new Instruction(getUniqueId(), typeId, opCode); 2721617a3babSopenharmony_ci for (auto it = operands.cbegin(); it != operands.cend(); ++it) { 2722617a3babSopenharmony_ci if (it->isId) 2723617a3babSopenharmony_ci op->addIdOperand(it->word); 2724617a3babSopenharmony_ci else 2725617a3babSopenharmony_ci op->addImmediateOperand(it->word); 2726617a3babSopenharmony_ci } 2727617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2728617a3babSopenharmony_ci 2729617a3babSopenharmony_ci return op->getResultId(); 2730617a3babSopenharmony_ci} 2731617a3babSopenharmony_ci 2732617a3babSopenharmony_ciId Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, 2733617a3babSopenharmony_ci const std::vector<unsigned>& literals) 2734617a3babSopenharmony_ci{ 2735617a3babSopenharmony_ci Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); 2736617a3babSopenharmony_ci op->addImmediateOperand((unsigned) opCode); 2737617a3babSopenharmony_ci for (auto it = operands.cbegin(); it != operands.cend(); ++it) 2738617a3babSopenharmony_ci op->addIdOperand(*it); 2739617a3babSopenharmony_ci for (auto it = literals.cbegin(); it != literals.cend(); ++it) 2740617a3babSopenharmony_ci op->addImmediateOperand(*it); 2741617a3babSopenharmony_ci module.mapInstruction(op); 2742617a3babSopenharmony_ci constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(op)); 2743617a3babSopenharmony_ci 2744617a3babSopenharmony_ci // OpSpecConstantOp's using 8 or 16 bit types require the associated capability 2745617a3babSopenharmony_ci if (containsType(typeId, OpTypeInt, 8)) 2746617a3babSopenharmony_ci addCapability(CapabilityInt8); 2747617a3babSopenharmony_ci if (containsType(typeId, OpTypeInt, 16)) 2748617a3babSopenharmony_ci addCapability(CapabilityInt16); 2749617a3babSopenharmony_ci if (containsType(typeId, OpTypeFloat, 16)) 2750617a3babSopenharmony_ci addCapability(CapabilityFloat16); 2751617a3babSopenharmony_ci 2752617a3babSopenharmony_ci return op->getResultId(); 2753617a3babSopenharmony_ci} 2754617a3babSopenharmony_ci 2755617a3babSopenharmony_ciId Builder::createFunctionCall(spv::Function* function, const std::vector<spv::Id>& args) 2756617a3babSopenharmony_ci{ 2757617a3babSopenharmony_ci Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall); 2758617a3babSopenharmony_ci op->addIdOperand(function->getId()); 2759617a3babSopenharmony_ci for (int a = 0; a < (int)args.size(); ++a) 2760617a3babSopenharmony_ci op->addIdOperand(args[a]); 2761617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 2762617a3babSopenharmony_ci 2763617a3babSopenharmony_ci return op->getResultId(); 2764617a3babSopenharmony_ci} 2765617a3babSopenharmony_ci 2766617a3babSopenharmony_ci// Comments in header 2767617a3babSopenharmony_ciId Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector<unsigned>& channels) 2768617a3babSopenharmony_ci{ 2769617a3babSopenharmony_ci if (channels.size() == 1) 2770617a3babSopenharmony_ci return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision); 2771617a3babSopenharmony_ci 2772617a3babSopenharmony_ci if (generatingOpCodeForSpecConst) { 2773617a3babSopenharmony_ci std::vector<Id> operands(2); 2774617a3babSopenharmony_ci operands[0] = operands[1] = source; 2775617a3babSopenharmony_ci return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, operands, channels), precision); 2776617a3babSopenharmony_ci } 2777617a3babSopenharmony_ci Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); 2778617a3babSopenharmony_ci assert(isVector(source)); 2779617a3babSopenharmony_ci swizzle->addIdOperand(source); 2780617a3babSopenharmony_ci swizzle->addIdOperand(source); 2781617a3babSopenharmony_ci for (int i = 0; i < (int)channels.size(); ++i) 2782617a3babSopenharmony_ci swizzle->addImmediateOperand(channels[i]); 2783617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle)); 2784617a3babSopenharmony_ci 2785617a3babSopenharmony_ci return setPrecision(swizzle->getResultId(), precision); 2786617a3babSopenharmony_ci} 2787617a3babSopenharmony_ci 2788617a3babSopenharmony_ci// Comments in header 2789617a3babSopenharmony_ciId Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector<unsigned>& channels) 2790617a3babSopenharmony_ci{ 2791617a3babSopenharmony_ci if (channels.size() == 1 && getNumComponents(source) == 1) 2792617a3babSopenharmony_ci return createCompositeInsert(source, target, typeId, channels.front()); 2793617a3babSopenharmony_ci 2794617a3babSopenharmony_ci Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); 2795617a3babSopenharmony_ci 2796617a3babSopenharmony_ci assert(isVector(target)); 2797617a3babSopenharmony_ci swizzle->addIdOperand(target); 2798617a3babSopenharmony_ci 2799617a3babSopenharmony_ci assert(getNumComponents(source) == (int)channels.size()); 2800617a3babSopenharmony_ci assert(isVector(source)); 2801617a3babSopenharmony_ci swizzle->addIdOperand(source); 2802617a3babSopenharmony_ci 2803617a3babSopenharmony_ci // Set up an identity shuffle from the base value to the result value 2804617a3babSopenharmony_ci unsigned int components[4]; 2805617a3babSopenharmony_ci int numTargetComponents = getNumComponents(target); 2806617a3babSopenharmony_ci for (int i = 0; i < numTargetComponents; ++i) 2807617a3babSopenharmony_ci components[i] = i; 2808617a3babSopenharmony_ci 2809617a3babSopenharmony_ci // Punch in the l-value swizzle 2810617a3babSopenharmony_ci for (int i = 0; i < (int)channels.size(); ++i) 2811617a3babSopenharmony_ci components[channels[i]] = numTargetComponents + i; 2812617a3babSopenharmony_ci 2813617a3babSopenharmony_ci // finish the instruction with these components selectors 2814617a3babSopenharmony_ci for (int i = 0; i < numTargetComponents; ++i) 2815617a3babSopenharmony_ci swizzle->addImmediateOperand(components[i]); 2816617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle)); 2817617a3babSopenharmony_ci 2818617a3babSopenharmony_ci return swizzle->getResultId(); 2819617a3babSopenharmony_ci} 2820617a3babSopenharmony_ci 2821617a3babSopenharmony_ci// Comments in header 2822617a3babSopenharmony_civoid Builder::promoteScalar(Decoration precision, Id& left, Id& right) 2823617a3babSopenharmony_ci{ 2824617a3babSopenharmony_ci int direction = getNumComponents(right) - getNumComponents(left); 2825617a3babSopenharmony_ci 2826617a3babSopenharmony_ci if (direction > 0) 2827617a3babSopenharmony_ci left = smearScalar(precision, left, makeVectorType(getTypeId(left), getNumComponents(right))); 2828617a3babSopenharmony_ci else if (direction < 0) 2829617a3babSopenharmony_ci right = smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left))); 2830617a3babSopenharmony_ci 2831617a3babSopenharmony_ci return; 2832617a3babSopenharmony_ci} 2833617a3babSopenharmony_ci 2834617a3babSopenharmony_ci// Comments in header 2835617a3babSopenharmony_ciId Builder::smearScalar(Decoration precision, Id scalar, Id vectorType) 2836617a3babSopenharmony_ci{ 2837617a3babSopenharmony_ci assert(getNumComponents(scalar) == 1); 2838617a3babSopenharmony_ci assert(getTypeId(scalar) == getScalarTypeId(vectorType)); 2839617a3babSopenharmony_ci 2840617a3babSopenharmony_ci int numComponents = getNumTypeComponents(vectorType); 2841617a3babSopenharmony_ci if (numComponents == 1) 2842617a3babSopenharmony_ci return scalar; 2843617a3babSopenharmony_ci 2844617a3babSopenharmony_ci Instruction* smear = nullptr; 2845617a3babSopenharmony_ci if (generatingOpCodeForSpecConst) { 2846617a3babSopenharmony_ci auto members = std::vector<spv::Id>(numComponents, scalar); 2847617a3babSopenharmony_ci // Sometime even in spec-constant-op mode, the temporary vector created by 2848617a3babSopenharmony_ci // promoting a scalar might not be a spec constant. This should depend on 2849617a3babSopenharmony_ci // the scalar. 2850617a3babSopenharmony_ci // e.g.: 2851617a3babSopenharmony_ci // const vec2 spec_const_result = a_spec_const_vec2 + a_front_end_const_scalar; 2852617a3babSopenharmony_ci // In such cases, the temporary vector created from a_front_end_const_scalar 2853617a3babSopenharmony_ci // is not a spec constant vector, even though the binary operation node is marked 2854617a3babSopenharmony_ci // as 'specConstant' and we are in spec-constant-op mode. 2855617a3babSopenharmony_ci auto result_id = makeCompositeConstant(vectorType, members, isSpecConstant(scalar)); 2856617a3babSopenharmony_ci smear = module.getInstruction(result_id); 2857617a3babSopenharmony_ci } else { 2858617a3babSopenharmony_ci smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); 2859617a3babSopenharmony_ci for (int c = 0; c < numComponents; ++c) 2860617a3babSopenharmony_ci smear->addIdOperand(scalar); 2861617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(smear)); 2862617a3babSopenharmony_ci } 2863617a3babSopenharmony_ci 2864617a3babSopenharmony_ci return setPrecision(smear->getResultId(), precision); 2865617a3babSopenharmony_ci} 2866617a3babSopenharmony_ci 2867617a3babSopenharmony_ci// Comments in header 2868617a3babSopenharmony_ciId Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector<Id>& args) 2869617a3babSopenharmony_ci{ 2870617a3babSopenharmony_ci Instruction* inst = new Instruction(getUniqueId(), resultType, OpExtInst); 2871617a3babSopenharmony_ci inst->addIdOperand(builtins); 2872617a3babSopenharmony_ci inst->addImmediateOperand(entryPoint); 2873617a3babSopenharmony_ci for (int arg = 0; arg < (int)args.size(); ++arg) 2874617a3babSopenharmony_ci inst->addIdOperand(args[arg]); 2875617a3babSopenharmony_ci 2876617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(inst)); 2877617a3babSopenharmony_ci 2878617a3babSopenharmony_ci return inst->getResultId(); 2879617a3babSopenharmony_ci} 2880617a3babSopenharmony_ci 2881617a3babSopenharmony_ci// Accept all parameters needed to create a texture instruction. 2882617a3babSopenharmony_ci// Create the correct instruction based on the inputs, and make the call. 2883617a3babSopenharmony_ciId Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, 2884617a3babSopenharmony_ci bool noImplicitLod, const TextureParameters& parameters, ImageOperandsMask signExtensionMask) 2885617a3babSopenharmony_ci{ 2886617a3babSopenharmony_ci std::vector<Id> texArgs; 2887617a3babSopenharmony_ci 2888617a3babSopenharmony_ci // 2889617a3babSopenharmony_ci // Set up the fixed arguments 2890617a3babSopenharmony_ci // 2891617a3babSopenharmony_ci bool explicitLod = false; 2892617a3babSopenharmony_ci texArgs.push_back(parameters.sampler); 2893617a3babSopenharmony_ci texArgs.push_back(parameters.coords); 2894617a3babSopenharmony_ci if (parameters.Dref != NoResult) 2895617a3babSopenharmony_ci texArgs.push_back(parameters.Dref); 2896617a3babSopenharmony_ci if (parameters.component != NoResult) 2897617a3babSopenharmony_ci texArgs.push_back(parameters.component); 2898617a3babSopenharmony_ci 2899617a3babSopenharmony_ci if (parameters.granularity != NoResult) 2900617a3babSopenharmony_ci texArgs.push_back(parameters.granularity); 2901617a3babSopenharmony_ci if (parameters.coarse != NoResult) 2902617a3babSopenharmony_ci texArgs.push_back(parameters.coarse); 2903617a3babSopenharmony_ci 2904617a3babSopenharmony_ci // 2905617a3babSopenharmony_ci // Set up the optional arguments 2906617a3babSopenharmony_ci // 2907617a3babSopenharmony_ci size_t optArgNum = texArgs.size(); // the position of the mask for the optional arguments, if any. 2908617a3babSopenharmony_ci ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand 2909617a3babSopenharmony_ci if (parameters.bias) { 2910617a3babSopenharmony_ci mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask); 2911617a3babSopenharmony_ci texArgs.push_back(parameters.bias); 2912617a3babSopenharmony_ci } 2913617a3babSopenharmony_ci if (parameters.lod) { 2914617a3babSopenharmony_ci mask = (ImageOperandsMask)(mask | ImageOperandsLodMask); 2915617a3babSopenharmony_ci texArgs.push_back(parameters.lod); 2916617a3babSopenharmony_ci explicitLod = true; 2917617a3babSopenharmony_ci } else if (parameters.gradX) { 2918617a3babSopenharmony_ci mask = (ImageOperandsMask)(mask | ImageOperandsGradMask); 2919617a3babSopenharmony_ci texArgs.push_back(parameters.gradX); 2920617a3babSopenharmony_ci texArgs.push_back(parameters.gradY); 2921617a3babSopenharmony_ci explicitLod = true; 2922617a3babSopenharmony_ci } else if (noImplicitLod && ! fetch && ! gather) { 2923617a3babSopenharmony_ci // have to explicitly use lod of 0 if not allowed to have them be implicit, and 2924617a3babSopenharmony_ci // we would otherwise be about to issue an implicit instruction 2925617a3babSopenharmony_ci mask = (ImageOperandsMask)(mask | ImageOperandsLodMask); 2926617a3babSopenharmony_ci texArgs.push_back(makeFloatConstant(0.0)); 2927617a3babSopenharmony_ci explicitLod = true; 2928617a3babSopenharmony_ci } 2929617a3babSopenharmony_ci if (parameters.offset) { 2930617a3babSopenharmony_ci if (isConstant(parameters.offset)) 2931617a3babSopenharmony_ci mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetMask); 2932617a3babSopenharmony_ci else { 2933617a3babSopenharmony_ci addCapability(CapabilityImageGatherExtended); 2934617a3babSopenharmony_ci mask = (ImageOperandsMask)(mask | ImageOperandsOffsetMask); 2935617a3babSopenharmony_ci } 2936617a3babSopenharmony_ci texArgs.push_back(parameters.offset); 2937617a3babSopenharmony_ci } 2938617a3babSopenharmony_ci if (parameters.offsets) { 2939617a3babSopenharmony_ci addCapability(CapabilityImageGatherExtended); 2940617a3babSopenharmony_ci mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetsMask); 2941617a3babSopenharmony_ci texArgs.push_back(parameters.offsets); 2942617a3babSopenharmony_ci } 2943617a3babSopenharmony_ci if (parameters.sample) { 2944617a3babSopenharmony_ci mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask); 2945617a3babSopenharmony_ci texArgs.push_back(parameters.sample); 2946617a3babSopenharmony_ci } 2947617a3babSopenharmony_ci if (parameters.lodClamp) { 2948617a3babSopenharmony_ci // capability if this bit is used 2949617a3babSopenharmony_ci addCapability(CapabilityMinLod); 2950617a3babSopenharmony_ci 2951617a3babSopenharmony_ci mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask); 2952617a3babSopenharmony_ci texArgs.push_back(parameters.lodClamp); 2953617a3babSopenharmony_ci } 2954617a3babSopenharmony_ci if (parameters.nonprivate) { 2955617a3babSopenharmony_ci mask = mask | ImageOperandsNonPrivateTexelKHRMask; 2956617a3babSopenharmony_ci } 2957617a3babSopenharmony_ci if (parameters.volatil) { 2958617a3babSopenharmony_ci mask = mask | ImageOperandsVolatileTexelKHRMask; 2959617a3babSopenharmony_ci } 2960617a3babSopenharmony_ci mask = mask | signExtensionMask; 2961617a3babSopenharmony_ci // insert the operand for the mask, if any bits were set. 2962617a3babSopenharmony_ci if (mask != ImageOperandsMaskNone) 2963617a3babSopenharmony_ci texArgs.insert(texArgs.begin() + optArgNum, mask); 2964617a3babSopenharmony_ci 2965617a3babSopenharmony_ci // 2966617a3babSopenharmony_ci // Set up the instruction 2967617a3babSopenharmony_ci // 2968617a3babSopenharmony_ci Op opCode = OpNop; // All paths below need to set this 2969617a3babSopenharmony_ci if (fetch) { 2970617a3babSopenharmony_ci if (sparse) 2971617a3babSopenharmony_ci opCode = OpImageSparseFetch; 2972617a3babSopenharmony_ci else 2973617a3babSopenharmony_ci opCode = OpImageFetch; 2974617a3babSopenharmony_ci } else if (parameters.granularity && parameters.coarse) { 2975617a3babSopenharmony_ci opCode = OpImageSampleFootprintNV; 2976617a3babSopenharmony_ci } else if (gather) { 2977617a3babSopenharmony_ci if (parameters.Dref) 2978617a3babSopenharmony_ci if (sparse) 2979617a3babSopenharmony_ci opCode = OpImageSparseDrefGather; 2980617a3babSopenharmony_ci else 2981617a3babSopenharmony_ci opCode = OpImageDrefGather; 2982617a3babSopenharmony_ci else 2983617a3babSopenharmony_ci if (sparse) 2984617a3babSopenharmony_ci opCode = OpImageSparseGather; 2985617a3babSopenharmony_ci else 2986617a3babSopenharmony_ci opCode = OpImageGather; 2987617a3babSopenharmony_ci } else if (explicitLod) { 2988617a3babSopenharmony_ci if (parameters.Dref) { 2989617a3babSopenharmony_ci if (proj) 2990617a3babSopenharmony_ci if (sparse) 2991617a3babSopenharmony_ci opCode = OpImageSparseSampleProjDrefExplicitLod; 2992617a3babSopenharmony_ci else 2993617a3babSopenharmony_ci opCode = OpImageSampleProjDrefExplicitLod; 2994617a3babSopenharmony_ci else 2995617a3babSopenharmony_ci if (sparse) 2996617a3babSopenharmony_ci opCode = OpImageSparseSampleDrefExplicitLod; 2997617a3babSopenharmony_ci else 2998617a3babSopenharmony_ci opCode = OpImageSampleDrefExplicitLod; 2999617a3babSopenharmony_ci } else { 3000617a3babSopenharmony_ci if (proj) 3001617a3babSopenharmony_ci if (sparse) 3002617a3babSopenharmony_ci opCode = OpImageSparseSampleProjExplicitLod; 3003617a3babSopenharmony_ci else 3004617a3babSopenharmony_ci opCode = OpImageSampleProjExplicitLod; 3005617a3babSopenharmony_ci else 3006617a3babSopenharmony_ci if (sparse) 3007617a3babSopenharmony_ci opCode = OpImageSparseSampleExplicitLod; 3008617a3babSopenharmony_ci else 3009617a3babSopenharmony_ci opCode = OpImageSampleExplicitLod; 3010617a3babSopenharmony_ci } 3011617a3babSopenharmony_ci } else { 3012617a3babSopenharmony_ci if (parameters.Dref) { 3013617a3babSopenharmony_ci if (proj) 3014617a3babSopenharmony_ci if (sparse) 3015617a3babSopenharmony_ci opCode = OpImageSparseSampleProjDrefImplicitLod; 3016617a3babSopenharmony_ci else 3017617a3babSopenharmony_ci opCode = OpImageSampleProjDrefImplicitLod; 3018617a3babSopenharmony_ci else 3019617a3babSopenharmony_ci if (sparse) 3020617a3babSopenharmony_ci opCode = OpImageSparseSampleDrefImplicitLod; 3021617a3babSopenharmony_ci else 3022617a3babSopenharmony_ci opCode = OpImageSampleDrefImplicitLod; 3023617a3babSopenharmony_ci } else { 3024617a3babSopenharmony_ci if (proj) 3025617a3babSopenharmony_ci if (sparse) 3026617a3babSopenharmony_ci opCode = OpImageSparseSampleProjImplicitLod; 3027617a3babSopenharmony_ci else 3028617a3babSopenharmony_ci opCode = OpImageSampleProjImplicitLod; 3029617a3babSopenharmony_ci else 3030617a3babSopenharmony_ci if (sparse) 3031617a3babSopenharmony_ci opCode = OpImageSparseSampleImplicitLod; 3032617a3babSopenharmony_ci else 3033617a3babSopenharmony_ci opCode = OpImageSampleImplicitLod; 3034617a3babSopenharmony_ci } 3035617a3babSopenharmony_ci } 3036617a3babSopenharmony_ci 3037617a3babSopenharmony_ci // See if the result type is expecting a smeared result. 3038617a3babSopenharmony_ci // This happens when a legacy shadow*() call is made, which 3039617a3babSopenharmony_ci // gets a vec4 back instead of a float. 3040617a3babSopenharmony_ci Id smearedType = resultType; 3041617a3babSopenharmony_ci if (! isScalarType(resultType)) { 3042617a3babSopenharmony_ci switch (opCode) { 3043617a3babSopenharmony_ci case OpImageSampleDrefImplicitLod: 3044617a3babSopenharmony_ci case OpImageSampleDrefExplicitLod: 3045617a3babSopenharmony_ci case OpImageSampleProjDrefImplicitLod: 3046617a3babSopenharmony_ci case OpImageSampleProjDrefExplicitLod: 3047617a3babSopenharmony_ci resultType = getScalarTypeId(resultType); 3048617a3babSopenharmony_ci break; 3049617a3babSopenharmony_ci default: 3050617a3babSopenharmony_ci break; 3051617a3babSopenharmony_ci } 3052617a3babSopenharmony_ci } 3053617a3babSopenharmony_ci 3054617a3babSopenharmony_ci Id typeId0 = 0; 3055617a3babSopenharmony_ci Id typeId1 = 0; 3056617a3babSopenharmony_ci 3057617a3babSopenharmony_ci if (sparse) { 3058617a3babSopenharmony_ci typeId0 = resultType; 3059617a3babSopenharmony_ci typeId1 = getDerefTypeId(parameters.texelOut); 3060617a3babSopenharmony_ci resultType = makeStructResultType(typeId0, typeId1); 3061617a3babSopenharmony_ci } 3062617a3babSopenharmony_ci 3063617a3babSopenharmony_ci // Build the SPIR-V instruction 3064617a3babSopenharmony_ci Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode); 3065617a3babSopenharmony_ci for (size_t op = 0; op < optArgNum; ++op) 3066617a3babSopenharmony_ci textureInst->addIdOperand(texArgs[op]); 3067617a3babSopenharmony_ci if (optArgNum < texArgs.size()) 3068617a3babSopenharmony_ci textureInst->addImmediateOperand(texArgs[optArgNum]); 3069617a3babSopenharmony_ci for (size_t op = optArgNum + 1; op < texArgs.size(); ++op) 3070617a3babSopenharmony_ci textureInst->addIdOperand(texArgs[op]); 3071617a3babSopenharmony_ci setPrecision(textureInst->getResultId(), precision); 3072617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(textureInst)); 3073617a3babSopenharmony_ci 3074617a3babSopenharmony_ci Id resultId = textureInst->getResultId(); 3075617a3babSopenharmony_ci 3076617a3babSopenharmony_ci if (sparse) { 3077617a3babSopenharmony_ci // set capability 3078617a3babSopenharmony_ci addCapability(CapabilitySparseResidency); 3079617a3babSopenharmony_ci 3080617a3babSopenharmony_ci // Decode the return type that was a special structure 3081617a3babSopenharmony_ci createStore(createCompositeExtract(resultId, typeId1, 1), parameters.texelOut); 3082617a3babSopenharmony_ci resultId = createCompositeExtract(resultId, typeId0, 0); 3083617a3babSopenharmony_ci setPrecision(resultId, precision); 3084617a3babSopenharmony_ci } else { 3085617a3babSopenharmony_ci // When a smear is needed, do it, as per what was computed 3086617a3babSopenharmony_ci // above when resultType was changed to a scalar type. 3087617a3babSopenharmony_ci if (resultType != smearedType) 3088617a3babSopenharmony_ci resultId = smearScalar(precision, resultId, smearedType); 3089617a3babSopenharmony_ci } 3090617a3babSopenharmony_ci 3091617a3babSopenharmony_ci return resultId; 3092617a3babSopenharmony_ci} 3093617a3babSopenharmony_ci 3094617a3babSopenharmony_ci// Comments in header 3095617a3babSopenharmony_ciId Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters, bool isUnsignedResult) 3096617a3babSopenharmony_ci{ 3097617a3babSopenharmony_ci // Figure out the result type 3098617a3babSopenharmony_ci Id resultType = 0; 3099617a3babSopenharmony_ci switch (opCode) { 3100617a3babSopenharmony_ci case OpImageQuerySize: 3101617a3babSopenharmony_ci case OpImageQuerySizeLod: 3102617a3babSopenharmony_ci { 3103617a3babSopenharmony_ci int numComponents = 0; 3104617a3babSopenharmony_ci switch (getTypeDimensionality(getImageType(parameters.sampler))) { 3105617a3babSopenharmony_ci case Dim1D: 3106617a3babSopenharmony_ci case DimBuffer: 3107617a3babSopenharmony_ci numComponents = 1; 3108617a3babSopenharmony_ci break; 3109617a3babSopenharmony_ci case Dim2D: 3110617a3babSopenharmony_ci case DimCube: 3111617a3babSopenharmony_ci case DimRect: 3112617a3babSopenharmony_ci case DimSubpassData: 3113617a3babSopenharmony_ci numComponents = 2; 3114617a3babSopenharmony_ci break; 3115617a3babSopenharmony_ci case Dim3D: 3116617a3babSopenharmony_ci numComponents = 3; 3117617a3babSopenharmony_ci break; 3118617a3babSopenharmony_ci 3119617a3babSopenharmony_ci default: 3120617a3babSopenharmony_ci assert(0); 3121617a3babSopenharmony_ci break; 3122617a3babSopenharmony_ci } 3123617a3babSopenharmony_ci if (isArrayedImageType(getImageType(parameters.sampler))) 3124617a3babSopenharmony_ci ++numComponents; 3125617a3babSopenharmony_ci 3126617a3babSopenharmony_ci Id intType = isUnsignedResult ? makeUintType(32) : makeIntType(32); 3127617a3babSopenharmony_ci if (numComponents == 1) 3128617a3babSopenharmony_ci resultType = intType; 3129617a3babSopenharmony_ci else 3130617a3babSopenharmony_ci resultType = makeVectorType(intType, numComponents); 3131617a3babSopenharmony_ci 3132617a3babSopenharmony_ci break; 3133617a3babSopenharmony_ci } 3134617a3babSopenharmony_ci case OpImageQueryLod: 3135617a3babSopenharmony_ci resultType = makeVectorType(getScalarTypeId(getTypeId(parameters.coords)), 2); 3136617a3babSopenharmony_ci break; 3137617a3babSopenharmony_ci case OpImageQueryLevels: 3138617a3babSopenharmony_ci case OpImageQuerySamples: 3139617a3babSopenharmony_ci resultType = isUnsignedResult ? makeUintType(32) : makeIntType(32); 3140617a3babSopenharmony_ci break; 3141617a3babSopenharmony_ci default: 3142617a3babSopenharmony_ci assert(0); 3143617a3babSopenharmony_ci break; 3144617a3babSopenharmony_ci } 3145617a3babSopenharmony_ci 3146617a3babSopenharmony_ci Instruction* query = new Instruction(getUniqueId(), resultType, opCode); 3147617a3babSopenharmony_ci query->addIdOperand(parameters.sampler); 3148617a3babSopenharmony_ci if (parameters.coords) 3149617a3babSopenharmony_ci query->addIdOperand(parameters.coords); 3150617a3babSopenharmony_ci if (parameters.lod) 3151617a3babSopenharmony_ci query->addIdOperand(parameters.lod); 3152617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(query)); 3153617a3babSopenharmony_ci addCapability(CapabilityImageQuery); 3154617a3babSopenharmony_ci 3155617a3babSopenharmony_ci return query->getResultId(); 3156617a3babSopenharmony_ci} 3157617a3babSopenharmony_ci 3158617a3babSopenharmony_ci// External comments in header. 3159617a3babSopenharmony_ci// Operates recursively to visit the composite's hierarchy. 3160617a3babSopenharmony_ciId Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, bool equal) 3161617a3babSopenharmony_ci{ 3162617a3babSopenharmony_ci Id boolType = makeBoolType(); 3163617a3babSopenharmony_ci Id valueType = getTypeId(value1); 3164617a3babSopenharmony_ci 3165617a3babSopenharmony_ci Id resultId = NoResult; 3166617a3babSopenharmony_ci 3167617a3babSopenharmony_ci int numConstituents = getNumTypeConstituents(valueType); 3168617a3babSopenharmony_ci 3169617a3babSopenharmony_ci // Scalars and Vectors 3170617a3babSopenharmony_ci 3171617a3babSopenharmony_ci if (isScalarType(valueType) || isVectorType(valueType)) { 3172617a3babSopenharmony_ci assert(valueType == getTypeId(value2)); 3173617a3babSopenharmony_ci // These just need a single comparison, just have 3174617a3babSopenharmony_ci // to figure out what it is. 3175617a3babSopenharmony_ci Op op; 3176617a3babSopenharmony_ci switch (getMostBasicTypeClass(valueType)) { 3177617a3babSopenharmony_ci case OpTypeFloat: 3178617a3babSopenharmony_ci op = equal ? OpFOrdEqual : OpFUnordNotEqual; 3179617a3babSopenharmony_ci break; 3180617a3babSopenharmony_ci case OpTypeInt: 3181617a3babSopenharmony_ci default: 3182617a3babSopenharmony_ci op = equal ? OpIEqual : OpINotEqual; 3183617a3babSopenharmony_ci break; 3184617a3babSopenharmony_ci case OpTypeBool: 3185617a3babSopenharmony_ci op = equal ? OpLogicalEqual : OpLogicalNotEqual; 3186617a3babSopenharmony_ci precision = NoPrecision; 3187617a3babSopenharmony_ci break; 3188617a3babSopenharmony_ci } 3189617a3babSopenharmony_ci 3190617a3babSopenharmony_ci if (isScalarType(valueType)) { 3191617a3babSopenharmony_ci // scalar 3192617a3babSopenharmony_ci resultId = createBinOp(op, boolType, value1, value2); 3193617a3babSopenharmony_ci } else { 3194617a3babSopenharmony_ci // vector 3195617a3babSopenharmony_ci resultId = createBinOp(op, makeVectorType(boolType, numConstituents), value1, value2); 3196617a3babSopenharmony_ci setPrecision(resultId, precision); 3197617a3babSopenharmony_ci // reduce vector compares... 3198617a3babSopenharmony_ci resultId = createUnaryOp(equal ? OpAll : OpAny, boolType, resultId); 3199617a3babSopenharmony_ci } 3200617a3babSopenharmony_ci 3201617a3babSopenharmony_ci return setPrecision(resultId, precision); 3202617a3babSopenharmony_ci } 3203617a3babSopenharmony_ci 3204617a3babSopenharmony_ci // Only structs, arrays, and matrices should be left. 3205617a3babSopenharmony_ci // They share in common the reduction operation across their constituents. 3206617a3babSopenharmony_ci assert(isAggregateType(valueType) || isMatrixType(valueType)); 3207617a3babSopenharmony_ci 3208617a3babSopenharmony_ci // Compare each pair of constituents 3209617a3babSopenharmony_ci for (int constituent = 0; constituent < numConstituents; ++constituent) { 3210617a3babSopenharmony_ci std::vector<unsigned> indexes(1, constituent); 3211617a3babSopenharmony_ci Id constituentType1 = getContainedTypeId(getTypeId(value1), constituent); 3212617a3babSopenharmony_ci Id constituentType2 = getContainedTypeId(getTypeId(value2), constituent); 3213617a3babSopenharmony_ci Id constituent1 = createCompositeExtract(value1, constituentType1, indexes); 3214617a3babSopenharmony_ci Id constituent2 = createCompositeExtract(value2, constituentType2, indexes); 3215617a3babSopenharmony_ci 3216617a3babSopenharmony_ci Id subResultId = createCompositeCompare(precision, constituent1, constituent2, equal); 3217617a3babSopenharmony_ci 3218617a3babSopenharmony_ci if (constituent == 0) 3219617a3babSopenharmony_ci resultId = subResultId; 3220617a3babSopenharmony_ci else 3221617a3babSopenharmony_ci resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), 3222617a3babSopenharmony_ci precision); 3223617a3babSopenharmony_ci } 3224617a3babSopenharmony_ci 3225617a3babSopenharmony_ci return resultId; 3226617a3babSopenharmony_ci} 3227617a3babSopenharmony_ci 3228617a3babSopenharmony_ci// OpCompositeConstruct 3229617a3babSopenharmony_ciId Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents) 3230617a3babSopenharmony_ci{ 3231617a3babSopenharmony_ci assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && 3232617a3babSopenharmony_ci getNumTypeConstituents(typeId) == (int)constituents.size())); 3233617a3babSopenharmony_ci 3234617a3babSopenharmony_ci if (generatingOpCodeForSpecConst) { 3235617a3babSopenharmony_ci // Sometime, even in spec-constant-op mode, the constant composite to be 3236617a3babSopenharmony_ci // constructed may not be a specialization constant. 3237617a3babSopenharmony_ci // e.g.: 3238617a3babSopenharmony_ci // const mat2 m2 = mat2(a_spec_const, a_front_end_const, another_front_end_const, third_front_end_const); 3239617a3babSopenharmony_ci // The first column vector should be a spec constant one, as a_spec_const is a spec constant. 3240617a3babSopenharmony_ci // The second column vector should NOT be spec constant, as it does not contain any spec constants. 3241617a3babSopenharmony_ci // To handle such cases, we check the constituents of the constant vector to determine whether this 3242617a3babSopenharmony_ci // vector should be created as a spec constant. 3243617a3babSopenharmony_ci return makeCompositeConstant(typeId, constituents, 3244617a3babSopenharmony_ci std::any_of(constituents.begin(), constituents.end(), 3245617a3babSopenharmony_ci [&](spv::Id id) { return isSpecConstant(id); })); 3246617a3babSopenharmony_ci } 3247617a3babSopenharmony_ci 3248617a3babSopenharmony_ci Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct); 3249617a3babSopenharmony_ci for (int c = 0; c < (int)constituents.size(); ++c) 3250617a3babSopenharmony_ci op->addIdOperand(constituents[c]); 3251617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); 3252617a3babSopenharmony_ci 3253617a3babSopenharmony_ci return op->getResultId(); 3254617a3babSopenharmony_ci} 3255617a3babSopenharmony_ci 3256617a3babSopenharmony_ci// Vector or scalar constructor 3257617a3babSopenharmony_ciId Builder::createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId) 3258617a3babSopenharmony_ci{ 3259617a3babSopenharmony_ci Id result = NoResult; 3260617a3babSopenharmony_ci unsigned int numTargetComponents = getNumTypeComponents(resultTypeId); 3261617a3babSopenharmony_ci unsigned int targetComponent = 0; 3262617a3babSopenharmony_ci 3263617a3babSopenharmony_ci // Special case: when calling a vector constructor with a single scalar 3264617a3babSopenharmony_ci // argument, smear the scalar 3265617a3babSopenharmony_ci if (sources.size() == 1 && isScalar(sources[0]) && numTargetComponents > 1) 3266617a3babSopenharmony_ci return smearScalar(precision, sources[0], resultTypeId); 3267617a3babSopenharmony_ci 3268617a3babSopenharmony_ci // accumulate the arguments for OpCompositeConstruct 3269617a3babSopenharmony_ci std::vector<Id> constituents; 3270617a3babSopenharmony_ci Id scalarTypeId = getScalarTypeId(resultTypeId); 3271617a3babSopenharmony_ci 3272617a3babSopenharmony_ci // lambda to store the result of visiting an argument component 3273617a3babSopenharmony_ci const auto latchResult = [&](Id comp) { 3274617a3babSopenharmony_ci if (numTargetComponents > 1) 3275617a3babSopenharmony_ci constituents.push_back(comp); 3276617a3babSopenharmony_ci else 3277617a3babSopenharmony_ci result = comp; 3278617a3babSopenharmony_ci ++targetComponent; 3279617a3babSopenharmony_ci }; 3280617a3babSopenharmony_ci 3281617a3babSopenharmony_ci // lambda to visit a vector argument's components 3282617a3babSopenharmony_ci const auto accumulateVectorConstituents = [&](Id sourceArg) { 3283617a3babSopenharmony_ci unsigned int sourceSize = getNumComponents(sourceArg); 3284617a3babSopenharmony_ci unsigned int sourcesToUse = sourceSize; 3285617a3babSopenharmony_ci if (sourcesToUse + targetComponent > numTargetComponents) 3286617a3babSopenharmony_ci sourcesToUse = numTargetComponents - targetComponent; 3287617a3babSopenharmony_ci 3288617a3babSopenharmony_ci for (unsigned int s = 0; s < sourcesToUse; ++s) { 3289617a3babSopenharmony_ci std::vector<unsigned> swiz; 3290617a3babSopenharmony_ci swiz.push_back(s); 3291617a3babSopenharmony_ci latchResult(createRvalueSwizzle(precision, scalarTypeId, sourceArg, swiz)); 3292617a3babSopenharmony_ci } 3293617a3babSopenharmony_ci }; 3294617a3babSopenharmony_ci 3295617a3babSopenharmony_ci // lambda to visit a matrix argument's components 3296617a3babSopenharmony_ci const auto accumulateMatrixConstituents = [&](Id sourceArg) { 3297617a3babSopenharmony_ci unsigned int sourceSize = getNumColumns(sourceArg) * getNumRows(sourceArg); 3298617a3babSopenharmony_ci unsigned int sourcesToUse = sourceSize; 3299617a3babSopenharmony_ci if (sourcesToUse + targetComponent > numTargetComponents) 3300617a3babSopenharmony_ci sourcesToUse = numTargetComponents - targetComponent; 3301617a3babSopenharmony_ci 3302617a3babSopenharmony_ci int col = 0; 3303617a3babSopenharmony_ci int row = 0; 3304617a3babSopenharmony_ci for (unsigned int s = 0; s < sourcesToUse; ++s) { 3305617a3babSopenharmony_ci if (row >= getNumRows(sourceArg)) { 3306617a3babSopenharmony_ci row = 0; 3307617a3babSopenharmony_ci col++; 3308617a3babSopenharmony_ci } 3309617a3babSopenharmony_ci std::vector<Id> indexes; 3310617a3babSopenharmony_ci indexes.push_back(col); 3311617a3babSopenharmony_ci indexes.push_back(row); 3312617a3babSopenharmony_ci latchResult(createCompositeExtract(sourceArg, scalarTypeId, indexes)); 3313617a3babSopenharmony_ci row++; 3314617a3babSopenharmony_ci } 3315617a3babSopenharmony_ci }; 3316617a3babSopenharmony_ci 3317617a3babSopenharmony_ci // Go through the source arguments, each one could have either 3318617a3babSopenharmony_ci // a single or multiple components to contribute. 3319617a3babSopenharmony_ci for (unsigned int i = 0; i < sources.size(); ++i) { 3320617a3babSopenharmony_ci 3321617a3babSopenharmony_ci if (isScalar(sources[i]) || isPointer(sources[i])) 3322617a3babSopenharmony_ci latchResult(sources[i]); 3323617a3babSopenharmony_ci else if (isVector(sources[i])) 3324617a3babSopenharmony_ci accumulateVectorConstituents(sources[i]); 3325617a3babSopenharmony_ci else if (isMatrix(sources[i])) 3326617a3babSopenharmony_ci accumulateMatrixConstituents(sources[i]); 3327617a3babSopenharmony_ci else 3328617a3babSopenharmony_ci assert(0); 3329617a3babSopenharmony_ci 3330617a3babSopenharmony_ci if (targetComponent >= numTargetComponents) 3331617a3babSopenharmony_ci break; 3332617a3babSopenharmony_ci } 3333617a3babSopenharmony_ci 3334617a3babSopenharmony_ci // If the result is a vector, make it from the gathered constituents. 3335617a3babSopenharmony_ci if (constituents.size() > 0) 3336617a3babSopenharmony_ci result = createCompositeConstruct(resultTypeId, constituents); 3337617a3babSopenharmony_ci 3338617a3babSopenharmony_ci return setPrecision(result, precision); 3339617a3babSopenharmony_ci} 3340617a3babSopenharmony_ci 3341617a3babSopenharmony_ci// Comments in header 3342617a3babSopenharmony_ciId Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId) 3343617a3babSopenharmony_ci{ 3344617a3babSopenharmony_ci Id componentTypeId = getScalarTypeId(resultTypeId); 3345617a3babSopenharmony_ci int numCols = getTypeNumColumns(resultTypeId); 3346617a3babSopenharmony_ci int numRows = getTypeNumRows(resultTypeId); 3347617a3babSopenharmony_ci 3348617a3babSopenharmony_ci Instruction* instr = module.getInstruction(componentTypeId); 3349617a3babSopenharmony_ci const unsigned bitCount = instr->getImmediateOperand(0); 3350617a3babSopenharmony_ci 3351617a3babSopenharmony_ci // Optimize matrix constructed from a bigger matrix 3352617a3babSopenharmony_ci if (isMatrix(sources[0]) && getNumColumns(sources[0]) >= numCols && getNumRows(sources[0]) >= numRows) { 3353617a3babSopenharmony_ci // To truncate the matrix to a smaller number of rows/columns, we need to: 3354617a3babSopenharmony_ci // 1. For each column, extract the column and truncate it to the required size using shuffle 3355617a3babSopenharmony_ci // 2. Assemble the resulting matrix from all columns 3356617a3babSopenharmony_ci Id matrix = sources[0]; 3357617a3babSopenharmony_ci Id columnTypeId = getContainedTypeId(resultTypeId); 3358617a3babSopenharmony_ci Id sourceColumnTypeId = getContainedTypeId(getTypeId(matrix)); 3359617a3babSopenharmony_ci 3360617a3babSopenharmony_ci std::vector<unsigned> channels; 3361617a3babSopenharmony_ci for (int row = 0; row < numRows; ++row) 3362617a3babSopenharmony_ci channels.push_back(row); 3363617a3babSopenharmony_ci 3364617a3babSopenharmony_ci std::vector<Id> matrixColumns; 3365617a3babSopenharmony_ci for (int col = 0; col < numCols; ++col) { 3366617a3babSopenharmony_ci std::vector<unsigned> indexes; 3367617a3babSopenharmony_ci indexes.push_back(col); 3368617a3babSopenharmony_ci Id colv = createCompositeExtract(matrix, sourceColumnTypeId, indexes); 3369617a3babSopenharmony_ci setPrecision(colv, precision); 3370617a3babSopenharmony_ci 3371617a3babSopenharmony_ci if (numRows != getNumRows(matrix)) { 3372617a3babSopenharmony_ci matrixColumns.push_back(createRvalueSwizzle(precision, columnTypeId, colv, channels)); 3373617a3babSopenharmony_ci } else { 3374617a3babSopenharmony_ci matrixColumns.push_back(colv); 3375617a3babSopenharmony_ci } 3376617a3babSopenharmony_ci } 3377617a3babSopenharmony_ci 3378617a3babSopenharmony_ci return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision); 3379617a3babSopenharmony_ci } 3380617a3babSopenharmony_ci 3381617a3babSopenharmony_ci // Otherwise, will use a two step process 3382617a3babSopenharmony_ci // 1. make a compile-time 2D array of values 3383617a3babSopenharmony_ci // 2. construct a matrix from that array 3384617a3babSopenharmony_ci 3385617a3babSopenharmony_ci // Step 1. 3386617a3babSopenharmony_ci 3387617a3babSopenharmony_ci // initialize the array to the identity matrix 3388617a3babSopenharmony_ci Id ids[maxMatrixSize][maxMatrixSize]; 3389617a3babSopenharmony_ci Id one = (bitCount == 64 ? makeDoubleConstant(1.0) : makeFloatConstant(1.0)); 3390617a3babSopenharmony_ci Id zero = (bitCount == 64 ? makeDoubleConstant(0.0) : makeFloatConstant(0.0)); 3391617a3babSopenharmony_ci for (int col = 0; col < 4; ++col) { 3392617a3babSopenharmony_ci for (int row = 0; row < 4; ++row) { 3393617a3babSopenharmony_ci if (col == row) 3394617a3babSopenharmony_ci ids[col][row] = one; 3395617a3babSopenharmony_ci else 3396617a3babSopenharmony_ci ids[col][row] = zero; 3397617a3babSopenharmony_ci } 3398617a3babSopenharmony_ci } 3399617a3babSopenharmony_ci 3400617a3babSopenharmony_ci // modify components as dictated by the arguments 3401617a3babSopenharmony_ci if (sources.size() == 1 && isScalar(sources[0])) { 3402617a3babSopenharmony_ci // a single scalar; resets the diagonals 3403617a3babSopenharmony_ci for (int col = 0; col < 4; ++col) 3404617a3babSopenharmony_ci ids[col][col] = sources[0]; 3405617a3babSopenharmony_ci } else if (isMatrix(sources[0])) { 3406617a3babSopenharmony_ci // constructing from another matrix; copy over the parts that exist in both the argument and constructee 3407617a3babSopenharmony_ci Id matrix = sources[0]; 3408617a3babSopenharmony_ci int minCols = std::min(numCols, getNumColumns(matrix)); 3409617a3babSopenharmony_ci int minRows = std::min(numRows, getNumRows(matrix)); 3410617a3babSopenharmony_ci for (int col = 0; col < minCols; ++col) { 3411617a3babSopenharmony_ci std::vector<unsigned> indexes; 3412617a3babSopenharmony_ci indexes.push_back(col); 3413617a3babSopenharmony_ci for (int row = 0; row < minRows; ++row) { 3414617a3babSopenharmony_ci indexes.push_back(row); 3415617a3babSopenharmony_ci ids[col][row] = createCompositeExtract(matrix, componentTypeId, indexes); 3416617a3babSopenharmony_ci indexes.pop_back(); 3417617a3babSopenharmony_ci setPrecision(ids[col][row], precision); 3418617a3babSopenharmony_ci } 3419617a3babSopenharmony_ci } 3420617a3babSopenharmony_ci } else { 3421617a3babSopenharmony_ci // fill in the matrix in column-major order with whatever argument components are available 3422617a3babSopenharmony_ci int row = 0; 3423617a3babSopenharmony_ci int col = 0; 3424617a3babSopenharmony_ci 3425617a3babSopenharmony_ci for (int arg = 0; arg < (int)sources.size() && col < numCols; ++arg) { 3426617a3babSopenharmony_ci Id argComp = sources[arg]; 3427617a3babSopenharmony_ci for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) { 3428617a3babSopenharmony_ci if (getNumComponents(sources[arg]) > 1) { 3429617a3babSopenharmony_ci argComp = createCompositeExtract(sources[arg], componentTypeId, comp); 3430617a3babSopenharmony_ci setPrecision(argComp, precision); 3431617a3babSopenharmony_ci } 3432617a3babSopenharmony_ci ids[col][row++] = argComp; 3433617a3babSopenharmony_ci if (row == numRows) { 3434617a3babSopenharmony_ci row = 0; 3435617a3babSopenharmony_ci col++; 3436617a3babSopenharmony_ci } 3437617a3babSopenharmony_ci if (col == numCols) { 3438617a3babSopenharmony_ci // If more components are provided than fit the matrix, discard the rest. 3439617a3babSopenharmony_ci break; 3440617a3babSopenharmony_ci } 3441617a3babSopenharmony_ci } 3442617a3babSopenharmony_ci } 3443617a3babSopenharmony_ci } 3444617a3babSopenharmony_ci 3445617a3babSopenharmony_ci // Step 2: Construct a matrix from that array. 3446617a3babSopenharmony_ci // First make the column vectors, then make the matrix. 3447617a3babSopenharmony_ci 3448617a3babSopenharmony_ci // make the column vectors 3449617a3babSopenharmony_ci Id columnTypeId = getContainedTypeId(resultTypeId); 3450617a3babSopenharmony_ci std::vector<Id> matrixColumns; 3451617a3babSopenharmony_ci for (int col = 0; col < numCols; ++col) { 3452617a3babSopenharmony_ci std::vector<Id> vectorComponents; 3453617a3babSopenharmony_ci for (int row = 0; row < numRows; ++row) 3454617a3babSopenharmony_ci vectorComponents.push_back(ids[col][row]); 3455617a3babSopenharmony_ci Id column = createCompositeConstruct(columnTypeId, vectorComponents); 3456617a3babSopenharmony_ci setPrecision(column, precision); 3457617a3babSopenharmony_ci matrixColumns.push_back(column); 3458617a3babSopenharmony_ci } 3459617a3babSopenharmony_ci 3460617a3babSopenharmony_ci // make the matrix 3461617a3babSopenharmony_ci return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision); 3462617a3babSopenharmony_ci} 3463617a3babSopenharmony_ci 3464617a3babSopenharmony_ci// Comments in header 3465617a3babSopenharmony_ciBuilder::If::If(Id cond, unsigned int ctrl, Builder& gb) : 3466617a3babSopenharmony_ci builder(gb), 3467617a3babSopenharmony_ci condition(cond), 3468617a3babSopenharmony_ci control(ctrl), 3469617a3babSopenharmony_ci elseBlock(nullptr) 3470617a3babSopenharmony_ci{ 3471617a3babSopenharmony_ci function = &builder.getBuildPoint()->getParent(); 3472617a3babSopenharmony_ci 3473617a3babSopenharmony_ci // make the blocks, but only put the then-block into the function, 3474617a3babSopenharmony_ci // the else-block and merge-block will be added later, in order, after 3475617a3babSopenharmony_ci // earlier code is emitted 3476617a3babSopenharmony_ci thenBlock = new Block(builder.getUniqueId(), *function); 3477617a3babSopenharmony_ci mergeBlock = new Block(builder.getUniqueId(), *function); 3478617a3babSopenharmony_ci 3479617a3babSopenharmony_ci // Save the current block, so that we can add in the flow control split when 3480617a3babSopenharmony_ci // makeEndIf is called. 3481617a3babSopenharmony_ci headerBlock = builder.getBuildPoint(); 3482617a3babSopenharmony_ci 3483617a3babSopenharmony_ci function->addBlock(thenBlock); 3484617a3babSopenharmony_ci builder.setBuildPoint(thenBlock); 3485617a3babSopenharmony_ci} 3486617a3babSopenharmony_ci 3487617a3babSopenharmony_ci// Comments in header 3488617a3babSopenharmony_civoid Builder::If::makeBeginElse() 3489617a3babSopenharmony_ci{ 3490617a3babSopenharmony_ci // Close out the "then" by having it jump to the mergeBlock 3491617a3babSopenharmony_ci builder.createBranch(mergeBlock); 3492617a3babSopenharmony_ci 3493617a3babSopenharmony_ci // Make the first else block and add it to the function 3494617a3babSopenharmony_ci elseBlock = new Block(builder.getUniqueId(), *function); 3495617a3babSopenharmony_ci function->addBlock(elseBlock); 3496617a3babSopenharmony_ci 3497617a3babSopenharmony_ci // Start building the else block 3498617a3babSopenharmony_ci builder.setBuildPoint(elseBlock); 3499617a3babSopenharmony_ci} 3500617a3babSopenharmony_ci 3501617a3babSopenharmony_ci// Comments in header 3502617a3babSopenharmony_civoid Builder::If::makeEndIf() 3503617a3babSopenharmony_ci{ 3504617a3babSopenharmony_ci // jump to the merge block 3505617a3babSopenharmony_ci builder.createBranch(mergeBlock); 3506617a3babSopenharmony_ci 3507617a3babSopenharmony_ci // Go back to the headerBlock and make the flow control split 3508617a3babSopenharmony_ci builder.setBuildPoint(headerBlock); 3509617a3babSopenharmony_ci builder.createSelectionMerge(mergeBlock, control); 3510617a3babSopenharmony_ci if (elseBlock) 3511617a3babSopenharmony_ci builder.createConditionalBranch(condition, thenBlock, elseBlock); 3512617a3babSopenharmony_ci else 3513617a3babSopenharmony_ci builder.createConditionalBranch(condition, thenBlock, mergeBlock); 3514617a3babSopenharmony_ci 3515617a3babSopenharmony_ci // add the merge block to the function 3516617a3babSopenharmony_ci function->addBlock(mergeBlock); 3517617a3babSopenharmony_ci builder.setBuildPoint(mergeBlock); 3518617a3babSopenharmony_ci} 3519617a3babSopenharmony_ci 3520617a3babSopenharmony_ci// Comments in header 3521617a3babSopenharmony_civoid Builder::makeSwitch(Id selector, unsigned int control, int numSegments, const std::vector<int>& caseValues, 3522617a3babSopenharmony_ci const std::vector<int>& valueIndexToSegment, int defaultSegment, 3523617a3babSopenharmony_ci std::vector<Block*>& segmentBlocks) 3524617a3babSopenharmony_ci{ 3525617a3babSopenharmony_ci Function& function = buildPoint->getParent(); 3526617a3babSopenharmony_ci 3527617a3babSopenharmony_ci // make all the blocks 3528617a3babSopenharmony_ci for (int s = 0; s < numSegments; ++s) 3529617a3babSopenharmony_ci segmentBlocks.push_back(new Block(getUniqueId(), function)); 3530617a3babSopenharmony_ci 3531617a3babSopenharmony_ci Block* mergeBlock = new Block(getUniqueId(), function); 3532617a3babSopenharmony_ci 3533617a3babSopenharmony_ci // make and insert the switch's selection-merge instruction 3534617a3babSopenharmony_ci createSelectionMerge(mergeBlock, control); 3535617a3babSopenharmony_ci 3536617a3babSopenharmony_ci // make the switch instruction 3537617a3babSopenharmony_ci Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch); 3538617a3babSopenharmony_ci switchInst->addIdOperand(selector); 3539617a3babSopenharmony_ci auto defaultOrMerge = (defaultSegment >= 0) ? segmentBlocks[defaultSegment] : mergeBlock; 3540617a3babSopenharmony_ci switchInst->addIdOperand(defaultOrMerge->getId()); 3541617a3babSopenharmony_ci defaultOrMerge->addPredecessor(buildPoint); 3542617a3babSopenharmony_ci for (int i = 0; i < (int)caseValues.size(); ++i) { 3543617a3babSopenharmony_ci switchInst->addImmediateOperand(caseValues[i]); 3544617a3babSopenharmony_ci switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId()); 3545617a3babSopenharmony_ci segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint); 3546617a3babSopenharmony_ci } 3547617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(switchInst)); 3548617a3babSopenharmony_ci 3549617a3babSopenharmony_ci // push the merge block 3550617a3babSopenharmony_ci switchMerges.push(mergeBlock); 3551617a3babSopenharmony_ci} 3552617a3babSopenharmony_ci 3553617a3babSopenharmony_ci// Comments in header 3554617a3babSopenharmony_civoid Builder::addSwitchBreak() 3555617a3babSopenharmony_ci{ 3556617a3babSopenharmony_ci // branch to the top of the merge block stack 3557617a3babSopenharmony_ci createBranch(switchMerges.top()); 3558617a3babSopenharmony_ci createAndSetNoPredecessorBlock("post-switch-break"); 3559617a3babSopenharmony_ci} 3560617a3babSopenharmony_ci 3561617a3babSopenharmony_ci// Comments in header 3562617a3babSopenharmony_civoid Builder::nextSwitchSegment(std::vector<Block*>& segmentBlock, int nextSegment) 3563617a3babSopenharmony_ci{ 3564617a3babSopenharmony_ci int lastSegment = nextSegment - 1; 3565617a3babSopenharmony_ci if (lastSegment >= 0) { 3566617a3babSopenharmony_ci // Close out previous segment by jumping, if necessary, to next segment 3567617a3babSopenharmony_ci if (! buildPoint->isTerminated()) 3568617a3babSopenharmony_ci createBranch(segmentBlock[nextSegment]); 3569617a3babSopenharmony_ci } 3570617a3babSopenharmony_ci Block* block = segmentBlock[nextSegment]; 3571617a3babSopenharmony_ci block->getParent().addBlock(block); 3572617a3babSopenharmony_ci setBuildPoint(block); 3573617a3babSopenharmony_ci} 3574617a3babSopenharmony_ci 3575617a3babSopenharmony_ci// Comments in header 3576617a3babSopenharmony_civoid Builder::endSwitch(std::vector<Block*>& /*segmentBlock*/) 3577617a3babSopenharmony_ci{ 3578617a3babSopenharmony_ci // Close out previous segment by jumping, if necessary, to next segment 3579617a3babSopenharmony_ci if (! buildPoint->isTerminated()) 3580617a3babSopenharmony_ci addSwitchBreak(); 3581617a3babSopenharmony_ci 3582617a3babSopenharmony_ci switchMerges.top()->getParent().addBlock(switchMerges.top()); 3583617a3babSopenharmony_ci setBuildPoint(switchMerges.top()); 3584617a3babSopenharmony_ci 3585617a3babSopenharmony_ci switchMerges.pop(); 3586617a3babSopenharmony_ci} 3587617a3babSopenharmony_ci 3588617a3babSopenharmony_ciBlock& Builder::makeNewBlock() 3589617a3babSopenharmony_ci{ 3590617a3babSopenharmony_ci Function& function = buildPoint->getParent(); 3591617a3babSopenharmony_ci auto block = new Block(getUniqueId(), function); 3592617a3babSopenharmony_ci function.addBlock(block); 3593617a3babSopenharmony_ci return *block; 3594617a3babSopenharmony_ci} 3595617a3babSopenharmony_ci 3596617a3babSopenharmony_ciBuilder::LoopBlocks& Builder::makeNewLoop() 3597617a3babSopenharmony_ci{ 3598617a3babSopenharmony_ci // This verbosity is needed to simultaneously get the same behavior 3599617a3babSopenharmony_ci // everywhere (id's in the same order), have a syntax that works 3600617a3babSopenharmony_ci // across lots of versions of C++, have no warnings from pedantic 3601617a3babSopenharmony_ci // compilation modes, and leave the rest of the code alone. 3602617a3babSopenharmony_ci Block& head = makeNewBlock(); 3603617a3babSopenharmony_ci Block& body = makeNewBlock(); 3604617a3babSopenharmony_ci Block& merge = makeNewBlock(); 3605617a3babSopenharmony_ci Block& continue_target = makeNewBlock(); 3606617a3babSopenharmony_ci LoopBlocks blocks(head, body, merge, continue_target); 3607617a3babSopenharmony_ci loops.push(blocks); 3608617a3babSopenharmony_ci return loops.top(); 3609617a3babSopenharmony_ci} 3610617a3babSopenharmony_ci 3611617a3babSopenharmony_civoid Builder::createLoopContinue() 3612617a3babSopenharmony_ci{ 3613617a3babSopenharmony_ci createBranch(&loops.top().continue_target); 3614617a3babSopenharmony_ci // Set up a block for dead code. 3615617a3babSopenharmony_ci createAndSetNoPredecessorBlock("post-loop-continue"); 3616617a3babSopenharmony_ci} 3617617a3babSopenharmony_ci 3618617a3babSopenharmony_civoid Builder::createLoopExit() 3619617a3babSopenharmony_ci{ 3620617a3babSopenharmony_ci createBranch(&loops.top().merge); 3621617a3babSopenharmony_ci // Set up a block for dead code. 3622617a3babSopenharmony_ci createAndSetNoPredecessorBlock("post-loop-break"); 3623617a3babSopenharmony_ci} 3624617a3babSopenharmony_ci 3625617a3babSopenharmony_civoid Builder::closeLoop() 3626617a3babSopenharmony_ci{ 3627617a3babSopenharmony_ci loops.pop(); 3628617a3babSopenharmony_ci} 3629617a3babSopenharmony_ci 3630617a3babSopenharmony_civoid Builder::clearAccessChain() 3631617a3babSopenharmony_ci{ 3632617a3babSopenharmony_ci accessChain.base = NoResult; 3633617a3babSopenharmony_ci accessChain.indexChain.clear(); 3634617a3babSopenharmony_ci accessChain.instr = NoResult; 3635617a3babSopenharmony_ci accessChain.swizzle.clear(); 3636617a3babSopenharmony_ci accessChain.component = NoResult; 3637617a3babSopenharmony_ci accessChain.preSwizzleBaseType = NoType; 3638617a3babSopenharmony_ci accessChain.isRValue = false; 3639617a3babSopenharmony_ci accessChain.coherentFlags.clear(); 3640617a3babSopenharmony_ci accessChain.alignment = 0; 3641617a3babSopenharmony_ci} 3642617a3babSopenharmony_ci 3643617a3babSopenharmony_ci// Comments in header 3644617a3babSopenharmony_civoid Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, 3645617a3babSopenharmony_ci AccessChain::CoherentFlags coherentFlags, unsigned int alignment) 3646617a3babSopenharmony_ci{ 3647617a3babSopenharmony_ci accessChain.coherentFlags |= coherentFlags; 3648617a3babSopenharmony_ci accessChain.alignment |= alignment; 3649617a3babSopenharmony_ci 3650617a3babSopenharmony_ci // swizzles can be stacked in GLSL, but simplified to a single 3651617a3babSopenharmony_ci // one here; the base type doesn't change 3652617a3babSopenharmony_ci if (accessChain.preSwizzleBaseType == NoType) 3653617a3babSopenharmony_ci accessChain.preSwizzleBaseType = preSwizzleBaseType; 3654617a3babSopenharmony_ci 3655617a3babSopenharmony_ci // if needed, propagate the swizzle for the current access chain 3656617a3babSopenharmony_ci if (accessChain.swizzle.size() > 0) { 3657617a3babSopenharmony_ci std::vector<unsigned> oldSwizzle = accessChain.swizzle; 3658617a3babSopenharmony_ci accessChain.swizzle.resize(0); 3659617a3babSopenharmony_ci for (unsigned int i = 0; i < swizzle.size(); ++i) { 3660617a3babSopenharmony_ci assert(swizzle[i] < oldSwizzle.size()); 3661617a3babSopenharmony_ci accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]); 3662617a3babSopenharmony_ci } 3663617a3babSopenharmony_ci } else 3664617a3babSopenharmony_ci accessChain.swizzle = swizzle; 3665617a3babSopenharmony_ci 3666617a3babSopenharmony_ci // determine if we need to track this swizzle anymore 3667617a3babSopenharmony_ci simplifyAccessChainSwizzle(); 3668617a3babSopenharmony_ci} 3669617a3babSopenharmony_ci 3670617a3babSopenharmony_ci// Comments in header 3671617a3babSopenharmony_civoid Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) 3672617a3babSopenharmony_ci{ 3673617a3babSopenharmony_ci assert(accessChain.isRValue == false); 3674617a3babSopenharmony_ci 3675617a3babSopenharmony_ci transferAccessChainSwizzle(true); 3676617a3babSopenharmony_ci 3677617a3babSopenharmony_ci // If a swizzle exists and is not full and is not dynamic, then the swizzle will be broken into individual stores. 3678617a3babSopenharmony_ci if (accessChain.swizzle.size() > 0 && 3679617a3babSopenharmony_ci getNumTypeComponents(getResultingAccessChainType()) != (int)accessChain.swizzle.size() && 3680617a3babSopenharmony_ci accessChain.component == NoResult) { 3681617a3babSopenharmony_ci for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) { 3682617a3babSopenharmony_ci accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle[i])); 3683617a3babSopenharmony_ci accessChain.instr = NoResult; 3684617a3babSopenharmony_ci 3685617a3babSopenharmony_ci Id base = collapseAccessChain(); 3686617a3babSopenharmony_ci addDecoration(base, nonUniform); 3687617a3babSopenharmony_ci 3688617a3babSopenharmony_ci accessChain.indexChain.pop_back(); 3689617a3babSopenharmony_ci accessChain.instr = NoResult; 3690617a3babSopenharmony_ci 3691617a3babSopenharmony_ci // dynamic component should be gone 3692617a3babSopenharmony_ci assert(accessChain.component == NoResult); 3693617a3babSopenharmony_ci 3694617a3babSopenharmony_ci Id source = createCompositeExtract(rvalue, getContainedTypeId(getTypeId(rvalue)), i); 3695617a3babSopenharmony_ci 3696617a3babSopenharmony_ci // take LSB of alignment 3697617a3babSopenharmony_ci alignment = alignment & ~(alignment & (alignment-1)); 3698617a3babSopenharmony_ci if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) { 3699617a3babSopenharmony_ci memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); 3700617a3babSopenharmony_ci } 3701617a3babSopenharmony_ci 3702617a3babSopenharmony_ci createStore(source, base, memoryAccess, scope, alignment); 3703617a3babSopenharmony_ci } 3704617a3babSopenharmony_ci } 3705617a3babSopenharmony_ci else { 3706617a3babSopenharmony_ci Id base = collapseAccessChain(); 3707617a3babSopenharmony_ci addDecoration(base, nonUniform); 3708617a3babSopenharmony_ci 3709617a3babSopenharmony_ci Id source = rvalue; 3710617a3babSopenharmony_ci 3711617a3babSopenharmony_ci // dynamic component should be gone 3712617a3babSopenharmony_ci assert(accessChain.component == NoResult); 3713617a3babSopenharmony_ci 3714617a3babSopenharmony_ci // If swizzle still exists, it may be out-of-order, we must load the target vector, 3715617a3babSopenharmony_ci // extract and insert elements to perform writeMask and/or swizzle. 3716617a3babSopenharmony_ci if (accessChain.swizzle.size() > 0) { 3717617a3babSopenharmony_ci Id tempBaseId = createLoad(base, spv::NoPrecision); 3718617a3babSopenharmony_ci source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle); 3719617a3babSopenharmony_ci } 3720617a3babSopenharmony_ci 3721617a3babSopenharmony_ci // take LSB of alignment 3722617a3babSopenharmony_ci alignment = alignment & ~(alignment & (alignment-1)); 3723617a3babSopenharmony_ci if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) { 3724617a3babSopenharmony_ci memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); 3725617a3babSopenharmony_ci } 3726617a3babSopenharmony_ci 3727617a3babSopenharmony_ci createStore(source, base, memoryAccess, scope, alignment); 3728617a3babSopenharmony_ci } 3729617a3babSopenharmony_ci} 3730617a3babSopenharmony_ci 3731617a3babSopenharmony_ci// Comments in header 3732617a3babSopenharmony_ciId Builder::accessChainLoad(Decoration precision, Decoration l_nonUniform, 3733617a3babSopenharmony_ci Decoration r_nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, 3734617a3babSopenharmony_ci spv::Scope scope, unsigned int alignment) 3735617a3babSopenharmony_ci{ 3736617a3babSopenharmony_ci Id id; 3737617a3babSopenharmony_ci 3738617a3babSopenharmony_ci if (accessChain.isRValue) { 3739617a3babSopenharmony_ci // transfer access chain, but try to stay in registers 3740617a3babSopenharmony_ci transferAccessChainSwizzle(false); 3741617a3babSopenharmony_ci if (accessChain.indexChain.size() > 0) { 3742617a3babSopenharmony_ci Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType; 3743617a3babSopenharmony_ci 3744617a3babSopenharmony_ci // if all the accesses are constants, we can use OpCompositeExtract 3745617a3babSopenharmony_ci std::vector<unsigned> indexes; 3746617a3babSopenharmony_ci bool constant = true; 3747617a3babSopenharmony_ci for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) { 3748617a3babSopenharmony_ci if (isConstantScalar(accessChain.indexChain[i])) 3749617a3babSopenharmony_ci indexes.push_back(getConstantScalar(accessChain.indexChain[i])); 3750617a3babSopenharmony_ci else { 3751617a3babSopenharmony_ci constant = false; 3752617a3babSopenharmony_ci break; 3753617a3babSopenharmony_ci } 3754617a3babSopenharmony_ci } 3755617a3babSopenharmony_ci 3756617a3babSopenharmony_ci if (constant) { 3757617a3babSopenharmony_ci id = createCompositeExtract(accessChain.base, swizzleBase, indexes); 3758617a3babSopenharmony_ci setPrecision(id, precision); 3759617a3babSopenharmony_ci } else { 3760617a3babSopenharmony_ci Id lValue = NoResult; 3761617a3babSopenharmony_ci if (spvVersion >= Spv_1_4 && isValidInitializer(accessChain.base)) { 3762617a3babSopenharmony_ci // make a new function variable for this r-value, using an initializer, 3763617a3babSopenharmony_ci // and mark it as NonWritable so that downstream it can be detected as a lookup 3764617a3babSopenharmony_ci // table 3765617a3babSopenharmony_ci lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base), 3766617a3babSopenharmony_ci "indexable", accessChain.base); 3767617a3babSopenharmony_ci addDecoration(lValue, DecorationNonWritable); 3768617a3babSopenharmony_ci } else { 3769617a3babSopenharmony_ci lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base), 3770617a3babSopenharmony_ci "indexable"); 3771617a3babSopenharmony_ci // store into it 3772617a3babSopenharmony_ci createStore(accessChain.base, lValue); 3773617a3babSopenharmony_ci } 3774617a3babSopenharmony_ci // move base to the new variable 3775617a3babSopenharmony_ci accessChain.base = lValue; 3776617a3babSopenharmony_ci accessChain.isRValue = false; 3777617a3babSopenharmony_ci 3778617a3babSopenharmony_ci // load through the access chain 3779617a3babSopenharmony_ci id = createLoad(collapseAccessChain(), precision); 3780617a3babSopenharmony_ci } 3781617a3babSopenharmony_ci } else 3782617a3babSopenharmony_ci id = accessChain.base; // no precision, it was set when this was defined 3783617a3babSopenharmony_ci } else { 3784617a3babSopenharmony_ci transferAccessChainSwizzle(true); 3785617a3babSopenharmony_ci 3786617a3babSopenharmony_ci // take LSB of alignment 3787617a3babSopenharmony_ci alignment = alignment & ~(alignment & (alignment-1)); 3788617a3babSopenharmony_ci if (getStorageClass(accessChain.base) == StorageClassPhysicalStorageBufferEXT) { 3789617a3babSopenharmony_ci memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); 3790617a3babSopenharmony_ci } 3791617a3babSopenharmony_ci 3792617a3babSopenharmony_ci // load through the access chain 3793617a3babSopenharmony_ci id = collapseAccessChain(); 3794617a3babSopenharmony_ci // Apply nonuniform both to the access chain and the loaded value. 3795617a3babSopenharmony_ci // Buffer accesses need the access chain decorated, and this is where 3796617a3babSopenharmony_ci // loaded image types get decorated. TODO: This should maybe move to 3797617a3babSopenharmony_ci // createImageTextureFunctionCall. 3798617a3babSopenharmony_ci addDecoration(id, l_nonUniform); 3799617a3babSopenharmony_ci id = createLoad(id, precision, memoryAccess, scope, alignment); 3800617a3babSopenharmony_ci addDecoration(id, r_nonUniform); 3801617a3babSopenharmony_ci } 3802617a3babSopenharmony_ci 3803617a3babSopenharmony_ci // Done, unless there are swizzles to do 3804617a3babSopenharmony_ci if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult) 3805617a3babSopenharmony_ci return id; 3806617a3babSopenharmony_ci 3807617a3babSopenharmony_ci // Do remaining swizzling 3808617a3babSopenharmony_ci 3809617a3babSopenharmony_ci // Do the basic swizzle 3810617a3babSopenharmony_ci if (accessChain.swizzle.size() > 0) { 3811617a3babSopenharmony_ci Id swizzledType = getScalarTypeId(getTypeId(id)); 3812617a3babSopenharmony_ci if (accessChain.swizzle.size() > 1) 3813617a3babSopenharmony_ci swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size()); 3814617a3babSopenharmony_ci id = createRvalueSwizzle(precision, swizzledType, id, accessChain.swizzle); 3815617a3babSopenharmony_ci } 3816617a3babSopenharmony_ci 3817617a3babSopenharmony_ci // Do the dynamic component 3818617a3babSopenharmony_ci if (accessChain.component != NoResult) 3819617a3babSopenharmony_ci id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision); 3820617a3babSopenharmony_ci 3821617a3babSopenharmony_ci addDecoration(id, r_nonUniform); 3822617a3babSopenharmony_ci return id; 3823617a3babSopenharmony_ci} 3824617a3babSopenharmony_ci 3825617a3babSopenharmony_ciId Builder::accessChainGetLValue() 3826617a3babSopenharmony_ci{ 3827617a3babSopenharmony_ci assert(accessChain.isRValue == false); 3828617a3babSopenharmony_ci 3829617a3babSopenharmony_ci transferAccessChainSwizzle(true); 3830617a3babSopenharmony_ci Id lvalue = collapseAccessChain(); 3831617a3babSopenharmony_ci 3832617a3babSopenharmony_ci // If swizzle exists, it is out-of-order or not full, we must load the target vector, 3833617a3babSopenharmony_ci // extract and insert elements to perform writeMask and/or swizzle. This does not 3834617a3babSopenharmony_ci // go with getting a direct l-value pointer. 3835617a3babSopenharmony_ci assert(accessChain.swizzle.size() == 0); 3836617a3babSopenharmony_ci assert(accessChain.component == NoResult); 3837617a3babSopenharmony_ci 3838617a3babSopenharmony_ci return lvalue; 3839617a3babSopenharmony_ci} 3840617a3babSopenharmony_ci 3841617a3babSopenharmony_ci// comment in header 3842617a3babSopenharmony_ciId Builder::accessChainGetInferredType() 3843617a3babSopenharmony_ci{ 3844617a3babSopenharmony_ci // anything to operate on? 3845617a3babSopenharmony_ci if (accessChain.base == NoResult) 3846617a3babSopenharmony_ci return NoType; 3847617a3babSopenharmony_ci Id type = getTypeId(accessChain.base); 3848617a3babSopenharmony_ci 3849617a3babSopenharmony_ci // do initial dereference 3850617a3babSopenharmony_ci if (! accessChain.isRValue) 3851617a3babSopenharmony_ci type = getContainedTypeId(type); 3852617a3babSopenharmony_ci 3853617a3babSopenharmony_ci // dereference each index 3854617a3babSopenharmony_ci for (auto it = accessChain.indexChain.cbegin(); it != accessChain.indexChain.cend(); ++it) { 3855617a3babSopenharmony_ci if (isStructType(type)) 3856617a3babSopenharmony_ci type = getContainedTypeId(type, getConstantScalar(*it)); 3857617a3babSopenharmony_ci else 3858617a3babSopenharmony_ci type = getContainedTypeId(type); 3859617a3babSopenharmony_ci } 3860617a3babSopenharmony_ci 3861617a3babSopenharmony_ci // dereference swizzle 3862617a3babSopenharmony_ci if (accessChain.swizzle.size() == 1) 3863617a3babSopenharmony_ci type = getContainedTypeId(type); 3864617a3babSopenharmony_ci else if (accessChain.swizzle.size() > 1) 3865617a3babSopenharmony_ci type = makeVectorType(getContainedTypeId(type), (int)accessChain.swizzle.size()); 3866617a3babSopenharmony_ci 3867617a3babSopenharmony_ci // dereference component selection 3868617a3babSopenharmony_ci if (accessChain.component) 3869617a3babSopenharmony_ci type = getContainedTypeId(type); 3870617a3babSopenharmony_ci 3871617a3babSopenharmony_ci return type; 3872617a3babSopenharmony_ci} 3873617a3babSopenharmony_ci 3874617a3babSopenharmony_civoid Builder::dump(std::vector<unsigned int>& out) const 3875617a3babSopenharmony_ci{ 3876617a3babSopenharmony_ci // Header, before first instructions: 3877617a3babSopenharmony_ci out.push_back(MagicNumber); 3878617a3babSopenharmony_ci out.push_back(spvVersion); 3879617a3babSopenharmony_ci out.push_back(builderNumber); 3880617a3babSopenharmony_ci out.push_back(uniqueId + 1); 3881617a3babSopenharmony_ci out.push_back(0); 3882617a3babSopenharmony_ci 3883617a3babSopenharmony_ci // Capabilities 3884617a3babSopenharmony_ci for (auto it = capabilities.cbegin(); it != capabilities.cend(); ++it) { 3885617a3babSopenharmony_ci Instruction capInst(0, 0, OpCapability); 3886617a3babSopenharmony_ci capInst.addImmediateOperand(*it); 3887617a3babSopenharmony_ci capInst.dump(out); 3888617a3babSopenharmony_ci } 3889617a3babSopenharmony_ci 3890617a3babSopenharmony_ci for (auto it = extensions.cbegin(); it != extensions.cend(); ++it) { 3891617a3babSopenharmony_ci Instruction extInst(0, 0, OpExtension); 3892617a3babSopenharmony_ci extInst.addStringOperand(it->c_str()); 3893617a3babSopenharmony_ci extInst.dump(out); 3894617a3babSopenharmony_ci } 3895617a3babSopenharmony_ci 3896617a3babSopenharmony_ci dumpInstructions(out, imports); 3897617a3babSopenharmony_ci Instruction memInst(0, 0, OpMemoryModel); 3898617a3babSopenharmony_ci memInst.addImmediateOperand(addressModel); 3899617a3babSopenharmony_ci memInst.addImmediateOperand(memoryModel); 3900617a3babSopenharmony_ci memInst.dump(out); 3901617a3babSopenharmony_ci 3902617a3babSopenharmony_ci // Instructions saved up while building: 3903617a3babSopenharmony_ci dumpInstructions(out, entryPoints); 3904617a3babSopenharmony_ci dumpInstructions(out, executionModes); 3905617a3babSopenharmony_ci 3906617a3babSopenharmony_ci // Debug instructions 3907617a3babSopenharmony_ci dumpInstructions(out, strings); 3908617a3babSopenharmony_ci dumpSourceInstructions(out); 3909617a3babSopenharmony_ci for (int e = 0; e < (int)sourceExtensions.size(); ++e) { 3910617a3babSopenharmony_ci Instruction sourceExtInst(0, 0, OpSourceExtension); 3911617a3babSopenharmony_ci sourceExtInst.addStringOperand(sourceExtensions[e]); 3912617a3babSopenharmony_ci sourceExtInst.dump(out); 3913617a3babSopenharmony_ci } 3914617a3babSopenharmony_ci dumpInstructions(out, names); 3915617a3babSopenharmony_ci dumpModuleProcesses(out); 3916617a3babSopenharmony_ci 3917617a3babSopenharmony_ci // Annotation instructions 3918617a3babSopenharmony_ci dumpInstructions(out, decorations); 3919617a3babSopenharmony_ci 3920617a3babSopenharmony_ci dumpInstructions(out, constantsTypesGlobals); 3921617a3babSopenharmony_ci dumpInstructions(out, externals); 3922617a3babSopenharmony_ci 3923617a3babSopenharmony_ci // The functions 3924617a3babSopenharmony_ci module.dump(out); 3925617a3babSopenharmony_ci} 3926617a3babSopenharmony_ci 3927617a3babSopenharmony_ci// 3928617a3babSopenharmony_ci// Protected methods. 3929617a3babSopenharmony_ci// 3930617a3babSopenharmony_ci 3931617a3babSopenharmony_ci// Turn the described access chain in 'accessChain' into an instruction(s) 3932617a3babSopenharmony_ci// computing its address. This *cannot* include complex swizzles, which must 3933617a3babSopenharmony_ci// be handled after this is called. 3934617a3babSopenharmony_ci// 3935617a3babSopenharmony_ci// Can generate code. 3936617a3babSopenharmony_ciId Builder::collapseAccessChain() 3937617a3babSopenharmony_ci{ 3938617a3babSopenharmony_ci assert(accessChain.isRValue == false); 3939617a3babSopenharmony_ci 3940617a3babSopenharmony_ci // did we already emit an access chain for this? 3941617a3babSopenharmony_ci if (accessChain.instr != NoResult) 3942617a3babSopenharmony_ci return accessChain.instr; 3943617a3babSopenharmony_ci 3944617a3babSopenharmony_ci // If we have a dynamic component, we can still transfer 3945617a3babSopenharmony_ci // that into a final operand to the access chain. We need to remap the 3946617a3babSopenharmony_ci // dynamic component through the swizzle to get a new dynamic component to 3947617a3babSopenharmony_ci // update. 3948617a3babSopenharmony_ci // 3949617a3babSopenharmony_ci // This was not done in transferAccessChainSwizzle() because it might 3950617a3babSopenharmony_ci // generate code. 3951617a3babSopenharmony_ci remapDynamicSwizzle(); 3952617a3babSopenharmony_ci if (accessChain.component != NoResult) { 3953617a3babSopenharmony_ci // transfer the dynamic component to the access chain 3954617a3babSopenharmony_ci accessChain.indexChain.push_back(accessChain.component); 3955617a3babSopenharmony_ci accessChain.component = NoResult; 3956617a3babSopenharmony_ci } 3957617a3babSopenharmony_ci 3958617a3babSopenharmony_ci // note that non-trivial swizzling is left pending 3959617a3babSopenharmony_ci 3960617a3babSopenharmony_ci // do we have an access chain? 3961617a3babSopenharmony_ci if (accessChain.indexChain.size() == 0) 3962617a3babSopenharmony_ci return accessChain.base; 3963617a3babSopenharmony_ci 3964617a3babSopenharmony_ci // emit the access chain 3965617a3babSopenharmony_ci StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base)); 3966617a3babSopenharmony_ci accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain); 3967617a3babSopenharmony_ci 3968617a3babSopenharmony_ci return accessChain.instr; 3969617a3babSopenharmony_ci} 3970617a3babSopenharmony_ci 3971617a3babSopenharmony_ci// For a dynamic component selection of a swizzle. 3972617a3babSopenharmony_ci// 3973617a3babSopenharmony_ci// Turn the swizzle and dynamic component into just a dynamic component. 3974617a3babSopenharmony_ci// 3975617a3babSopenharmony_ci// Generates code. 3976617a3babSopenharmony_civoid Builder::remapDynamicSwizzle() 3977617a3babSopenharmony_ci{ 3978617a3babSopenharmony_ci // do we have a swizzle to remap a dynamic component through? 3979617a3babSopenharmony_ci if (accessChain.component != NoResult && accessChain.swizzle.size() > 1) { 3980617a3babSopenharmony_ci // build a vector of the swizzle for the component to map into 3981617a3babSopenharmony_ci std::vector<Id> components; 3982617a3babSopenharmony_ci for (int c = 0; c < (int)accessChain.swizzle.size(); ++c) 3983617a3babSopenharmony_ci components.push_back(makeUintConstant(accessChain.swizzle[c])); 3984617a3babSopenharmony_ci Id mapType = makeVectorType(makeUintType(32), (int)accessChain.swizzle.size()); 3985617a3babSopenharmony_ci Id map = makeCompositeConstant(mapType, components); 3986617a3babSopenharmony_ci 3987617a3babSopenharmony_ci // use it 3988617a3babSopenharmony_ci accessChain.component = createVectorExtractDynamic(map, makeUintType(32), accessChain.component); 3989617a3babSopenharmony_ci accessChain.swizzle.clear(); 3990617a3babSopenharmony_ci } 3991617a3babSopenharmony_ci} 3992617a3babSopenharmony_ci 3993617a3babSopenharmony_ci// clear out swizzle if it is redundant, that is reselecting the same components 3994617a3babSopenharmony_ci// that would be present without the swizzle. 3995617a3babSopenharmony_civoid Builder::simplifyAccessChainSwizzle() 3996617a3babSopenharmony_ci{ 3997617a3babSopenharmony_ci // If the swizzle has fewer components than the vector, it is subsetting, and must stay 3998617a3babSopenharmony_ci // to preserve that fact. 3999617a3babSopenharmony_ci if (getNumTypeComponents(accessChain.preSwizzleBaseType) > (int)accessChain.swizzle.size()) 4000617a3babSopenharmony_ci return; 4001617a3babSopenharmony_ci 4002617a3babSopenharmony_ci // if components are out of order, it is a swizzle 4003617a3babSopenharmony_ci for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) { 4004617a3babSopenharmony_ci if (i != accessChain.swizzle[i]) 4005617a3babSopenharmony_ci return; 4006617a3babSopenharmony_ci } 4007617a3babSopenharmony_ci 4008617a3babSopenharmony_ci // otherwise, there is no need to track this swizzle 4009617a3babSopenharmony_ci accessChain.swizzle.clear(); 4010617a3babSopenharmony_ci if (accessChain.component == NoResult) 4011617a3babSopenharmony_ci accessChain.preSwizzleBaseType = NoType; 4012617a3babSopenharmony_ci} 4013617a3babSopenharmony_ci 4014617a3babSopenharmony_ci// To the extent any swizzling can become part of the chain 4015617a3babSopenharmony_ci// of accesses instead of a post operation, make it so. 4016617a3babSopenharmony_ci// If 'dynamic' is true, include transferring the dynamic component, 4017617a3babSopenharmony_ci// otherwise, leave it pending. 4018617a3babSopenharmony_ci// 4019617a3babSopenharmony_ci// Does not generate code. just updates the access chain. 4020617a3babSopenharmony_civoid Builder::transferAccessChainSwizzle(bool dynamic) 4021617a3babSopenharmony_ci{ 4022617a3babSopenharmony_ci // non existent? 4023617a3babSopenharmony_ci if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult) 4024617a3babSopenharmony_ci return; 4025617a3babSopenharmony_ci 4026617a3babSopenharmony_ci // too complex? 4027617a3babSopenharmony_ci // (this requires either a swizzle, or generating code for a dynamic component) 4028617a3babSopenharmony_ci if (accessChain.swizzle.size() > 1) 4029617a3babSopenharmony_ci return; 4030617a3babSopenharmony_ci 4031617a3babSopenharmony_ci // single component, either in the swizzle and/or dynamic component 4032617a3babSopenharmony_ci if (accessChain.swizzle.size() == 1) { 4033617a3babSopenharmony_ci assert(accessChain.component == NoResult); 4034617a3babSopenharmony_ci // handle static component selection 4035617a3babSopenharmony_ci accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front())); 4036617a3babSopenharmony_ci accessChain.swizzle.clear(); 4037617a3babSopenharmony_ci accessChain.preSwizzleBaseType = NoType; 4038617a3babSopenharmony_ci } else if (dynamic && accessChain.component != NoResult) { 4039617a3babSopenharmony_ci assert(accessChain.swizzle.size() == 0); 4040617a3babSopenharmony_ci // handle dynamic component 4041617a3babSopenharmony_ci accessChain.indexChain.push_back(accessChain.component); 4042617a3babSopenharmony_ci accessChain.preSwizzleBaseType = NoType; 4043617a3babSopenharmony_ci accessChain.component = NoResult; 4044617a3babSopenharmony_ci } 4045617a3babSopenharmony_ci} 4046617a3babSopenharmony_ci 4047617a3babSopenharmony_ci// Utility method for creating a new block and setting the insert point to 4048617a3babSopenharmony_ci// be in it. This is useful for flow-control operations that need a "dummy" 4049617a3babSopenharmony_ci// block proceeding them (e.g. instructions after a discard, etc). 4050617a3babSopenharmony_civoid Builder::createAndSetNoPredecessorBlock(const char* /*name*/) 4051617a3babSopenharmony_ci{ 4052617a3babSopenharmony_ci Block* block = new Block(getUniqueId(), buildPoint->getParent()); 4053617a3babSopenharmony_ci block->setUnreachable(); 4054617a3babSopenharmony_ci buildPoint->getParent().addBlock(block); 4055617a3babSopenharmony_ci setBuildPoint(block); 4056617a3babSopenharmony_ci 4057617a3babSopenharmony_ci // if (name) 4058617a3babSopenharmony_ci // addName(block->getId(), name); 4059617a3babSopenharmony_ci} 4060617a3babSopenharmony_ci 4061617a3babSopenharmony_ci// Comments in header 4062617a3babSopenharmony_civoid Builder::createBranch(Block* block) 4063617a3babSopenharmony_ci{ 4064617a3babSopenharmony_ci Instruction* branch = new Instruction(OpBranch); 4065617a3babSopenharmony_ci branch->addIdOperand(block->getId()); 4066617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(branch)); 4067617a3babSopenharmony_ci block->addPredecessor(buildPoint); 4068617a3babSopenharmony_ci} 4069617a3babSopenharmony_ci 4070617a3babSopenharmony_civoid Builder::createSelectionMerge(Block* mergeBlock, unsigned int control) 4071617a3babSopenharmony_ci{ 4072617a3babSopenharmony_ci Instruction* merge = new Instruction(OpSelectionMerge); 4073617a3babSopenharmony_ci merge->addIdOperand(mergeBlock->getId()); 4074617a3babSopenharmony_ci merge->addImmediateOperand(control); 4075617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(merge)); 4076617a3babSopenharmony_ci} 4077617a3babSopenharmony_ci 4078617a3babSopenharmony_civoid Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, 4079617a3babSopenharmony_ci const std::vector<unsigned int>& operands) 4080617a3babSopenharmony_ci{ 4081617a3babSopenharmony_ci Instruction* merge = new Instruction(OpLoopMerge); 4082617a3babSopenharmony_ci merge->addIdOperand(mergeBlock->getId()); 4083617a3babSopenharmony_ci merge->addIdOperand(continueBlock->getId()); 4084617a3babSopenharmony_ci merge->addImmediateOperand(control); 4085617a3babSopenharmony_ci for (int op = 0; op < (int)operands.size(); ++op) 4086617a3babSopenharmony_ci merge->addImmediateOperand(operands[op]); 4087617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(merge)); 4088617a3babSopenharmony_ci} 4089617a3babSopenharmony_ci 4090617a3babSopenharmony_civoid Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock) 4091617a3babSopenharmony_ci{ 4092617a3babSopenharmony_ci Instruction* branch = new Instruction(OpBranchConditional); 4093617a3babSopenharmony_ci branch->addIdOperand(condition); 4094617a3babSopenharmony_ci branch->addIdOperand(thenBlock->getId()); 4095617a3babSopenharmony_ci branch->addIdOperand(elseBlock->getId()); 4096617a3babSopenharmony_ci buildPoint->addInstruction(std::unique_ptr<Instruction>(branch)); 4097617a3babSopenharmony_ci thenBlock->addPredecessor(buildPoint); 4098617a3babSopenharmony_ci elseBlock->addPredecessor(buildPoint); 4099617a3babSopenharmony_ci} 4100617a3babSopenharmony_ci 4101617a3babSopenharmony_ci// OpSource 4102617a3babSopenharmony_ci// [OpSourceContinued] 4103617a3babSopenharmony_ci// ... 4104617a3babSopenharmony_civoid Builder::dumpSourceInstructions(const spv::Id fileId, const std::string& text, 4105617a3babSopenharmony_ci std::vector<unsigned int>& out) const 4106617a3babSopenharmony_ci{ 4107617a3babSopenharmony_ci const int maxWordCount = 0xFFFF; 4108617a3babSopenharmony_ci const int opSourceWordCount = 4; 4109617a3babSopenharmony_ci const int nonNullBytesPerInstruction = 4 * (maxWordCount - opSourceWordCount) - 1; 4110617a3babSopenharmony_ci 4111617a3babSopenharmony_ci if (sourceLang != SourceLanguageUnknown) { 4112617a3babSopenharmony_ci // OpSource Language Version File Source 4113617a3babSopenharmony_ci Instruction sourceInst(NoResult, NoType, OpSource); 4114617a3babSopenharmony_ci sourceInst.addImmediateOperand(sourceLang); 4115617a3babSopenharmony_ci sourceInst.addImmediateOperand(sourceVersion); 4116617a3babSopenharmony_ci // File operand 4117617a3babSopenharmony_ci if (fileId != NoResult) { 4118617a3babSopenharmony_ci sourceInst.addIdOperand(fileId); 4119617a3babSopenharmony_ci // Source operand 4120617a3babSopenharmony_ci if (text.size() > 0) { 4121617a3babSopenharmony_ci int nextByte = 0; 4122617a3babSopenharmony_ci std::string subString; 4123617a3babSopenharmony_ci while ((int)text.size() - nextByte > 0) { 4124617a3babSopenharmony_ci subString = text.substr(nextByte, nonNullBytesPerInstruction); 4125617a3babSopenharmony_ci if (nextByte == 0) { 4126617a3babSopenharmony_ci // OpSource 4127617a3babSopenharmony_ci sourceInst.addStringOperand(subString.c_str()); 4128617a3babSopenharmony_ci sourceInst.dump(out); 4129617a3babSopenharmony_ci } else { 4130617a3babSopenharmony_ci // OpSourcContinued 4131617a3babSopenharmony_ci Instruction sourceContinuedInst(OpSourceContinued); 4132617a3babSopenharmony_ci sourceContinuedInst.addStringOperand(subString.c_str()); 4133617a3babSopenharmony_ci sourceContinuedInst.dump(out); 4134617a3babSopenharmony_ci } 4135617a3babSopenharmony_ci nextByte += nonNullBytesPerInstruction; 4136617a3babSopenharmony_ci } 4137617a3babSopenharmony_ci } else 4138617a3babSopenharmony_ci sourceInst.dump(out); 4139617a3babSopenharmony_ci } else 4140617a3babSopenharmony_ci sourceInst.dump(out); 4141617a3babSopenharmony_ci } 4142617a3babSopenharmony_ci} 4143617a3babSopenharmony_ci 4144617a3babSopenharmony_ci// Dump an OpSource[Continued] sequence for the source and every include file 4145617a3babSopenharmony_civoid Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const 4146617a3babSopenharmony_ci{ 4147617a3babSopenharmony_ci if (emitNonSemanticShaderDebugInfo) return; 4148617a3babSopenharmony_ci dumpSourceInstructions(sourceFileStringId, sourceText, out); 4149617a3babSopenharmony_ci for (auto iItr = includeFiles.begin(); iItr != includeFiles.end(); ++iItr) 4150617a3babSopenharmony_ci dumpSourceInstructions(iItr->first, *iItr->second, out); 4151617a3babSopenharmony_ci} 4152617a3babSopenharmony_ci 4153617a3babSopenharmony_civoid Builder::dumpInstructions(std::vector<unsigned int>& out, 4154617a3babSopenharmony_ci const std::vector<std::unique_ptr<Instruction> >& instructions) const 4155617a3babSopenharmony_ci{ 4156617a3babSopenharmony_ci for (int i = 0; i < (int)instructions.size(); ++i) { 4157617a3babSopenharmony_ci instructions[i]->dump(out); 4158617a3babSopenharmony_ci } 4159617a3babSopenharmony_ci} 4160617a3babSopenharmony_ci 4161617a3babSopenharmony_civoid Builder::dumpModuleProcesses(std::vector<unsigned int>& out) const 4162617a3babSopenharmony_ci{ 4163617a3babSopenharmony_ci for (int i = 0; i < (int)moduleProcesses.size(); ++i) { 4164617a3babSopenharmony_ci Instruction moduleProcessed(OpModuleProcessed); 4165617a3babSopenharmony_ci moduleProcessed.addStringOperand(moduleProcesses[i]); 4166617a3babSopenharmony_ci moduleProcessed.dump(out); 4167617a3babSopenharmony_ci } 4168617a3babSopenharmony_ci} 4169617a3babSopenharmony_ci 4170617a3babSopenharmony_ci} // end spv namespace 4171