Home | History | Annotate | Download | only in libSPIRV
      1 //===- SPIRVFunction.h - Class to represent a SPIR-V function ----*- C++ -*-===//
      2 //
      3 //                     The LLVM/SPIRV Translator
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file defines Function class for SPIRV.
     11 //
     12 // Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
     13 //
     14 // Permission is hereby granted, free of charge, to any person obtaining a
     15 // copy of this software and associated documentation files (the "Software"),
     16 // to deal with the Software without restriction, including without limitation
     17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
     18 // and/or sell copies of the Software, and to permit persons to whom the
     19 // Software is furnished to do so, subject to the following conditions:
     20 //
     21 // Redistributions of source code must retain the above copyright notice,
     22 // this list of conditions and the following disclaimers.
     23 // Redistributions in binary form must reproduce the above copyright notice,
     24 // this list of conditions and the following disclaimers in the documentation
     25 // and/or other materials provided with the distribution.
     26 // Neither the names of Advanced Micro Devices, Inc., nor the names of its
     27 // contributors may be used to endorse or promote products derived from this
     28 // Software without specific prior written permission.
     29 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     30 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     31 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     32 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     33 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     34 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
     35 // THE SOFTWARE.
     36 //
     37 //===----------------------------------------------------------------------===//
     38 
     39 #ifndef SPIRVFUNCTION_HPP_
     40 #define SPIRVFUNCTION_HPP_
     41 #include "SPIRVValue.h"
     42 #include "SPIRVBasicBlock.h"
     43 #include <functional>
     44 
     45 namespace SPIRV{
     46 
     47 class BIFunction;
     48 class SPIRVDecoder;
     49 
     50 class SPIRVFunctionParameter: public SPIRVValue {
     51 public:
     52   SPIRVFunctionParameter(SPIRVType *TheType, SPIRVId TheId,
     53       SPIRVFunction *TheParent, unsigned TheArgNo);
     54   SPIRVFunctionParameter():SPIRVValue(OpFunctionParameter),
     55       ParentFunc(nullptr), ArgNo(0){}
     56   unsigned getArgNo()const { return ArgNo;}
     57   void foreachAttr(std::function<void(SPIRVFuncParamAttrKind)>);
     58   void addAttr(SPIRVFuncParamAttrKind Kind) {
     59     addDecorate(new SPIRVDecorate(DecorationFuncParamAttr, this, Kind));
     60   }
     61   void setParent(SPIRVFunction *Parent) { ParentFunc = Parent;}
     62   bool hasAttr(SPIRVFuncParamAttrKind Kind) const {
     63     return getDecorate(DecorationFuncParamAttr).count(Kind) ;
     64   }
     65   bool isByVal()const { return hasAttr(FunctionParameterAttributeByVal);}
     66   bool isZext()const { return hasAttr(FunctionParameterAttributeZext);}
     67   SPIRVCapVec getRequiredCapability() const {
     68     if (hasLinkageType() && getLinkageType() == LinkageTypeImport)
     69       return getVec(CapabilityLinkage);
     70     return SPIRVCapVec();
     71   }
     72 protected:
     73   void validate()const {
     74     SPIRVValue::validate();
     75     assert(ParentFunc && "Invalid parent function");
     76   }
     77   _SPIRV_DEF_ENCDEC2(Type, Id)
     78 private:
     79   SPIRVFunction *ParentFunc;
     80   unsigned ArgNo;
     81 };
     82 
     83 class SPIRVFunction: public SPIRVValue, public SPIRVComponentExecutionModes {
     84 public:
     85   // Complete constructor. It does not construct basic blocks.
     86   SPIRVFunction(SPIRVModule *M, SPIRVTypeFunction *FunctionType, SPIRVId TheId)
     87     :SPIRVValue(M, 5, OpFunction, FunctionType->getReturnType(), TheId),
     88      FuncType(FunctionType), FCtrlMask(FunctionControlMaskNone) {
     89     addAllArguments(TheId + 1);
     90     validate();
     91   }
     92 
     93   // Incomplete constructor
     94   SPIRVFunction():SPIRVValue(OpFunction),FuncType(NULL),
     95       FCtrlMask(FunctionControlMaskNone){}
     96 
     97   SPIRVDecoder getDecoder(std::istream &IS);
     98   SPIRVTypeFunction *getFunctionType() const { return FuncType;}
     99   SPIRVWord getFuncCtlMask() const { return FCtrlMask;}
    100   size_t getNumBasicBlock() const { return BBVec.size();}
    101   SPIRVBasicBlock *getBasicBlock(size_t i) const { return BBVec[i];}
    102   size_t getNumArguments() const {
    103     return getFunctionType()->getNumParameters();
    104   }
    105   SPIRVId getArgumentId(size_t i)const { return Parameters[i]->getId();}
    106   SPIRVFunctionParameter *getArgument(size_t i) const {
    107     return Parameters[i];
    108   }
    109   void foreachArgument(std::function<void(SPIRVFunctionParameter *)>Func) {
    110     for (size_t I = 0, E = getNumArguments(); I != E; ++I)
    111       Func(getArgument(I));
    112   }
    113 
    114   void foreachReturnValueAttr(std::function<void(SPIRVFuncParamAttrKind)>);
    115 
    116   void setFunctionControlMask(SPIRVWord Mask) {
    117     FCtrlMask = Mask;
    118   }
    119 
    120   void takeExecutionModes(SPIRVForward *Forward) {
    121     ExecModes = std::move(Forward->ExecModes);
    122   }
    123 
    124   // Assume BB contains valid Id.
    125   SPIRVBasicBlock *addBasicBlock(SPIRVBasicBlock *BB) {
    126     Module->add(BB);
    127     BB->setParent(this);
    128     BBVec.push_back(BB);
    129     return BB;
    130   }
    131 
    132   void encodeChildren(spv_ostream &)const;
    133   void encodeExecutionModes(spv_ostream &)const;
    134   _SPIRV_DCL_ENCDEC
    135   void validate()const {
    136     SPIRVValue::validate();
    137     assert(FuncType && "Invalid func type");
    138   }
    139 
    140 private:
    141   SPIRVFunctionParameter *addArgument(unsigned TheArgNo, SPIRVId TheId) {
    142     SPIRVFunctionParameter *Arg = new SPIRVFunctionParameter(
    143         getFunctionType()->getParameterType(TheArgNo),
    144         TheId, this, TheArgNo);
    145     Module->add(Arg);
    146     Parameters.push_back(Arg);
    147     return Arg;
    148   }
    149 
    150   void addAllArguments(SPIRVId FirstArgId) {
    151     for (size_t i = 0, e = getFunctionType()->getNumParameters(); i != e; ++i)
    152       addArgument(i, FirstArgId + i);
    153   }
    154   void decodeBB(SPIRVDecoder &);
    155 
    156   SPIRVTypeFunction *FuncType;                  // Function type
    157   SPIRVWord FCtrlMask;                          // Function control mask
    158 
    159   std::vector<SPIRVFunctionParameter *> Parameters;
    160   typedef std::vector<SPIRVBasicBlock *> SPIRVLBasicBlockVector;
    161   SPIRVLBasicBlockVector BBVec;
    162 };
    163 
    164 typedef SPIRVEntryOpCodeOnly<OpFunctionEnd> SPIRVFunctionEnd;
    165 
    166 }
    167 
    168 #endif /* SPIRVFUNCTION_HPP_ */
    169