| //===- SPIRVMDWalker.h - SPIR-V metadata walker header file ----*- 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 declares classes for walking SPIR-V metadata. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LIB_SPIRV_SPIRVMDWALKER_H_ |
| #define LIB_SPIRV_SPIRVMDWALKER_H_ |
| |
| #include "llvm/IR/Metadata.h" |
| #include "SPIRVInternal.h" |
| |
| #include <functional> |
| using namespace llvm; |
| |
| namespace SPIRV { |
| |
| class SPIRVMDWalker { |
| public: |
| template<typename ParentT> struct MDWrapper; |
| |
| struct NamedMDWrapper { |
| NamedMDWrapper(NamedMDNode *Named, SPIRVMDWalker& WW) |
| :NMD(Named), W(WW), I(0), Q(true){ |
| E = Named ? Named->getNumOperands() : 0; |
| } |
| |
| operator bool() const { return NMD;} |
| |
| bool atEnd() const { return !(NMD && I < E);} |
| |
| MDWrapper<NamedMDWrapper> nextOp() { |
| if (!Q) |
| assert(I < E && "out of bound"); |
| return MDWrapper<NamedMDWrapper>((NMD && I < E) ? NMD->getOperand(I++) |
| : nullptr, *this, W); |
| } |
| |
| NamedMDWrapper &setQuiet(bool Quiet) { |
| Q = Quiet; |
| return *this; |
| } |
| |
| NamedMDNode *NMD; |
| SPIRVMDWalker &W; |
| unsigned I; |
| unsigned E; |
| bool Q; // Quiet |
| }; |
| |
| template<typename ParentT> |
| struct MDWrapper { |
| MDWrapper(MDNode *Node, ParentT &Parent, SPIRVMDWalker &Walker) |
| :M(Node), P(Parent), W(Walker), I(0), Q(false){ |
| E = Node ? Node->getNumOperands() : 0; |
| } |
| |
| operator bool() const { return M;} |
| |
| bool atEnd() const { return !(M && I < E);} |
| |
| template<typename T> |
| MDWrapper &get(T &V) { |
| if (!Q) |
| assert(I < E && "out of bound"); |
| if (atEnd()) |
| return *this; |
| V = mdconst::dyn_extract<ConstantInt>(M->getOperand(I++)) |
| ->getZExtValue(); |
| return *this; |
| } |
| |
| MDWrapper &get(std::string &S) { |
| if (!Q) |
| assert (I < E && "out of bound"); |
| if (atEnd()) |
| return *this; |
| Metadata* Op = M->getOperand(I++); |
| if (!Op) |
| S = ""; |
| else if (auto Str = dyn_cast<MDString>(Op)) |
| S = Str->getString().str(); |
| else |
| S = ""; |
| return *this; |
| } |
| |
| MDWrapper &get(Function *&F) { |
| if (!Q) |
| assert (I < E && "out of bound"); |
| if (atEnd()) |
| return *this; |
| F = mdconst::dyn_extract<Function>(M->getOperand(I++)); |
| return *this; |
| } |
| |
| MDWrapper &get(SmallVectorImpl<std::string> &SV) { |
| if (atEnd()) |
| return *this; |
| while (I < E) { |
| std::string S; |
| get(S); |
| SV.push_back(S); |
| } |
| return *this; |
| } |
| |
| MDWrapper<MDWrapper> nextOp() { |
| if (!Q) |
| assert (I < E && "out of bound"); |
| return MDWrapper<MDWrapper>((M && I < E) ? |
| dyn_cast<MDNode>(M->getOperand(I++)) : nullptr, *this, W); |
| } |
| |
| ParentT &done() { |
| return P; |
| } |
| |
| MDWrapper &setQuiet(bool Quiet) { |
| Q = Quiet; |
| return *this; |
| } |
| |
| MDNode *M; |
| ParentT &P; |
| SPIRVMDWalker &W; |
| SmallVector<Metadata *, 10> V; |
| unsigned I; |
| unsigned E; |
| bool Q; // Quiet |
| }; |
| |
| explicit SPIRVMDWalker(Module &Mod):M(Mod), C(Mod.getContext()){} |
| |
| NamedMDWrapper getNamedMD(StringRef Name) { |
| return NamedMDWrapper(M.getNamedMetadata(Name), *this); |
| } |
| |
| friend struct NamedMDWrapper; |
| private: |
| Module& M; |
| LLVMContext& C; |
| }; |
| |
| } /* namespace SPIRV */ |
| |
| #endif /* LIB_SPIRV_SPIRVMDBUILDER_H_ */ |