//===- SPIRVValue.cpp - Class to represent a SPIR-V Value -------*- C++ -*-===// // // The LLVM/SPIRV Translator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal with the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimers. // Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimers in the documentation // and/or other materials provided with the distribution. // Neither the names of Advanced Micro Devices, Inc., nor the names of its // contributors may be used to endorse or promote products derived from this // Software without specific prior written permission. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH // THE SOFTWARE. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines the values defined in SPIR-V spec with op codes. /// /// The name of the SPIR-V values follow the op code name in the spec. /// This is for readability and ease of using macro to handle types. // //===----------------------------------------------------------------------===// #include "SPIRVValue.h" #include "SPIRVEnum.h" #include "llvm/ADT/APInt.h" namespace SPIRV { void SPIRVValue::setAlignment(SPIRVWord A) { if (A == 0) { eraseDecorate(DecorationAlignment); return; } SPIRVWord PrevAlignment; if (hasAlignment(&PrevAlignment)) { // Do nothing if the Id already has an Alignment decoration, provided // it matches the new alignment. assert(A == PrevAlignment && "New alignment does not match existing alignment"); return; } addDecorate(new SPIRVDecorate(DecorationAlignment, this, A)); SPIRVDBG(spvdbgs() << "Set alignment " << A << " for obj " << Id << "\n") } bool SPIRVValue::hasAlignment(SPIRVWord *Result) const { return hasDecorate(DecorationAlignment, 0, Result); } bool SPIRVValue::isVolatile() const { return hasDecorate(DecorationVolatile); } void SPIRVValue::setVolatile(bool IsVolatile) { if (!IsVolatile) { eraseDecorate(DecorationVolatile); return; } addDecorate(new SPIRVDecorate(DecorationVolatile, this)); SPIRVDBG(spvdbgs() << "Set volatile " << " for obj " << Id << "\n") } bool SPIRVValue::hasNoSignedWrap() const { return hasDecorate(DecorationNoSignedWrap); } bool SPIRVValue::hasNoUnsignedWrap() const { return hasDecorate(DecorationNoUnsignedWrap); } void SPIRVValue::setFPFastMathMode(SPIRVWord M) { if (M == 0) { eraseDecorate(DecorationFPFastMathMode); return; } addDecorate(new SPIRVDecorate(DecorationFPFastMathMode, this, M)); SPIRVDBG(spvdbgs() << "Set fast math mode to " << M << " for obj " << Id << "\n") } template void SPIRVValue::setNoIntegerDecorationWrap(bool HasNoIntegerWrap) { if (!HasNoIntegerWrap) { eraseDecorate(NoIntegerWrapDecoration); return; } // NoSignedWrap and NoUnsignedWrap decorations are available only if it is // allowed to use SPIR-V 1.4 or if SPV_KHR_no_integer_wrap_decoration // extension is enabled #ifdef _SPIRVDBG const std::string InstStr = NoIntegerWrapDecoration == DecorationNoSignedWrap ? "nsw" : "nuw"; #endif // _SPIRVDBG if (Module->isAllowedToUseVersion(VersionNumber::SPIRV_1_4)) { Module->setMinSPIRVVersion(VersionNumber::SPIRV_1_4); addDecorate(new SPIRVDecorate(NoIntegerWrapDecoration, this)); SPIRVDBG(spvdbgs() << "Set " << InstStr << " for obj " << Id << "\n") } else if (Module->isAllowedToUseExtension( ExtensionID::SPV_KHR_no_integer_wrap_decoration)) { Module->addExtension(ExtensionID::SPV_KHR_no_integer_wrap_decoration); addDecorate(new SPIRVDecorate(NoIntegerWrapDecoration, this)); SPIRVDBG(spvdbgs() << "Set " << InstStr << " for obj " << Id << "\n") } else { SPIRVDBG(spvdbgs() << "Skip setting " << InstStr << " for obj " << Id << "\n") } } template void SPIRVValue::setNoIntegerDecorationWrap(bool); template void SPIRVValue::setNoIntegerDecorationWrap(bool); template void SPIRVConstantBase::setWords(const uint64_t *TheValue) { assert(TheValue && "Nullptr value"); recalculateWordCount(); validate(); Words.resize(NumWords); for (size_t I = 0; I != NumWords / 2; ++I) { Words[I * 2] = static_cast(TheValue[I]) & SPIRVWORD_MAX; Words[I * 2 + 1] = static_cast((TheValue[I] >> SpirvWordBitWidth)) & SPIRVWORD_MAX; } if (NumWords % 2) Words.back() = static_cast(TheValue[NumWords / 2]) & SPIRVWORD_MAX; } // Complete constructor for AP integer constant template SPIRVConstantBase::SPIRVConstantBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId, const llvm::APInt &TheValue) : SPIRVValue(M, 0, OC, TheType, TheId) { setWords(TheValue.getRawData()); } // To solve errors about undefined reference to template class methods // definitions. template class SPIRVConstantBase; template class SPIRVConstantBase; } // namespace SPIRV