10e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//===- SPIRVFunction.h - Class to represent a SPIR-V function ----*- C++ -*-===//
20e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
30e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//                     The LLVM/SPIRV Translator
40e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
50e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// This file is distributed under the University of Illinois Open Source
60e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// License. See LICENSE.TXT for details.
70e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
80e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//===----------------------------------------------------------------------===//
90e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// This file defines Function class for SPIRV.
110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Permission is hereby granted, free of charge, to any person obtaining a
150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// copy of this software and associated documentation files (the "Software"),
160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// to deal with the Software without restriction, including without limitation
170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// the rights to use, copy, modify, merge, publish, distribute, sublicense,
180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// and/or sell copies of the Software, and to permit persons to whom the
190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Software is furnished to do so, subject to the following conditions:
200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Redistributions of source code must retain the above copyright notice,
220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// this list of conditions and the following disclaimers.
230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Redistributions in binary form must reproduce the above copyright notice,
240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// this list of conditions and the following disclaimers in the documentation
250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// and/or other materials provided with the distribution.
260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Neither the names of Advanced Micro Devices, Inc., nor the names of its
270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// contributors may be used to endorse or promote products derived from this
280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// Software without specific prior written permission.
290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung// THE SOFTWARE.
360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//
370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung//===----------------------------------------------------------------------===//
380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#ifndef SPIRVFUNCTION_HPP_
400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#define SPIRVFUNCTION_HPP_
410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "SPIRVValue.h"
420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include "SPIRVBasicBlock.h"
430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#include <functional>
440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungnamespace SPIRV{
460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass BIFunction;
480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVDecoder;
490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVFunctionParameter: public SPIRVValue {
510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunctionParameter(SPIRVType *TheType, SPIRVId TheId,
530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      SPIRVFunction *TheParent, unsigned TheArgNo);
540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunctionParameter():SPIRVValue(OpFunctionParameter),
550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      ParentFunc(nullptr), ArgNo(0){}
560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  unsigned getArgNo()const { return ArgNo;}
570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void foreachAttr(std::function<void(SPIRVFuncParamAttrKind)>);
580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void addAttr(SPIRVFuncParamAttrKind Kind) {
590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    addDecorate(new SPIRVDecorate(DecorationFuncParamAttr, this, Kind));
600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setParent(SPIRVFunction *Parent) { ParentFunc = Parent;}
620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool hasAttr(SPIRVFuncParamAttrKind Kind) const {
630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getDecorate(DecorationFuncParamAttr).count(Kind) ;
640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool isByVal()const { return hasAttr(FunctionParameterAttributeByVal);}
660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  bool isZext()const { return hasAttr(FunctionParameterAttributeZext);}
670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVCapVec getRequiredCapability() const {
680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    if (hasLinkageType() && getLinkageType() == LinkageTypeImport)
690e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      return getVec(CapabilityLinkage);
700e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return SPIRVCapVec();
710e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
720e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprotected:
730e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
740e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVValue::validate();
750e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(ParentFunc && "Invalid parent function");
760e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
770e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DEF_ENCDEC2(Type, Id)
780e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprivate:
790e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunction *ParentFunc;
800e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  unsigned ArgNo;
810e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
820e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
830e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungclass SPIRVFunction: public SPIRVValue, public SPIRVComponentExecutionModes {
840e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungpublic:
850e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Complete constructor. It does not construct basic blocks.
860e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunction(SPIRVModule *M, SPIRVTypeFunction *FunctionType, SPIRVId TheId)
870e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    :SPIRVValue(M, 5, OpFunction, FunctionType->getReturnType(), TheId),
880e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung     FuncType(FunctionType), FCtrlMask(FunctionControlMaskNone) {
890e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    addAllArguments(TheId + 1);
900e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    validate();
910e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
920e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
930e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Incomplete constructor
940e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunction():SPIRVValue(OpFunction),FuncType(NULL),
950e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      FCtrlMask(FunctionControlMaskNone){}
960e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
970e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVDecoder getDecoder(std::istream &IS);
980e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVTypeFunction *getFunctionType() const { return FuncType;}
990e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord getFuncCtlMask() const { return FCtrlMask;}
1000e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  size_t getNumBasicBlock() const { return BBVec.size();}
1010e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVBasicBlock *getBasicBlock(size_t i) const { return BBVec[i];}
1020e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  size_t getNumArguments() const {
1030e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return getFunctionType()->getNumParameters();
1040e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1050e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVId getArgumentId(size_t i)const { return Parameters[i]->getId();}
1060e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunctionParameter *getArgument(size_t i) const {
1070e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Parameters[i];
1080e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1090e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void foreachArgument(std::function<void(SPIRVFunctionParameter *)>Func) {
1100e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (size_t I = 0, E = getNumArguments(); I != E; ++I)
1110e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      Func(getArgument(I));
1120e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1130e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1140e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void foreachReturnValueAttr(std::function<void(SPIRVFuncParamAttrKind)>);
1150e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1160e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void setFunctionControlMask(SPIRVWord Mask) {
1170e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    FCtrlMask = Mask;
1180e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1190e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1200e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void takeExecutionModes(SPIRVForward *Forward) {
1210e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    ExecModes = std::move(Forward->ExecModes);
1220e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1230e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1240e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  // Assume BB contains valid Id.
1250e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVBasicBlock *addBasicBlock(SPIRVBasicBlock *BB) {
1260e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Module->add(BB);
1270e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    BB->setParent(this);
1280e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    BBVec.push_back(BB);
1290e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return BB;
1300e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1310e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1320e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void encodeChildren(spv_ostream &)const;
1330e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void encodeExecutionModes(spv_ostream &)const;
1340e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  _SPIRV_DCL_ENCDEC
1350e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void validate()const {
1360e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVValue::validate();
1370e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    assert(FuncType && "Invalid func type");
1380e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1390e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1400e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungprivate:
1410e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVFunctionParameter *addArgument(unsigned TheArgNo, SPIRVId TheId) {
1420e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    SPIRVFunctionParameter *Arg = new SPIRVFunctionParameter(
1430e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        getFunctionType()->getParameterType(TheArgNo),
1440e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung        TheId, this, TheArgNo);
1450e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Module->add(Arg);
1460e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    Parameters.push_back(Arg);
1470e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    return Arg;
1480e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1490e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1500e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void addAllArguments(SPIRVId FirstArgId) {
1510e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung    for (size_t i = 0, e = getFunctionType()->getNumParameters(); i != e; ++i)
1520e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung      addArgument(i, FirstArgId + i);
1530e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  }
1540e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  void decodeBB(SPIRVDecoder &);
1550e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1560e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVTypeFunction *FuncType;                  // Function type
1570e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVWord FCtrlMask;                          // Function control mask
1580e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1590e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  std::vector<SPIRVFunctionParameter *> Parameters;
1600e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  typedef std::vector<SPIRVBasicBlock *> SPIRVLBasicBlockVector;
1610e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung  SPIRVLBasicBlockVector BBVec;
1620e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung};
1630e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1640e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sungtypedef SPIRVEntryOpCodeOnly<OpFunctionEnd> SPIRVFunctionEnd;
1650e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1660e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung}
1670e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung
1680e839d7e9d7e5a096949e39a4c6e00670c8dee64I-Jui (Ray) Sung#endif /* SPIRVFUNCTION_HPP_ */
169