OpenVDB  8.1.1
FunctionTypes.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
65 
66 #ifndef OPENVDB_AX_CODEGEN_FUNCTION_TYPES_HAS_BEEN_INCLUDED
67 #define OPENVDB_AX_CODEGEN_FUNCTION_TYPES_HAS_BEEN_INCLUDED
68 
69 #include "Types.h"
70 #include "Utils.h" // isValidCast
71 #include "ConstantFolding.h"
72 
73 #include <openvdb/version.h>
74 
75 #include <llvm/IR/Constants.h>
76 #include <llvm/IR/IRBuilder.h>
77 #include <llvm/IR/Module.h>
78 
79 #include <algorithm>
80 #include <functional>
81 #include <memory>
82 #include <stack>
83 #include <type_traits>
84 #include <unordered_map>
85 #include <vector>
86 
87 namespace openvdb {
89 namespace OPENVDB_VERSION_NAME {
90 
91 namespace ax {
92 namespace codegen {
93 
96 
100 
101 template <typename T, size_t _SIZE = 1>
102 struct ArgType {
103  using Type = T;
104  static const size_t SIZE = _SIZE;
105  using ArrayType = Type[SIZE];
107 };
108 
109 template <typename T, size_t S>
110 struct LLVMType<ArgType<T,S>> : public AliasTypeMap<ArgType<T,S>, T[S]> {};
111 
125 
127 
131 
132 template <typename T> struct TypeToSymbol { static inline std::string s() { return "?"; } };
133 template <> struct TypeToSymbol<void> { static inline std::string s() { return "v"; } };
134 template <> struct TypeToSymbol<char> { static inline std::string s() { return "c"; } };
135 template <> struct TypeToSymbol<int16_t> { static inline std::string s() { return "s"; } };
136 template <> struct TypeToSymbol<int32_t> { static inline std::string s() { return "i"; } };
137 template <> struct TypeToSymbol<int64_t> { static inline std::string s() { return "l"; } };
138 template <> struct TypeToSymbol<float> { static inline std::string s() { return "f"; } };
139 template <> struct TypeToSymbol<double> { static inline std::string s() { return "d"; } };
140 template <> struct TypeToSymbol<codegen::String> { static inline std::string s() { return "a"; } };
141 
142 template <typename T>
143 struct TypeToSymbol<T*> {
144  static inline std::string s() { return TypeToSymbol<T>::s() + "*"; }
145 };
146 
147 template <typename T, size_t S>
148 struct TypeToSymbol<T[S]> {
149  static inline std::string s() { return TypeToSymbol<T>::s() + std::to_string(S); }
150 };
151 
152 template <typename T, size_t S> struct TypeToSymbol<ArgType<T,S>> : public TypeToSymbol<T[S]> {};
153 template <typename T> struct TypeToSymbol<math::Vec2<T>> : public TypeToSymbol<T[2]> {};
154 template <typename T> struct TypeToSymbol<math::Vec3<T>> : public TypeToSymbol<T[3]> {};
155 template <typename T> struct TypeToSymbol<math::Vec4<T>> : public TypeToSymbol<T[4]> {};
156 template <typename T> struct TypeToSymbol<math::Mat3<T>> : public TypeToSymbol<T[9]> {};
157 template <typename T> struct TypeToSymbol<math::Mat4<T>> : public TypeToSymbol<T[16]> {};
158 template <typename T> struct TypeToSymbol<const T> : public TypeToSymbol<T> {};
159 template <typename T> struct TypeToSymbol<const T*> : public TypeToSymbol<T*> {};
160 
163 
167 template <typename SignatureT, size_t I = FunctionTraits<SignatureT>::N_ARGS>
169 {
170  using ArgT = typename FunctionTraits<SignatureT>::template Arg<I-1>;
171  using ArgumentValueType = typename ArgT::Type;
172 
173  template <typename OpT>
174  static void apply(const OpT& op, const bool forwards) {
175  if (forwards) {
177  op(ArgumentValueType());
178  }
179  else {
180  op(ArgumentValueType());
182  }
183  }
184 };
185 
186 template <typename SignatureT>
187 struct ArgumentIterator<SignatureT, 0>
188 {
189  template <typename OpT>
190  static void apply(const OpT&, const bool) {}
191 };
192 
195 
201 template <typename SignatureT>
202 inline llvm::Type*
203 llvmTypesFromSignature(llvm::LLVMContext& C,
204  std::vector<llvm::Type*>* types = nullptr)
205 {
206  using Traits = FunctionTraits<SignatureT>;
207  using ArgumentIteratorT =
209 
210  if (types) {
211  types->reserve(Traits::N_ARGS);
212  auto callback = [&types, &C](auto type) {
213  using Type = decltype(type);
214  types->emplace_back(LLVMType<Type>::get(C));
215  };
216  ArgumentIteratorT::apply(callback, /*forwards*/true);
217  }
219 }
220 
225 template <typename SignatureT>
226 inline llvm::FunctionType*
227 llvmFunctionTypeFromSignature(llvm::LLVMContext& C)
228 {
229  std::vector<llvm::Type*> types;
230  llvm::Type* returnType =
231  llvmTypesFromSignature<SignatureT>(C, &types);
232  return llvm::FunctionType::get(/*Result=*/returnType,
233  /*Params=*/llvm::ArrayRef<llvm::Type*>(types),
234  /*isVarArg=*/false);
235 }
236 
248 void
249 printSignature(std::ostream& os,
250  const std::vector<llvm::Type*>& types,
251  const llvm::Type* returnType,
252  const char* name = nullptr,
253  const std::vector<const char*>& names = {},
254  const bool axTypes = false);
255 
258 
261 struct Function
262 {
263  using Ptr = std::shared_ptr<Function>;
264 
265  Function(const size_t size, const std::string& symbol)
266  : mSize(size)
267  , mSymbol(symbol)
268  , mAttributes(nullptr)
269  , mNames()
270  , mDeps() {
271  // symbol must be a valid string
272  assert(!symbol.empty());
273  }
274 
275  virtual ~Function() = default;
276 
280  virtual llvm::Type* types(std::vector<llvm::Type*>&, llvm::LLVMContext&) const = 0;
281 
306  virtual llvm::Function*
307  create(llvm::LLVMContext& C, llvm::Module* M = nullptr) const;
308 
312  llvm::Function* create(llvm::Module& M) const {
313  return this->create(M.getContext(), &M);
314  }
315 
320  llvm::Function* get(const llvm::Module& M) const;
321 
345  virtual llvm::Value*
346  call(const std::vector<llvm::Value*>& args,
347  llvm::IRBuilder<>& B,
348  const bool cast = false) const;
349 
351  enum SignatureMatch { None = 0, Size, Implicit, Explicit };
352 
374  virtual SignatureMatch match(const std::vector<llvm::Type*>& inputs, llvm::LLVMContext& C) const;
375 
377  inline size_t size() const { return mSize; }
378 
381  inline const char* symbol() const { return mSymbol.c_str(); }
382 
388  inline const char* argName(const size_t idx) const {
389  return idx < mNames.size() ? mNames[idx] : "";
390  }
391 
403  virtual void print(llvm::LLVMContext& C,
404  std::ostream& os,
405  const char* name = nullptr,
406  const bool axTypes = true) const;
407 
409 
410  inline bool hasParamAttribute(const size_t i,
411  const llvm::Attribute::AttrKind& kind) const
412  {
413  if (!mAttributes) return false;
414  const auto iter = mAttributes->mParamAttrs.find(i);
415  if (iter == mAttributes->mParamAttrs.end()) return false;
416  const auto& vec = iter->second;
417  return std::find(vec.begin(), vec.end(), kind) != vec.end();
418  }
419 
420  inline void setArgumentNames(std::vector<const char*> names) { mNames = names; }
421 
422  const std::vector<const char*>& dependencies() const { return mDeps; }
423  inline void setDependencies(std::vector<const char*> deps) { mDeps = deps; }
424 
425  inline void setFnAttributes(const std::vector<llvm::Attribute::AttrKind>& in)
426  {
427  this->attrs().mFnAttrs = in;
428  }
429  inline void setRetAttributes(const std::vector<llvm::Attribute::AttrKind>& in)
430  {
431  this->attrs().mRetAttrs = in;
432  }
433  inline void setParamAttributes(const size_t i,
434  const std::vector<llvm::Attribute::AttrKind>& in)
435  {
436  this->attrs().mParamAttrs[i] = in;
437  }
438 
439 protected:
440 
448  static void cast(std::vector<llvm::Value*>& args,
449  const std::vector<llvm::Type*>& types,
450  llvm::IRBuilder<>& B);
451 
452 private:
453 
454  struct Attributes {
455  std::vector<llvm::Attribute::AttrKind> mFnAttrs, mRetAttrs;
456  std::map<size_t, std::vector<llvm::Attribute::AttrKind>> mParamAttrs;
457  };
458 
459  inline Attributes& attrs() {
460  if (!mAttributes) mAttributes.reset(new Attributes());
461  return *mAttributes;
462  }
463 
464  llvm::AttributeList flattenAttrs(llvm::LLVMContext& C) const;
465 
466  const size_t mSize;
467  const std::string mSymbol;
468  std::unique_ptr<Attributes> mAttributes;
469  std::vector<const char*> mNames;
470  std::vector<const char*> mDeps;
471 };
472 
487 template <typename SignatureT, typename DerivedFunction>
488 struct SRetFunction : public DerivedFunction
489 {
490  using Ptr = std::shared_ptr<SRetFunction<SignatureT, DerivedFunction>>;
492 
493  // check there actually are arguments
494  static_assert(Traits::N_ARGS > 0,
495  "SRET Function object has been setup with the first argument as the return "
496  "value, however the provided signature is empty.");
497 
498  // check no return value exists
499  static_assert(std::is_same<typename Traits::ReturnType, void>::value,
500  "SRET Function object has been setup with the first argument as the return "
501  "value and a non void return type.");
502 
503 private:
504 
505  using FirstArgument = typename Traits::template Arg<0>::Type;
506  static_assert(std::is_pointer<FirstArgument>::value,
507  "SRET Function object has been setup with the first argument as the return "
508  "value, but this argument it is not a pointer type.");
509  using SRetType = typename std::remove_pointer<FirstArgument>::type;
510 
511 public:
512 
515  Function::SignatureMatch match(const std::vector<llvm::Type*>& args,
516  llvm::LLVMContext& C) const override
517  {
518  // append return type and right rotate
519  std::vector<llvm::Type*> inputs(args);
520  inputs.emplace_back(LLVMType<SRetType*>::get(C));
521  std::rotate(inputs.rbegin(), inputs.rbegin() + 1, inputs.rend());
522  return DerivedFunction::match(inputs, C);
523  }
524 
531  llvm::Value*
532  call(const std::vector<llvm::Value*>& args,
533  llvm::IRBuilder<>& B,
534  const bool cast) const override
535  {
536  // append return value and right rotate
537  std::vector<llvm::Value*> inputs(args);
538  llvm::Type* sret = LLVMType<SRetType>::get(B.getContext());
539  inputs.emplace_back(insertStaticAlloca(B, sret));
540  std::rotate(inputs.rbegin(), inputs.rbegin() + 1, inputs.rend());
541  DerivedFunction::call(inputs, B, cast);
542  return inputs.front();
543  }
544 
546  void print(llvm::LLVMContext& C,
547  std::ostream& os,
548  const char* name = nullptr,
549  const bool axTypes = true) const override
550  {
551  std::vector<llvm::Type*> current;
552  llvm::Type* ret = this->types(current, C);
553  // left rotate
554  std::rotate(current.begin(), current.begin() + 1, current.end());
555  ret = current.back();
556  current.pop_back();
557 
558  std::vector<const char*> names;
559  names.reserve(this->size());
560  for (size_t i = 0; i < this->size()-1; ++i) {
561  names.emplace_back(this->argName(i));
562  }
563  printSignature(os, current, ret, name, names, axTypes);
564  }
565 
566 protected:
568  template <typename ...Args>
569  SRetFunction(Args&&... ts) : DerivedFunction(ts...) {}
570 };
571 
573 struct CFunctionBase : public Function
574 {
575  using Ptr = std::shared_ptr<CFunctionBase>;
576 
577  ~CFunctionBase() override = default;
578 
581  virtual uint64_t address() const = 0;
582 
583  inline void setConstantFold(bool on) { mConstantFold = on; }
584  inline bool hasConstantFold() const { return mConstantFold; }
585 
586  inline virtual llvm::Value* fold(const std::vector<llvm::Value*>&,
587  llvm::LLVMContext&) const {
588  return nullptr;
589  }
590 
591 protected:
592  CFunctionBase(const size_t size,
593  const std::string& symbol)
594  : Function(size, symbol)
595  , mConstantFold(false) {}
596 
597 private:
598  bool mConstantFold;
599 };
600 
606 template <typename SignatureT>
607 struct CFunction : public CFunctionBase
608 {
610  using Ptr = std::shared_ptr<CFunctionT>;
612 
613  // Assert that the return argument is not a pointer (relaxed for void* for mallocs).
614  // Note that this is relaxed for IR functions where it's allowed if the function is
615  // forcefully inlined.
616  static_assert(std::is_same<typename Traits::ReturnType, void*>::value ||
617  !std::is_pointer<typename Traits::ReturnType>::value,
618  "CFunction object has been setup with a pointer return argument. C bindings "
619  "cannot return memory locations to LLVM - Consider using a CFunctionSRet.");
620 
621  CFunction(const std::string& symbol, const SignatureT function)
622  : CFunctionBase(Traits::N_ARGS, symbol)
623  , mFunction(function) {}
624 
625  ~CFunction() override = default;
626 
627  inline llvm::Type* types(std::vector<llvm::Type*>& types, llvm::LLVMContext& C) const override
628  {
629  return llvmTypesFromSignature<SignatureT>(C, &types);
630  }
631 
632  inline uint64_t address() const override final {
633  return reinterpret_cast<uint64_t>(mFunction);
634  }
635 
636  llvm::Value*
637  call(const std::vector<llvm::Value*>& args,
638  llvm::IRBuilder<>& B,
639  const bool cast) const override
640  {
641  llvm::Value* result = this->fold(args, B.getContext());
642  if (result) return result;
643  return Function::call(args, B, cast);
644  }
645 
646  llvm::Value* fold(const std::vector<llvm::Value*>& args, llvm::LLVMContext& C) const override final
647  {
648  auto allconst =
649  [](const std::vector<llvm::Value*>& vals) -> bool {
650  for (auto& value : vals) {
651  if (!llvm::isa<llvm::Constant>(value)) return false;
652  }
653  return true;
654  };
655 
656  if (!this->hasConstantFold()) return nullptr;
657  if (!allconst(args)) return nullptr;
658  std::vector<llvm::Constant*> constants;
659  constants.reserve(args.size());
660  for (auto& value : args) {
661  constants.emplace_back(llvm::cast<llvm::Constant>(value));
662  }
663 
664  // no guarantee that fold() will be able to cast all arguments
665  return ConstantFolder<SignatureT>::fold(constants, *mFunction, C);
666  }
667 
668 private:
669  const SignatureT* mFunction;
670 };
671 
673 struct IRFunctionBase : public Function
674 {
675  using Ptr = std::shared_ptr<IRFunctionBase>;
676 
686  using GeneratorCb = std::function<llvm::Value*
687  (const std::vector<llvm::Value*>&, llvm::IRBuilder<>&)>;
688 
689  llvm::Type* types(std::vector<llvm::Type*>& types,
690  llvm::LLVMContext& C) const override = 0;
691 
694  inline void setEmbedIR(bool on) { mEmbedIR = on; }
695  inline bool hasEmbedIR() const { return mEmbedIR; }
696 
709  llvm::Function*
710  create(llvm::LLVMContext& C, llvm::Module* M) const override;
711 
716  llvm::Value*
717  call(const std::vector<llvm::Value*>& args,
718  llvm::IRBuilder<>& B,
719  const bool cast) const override;
720 
721 protected:
722 
723  // @todo This should ideally live in FunctionGroup::execute, but the return
724  // type is allowed to differ for sret C bindings.
725  inline void
726  verifyResultType(const llvm::Type* result, const llvm::Type* expected) const
727  {
728  if (result == expected) return;
729  std::string source, target;
730  if (result) llvmTypeToString(result, source);
731  llvmTypeToString(expected, target);
732  OPENVDB_THROW(AXCodeGenError, "Function \"" + std::string(this->symbol()) +
733  "\" has been invoked with a mismatching return type. Expected: \"" +
734  target + "\", got \"" + source + "\".");
735  }
736 
737  IRFunctionBase(const std::string& symbol,
738  const GeneratorCb& gen,
739  const size_t size)
740  : Function(size, symbol)
741  , mGen(gen)
742  , mEmbedIR(false) {}
743  ~IRFunctionBase() override = default;
744 
746  bool mEmbedIR;
747 };
748 
750 template <typename SignatureT>
751 struct IRFunction : public IRFunctionBase
752 {
754  using Ptr = std::shared_ptr<IRFunction>;
755 
756  IRFunction(const std::string& symbol, const GeneratorCb& gen)
757  : IRFunctionBase(symbol, gen, Traits::N_ARGS) {}
758 
759  inline llvm::Type*
760  types(std::vector<llvm::Type*>& types, llvm::LLVMContext& C) const override
761  {
762  return llvmTypesFromSignature<SignatureT>(C, &types);
763  }
764 };
765 
768 template <typename SignatureT>
769 struct CFunctionSRet : public SRetFunction<SignatureT, CFunction<SignatureT>>
770 {
772  CFunctionSRet(const std::string& symbol, const SignatureT function)
773  : BaseT(symbol, function) {}
774  ~CFunctionSRet() override = default;
775 };
776 
779 template <typename SignatureT>
780 struct IRFunctionSRet : public SRetFunction<SignatureT, IRFunction<SignatureT>>
781 {
783  IRFunctionSRet(const std::string& symbol,
784  const IRFunctionBase::GeneratorCb& gen)
785  : BaseT(symbol, gen) {}
786  ~IRFunctionSRet() override = default;
787 };
788 
791 {
792  using Ptr = std::shared_ptr<FunctionGroup>;
793  using UniquePtr = std::unique_ptr<FunctionGroup>;
794  using FunctionList = std::vector<Function::Ptr>;
795 
796  FunctionGroup(const char* name,
797  const char* doc,
798  const FunctionList& list)
799  : mName(name)
800  , mDoc(doc)
801  , mFunctionList(list) {}
802  ~FunctionGroup() = default;
803 
817  const Function*
818  match(const std::vector<llvm::Type*>& types,
819  llvm::LLVMContext& C,
820  Function::SignatureMatch* type = nullptr) const;
821 
832  llvm::Value*
833  execute(const std::vector<llvm::Value*>& args,
834  llvm::IRBuilder<>& B) const;
835 
849  const Function*
850  execute(const std::vector<llvm::Value*>& args,
851  llvm::IRBuilder<>& B,
852  llvm::Value*& result) const;
853 
855  inline const FunctionList& list() const { return mFunctionList; }
856  const char* name() const { return mName; }
857  const char* doc() const { return mDoc; }
858 
859 private:
860  const char* mName;
861  const char* mDoc;
862  const FunctionList mFunctionList;
863 };
864 
875 {
877  C, IR, Any
878  };
879 
880  struct Settings
881  {
882  using Ptr = std::shared_ptr<Settings>;
883 
884  inline bool isDefault() const {
885  if (mNames) return false;
886  if (!mDeps.empty()) return false;
887  if (mConstantFold || mEmbedIR) return false;
888  if (!mFnAttrs.empty()) return false;
889  if (!mRetAttrs.empty()) return false;
890  if (!mParamAttrs.empty()) return false;
891  return true;
892  }
893 
894  std::shared_ptr<std::vector<const char*>> mNames = nullptr;
895  std::vector<const char*> mDeps = {};
896  bool mConstantFold = false;
897  bool mEmbedIR = false;
898  std::vector<llvm::Attribute::AttrKind> mFnAttrs = {};
899  std::vector<llvm::Attribute::AttrKind> mRetAttrs = {};
900  std::map<size_t, std::vector<llvm::Attribute::AttrKind>> mParamAttrs = {};
901  };
902 
903  FunctionBuilder(const char* name)
904  : mName(name)
905  , mCurrentSettings(new Settings()) {}
906 
907 
908  template <typename Signature, bool SRet = false>
909  inline FunctionBuilder&
911  const char* symbol = nullptr)
912  {
913  using IRFType = typename std::conditional
915  using IRPtr = typename IRFType::Ptr;
916 
917  Settings::Ptr settings = mCurrentSettings;
918  if (!mCurrentSettings->isDefault()) {
919  settings.reset(new Settings());
920  }
921 
922  std::string s;
923  if (symbol) s = std::string(symbol);
924  else s = this->genSymbol<Signature>();
925 
926  auto ir = IRPtr(new IRFType(s, cb));
927  mIRFunctions.emplace_back(ir);
928  mSettings[ir.get()] = settings;
929  mCurrentSettings = settings;
930  return *this;
931  }
932 
933  template <typename Signature, bool SRet = false>
934  inline FunctionBuilder&
935  addSignature(const Signature* ptr,
936  const char* symbol = nullptr)
937  {
938  using CFType = typename std::conditional
940  using CPtr = typename CFType::Ptr;
941 
942  Settings::Ptr settings = mCurrentSettings;
943  if (!mCurrentSettings->isDefault()) {
944  settings.reset(new Settings());
945  }
946 
947  std::string s;
948  if (symbol) s = std::string(symbol);
949  else s = this->genSymbol<Signature>();
950 
951  auto c = CPtr(new CFType(s, ptr));
952  mCFunctions.emplace_back(c);
953  mSettings[c.get()] = settings;
954  mCurrentSettings = settings;
955  return *this;
956  }
957 
958  template <typename Signature, bool SRet = false>
959  inline FunctionBuilder&
960  addSignature(const IRFunctionBase::GeneratorCb& cb, const Signature* ptr, const char* symbol = nullptr)
961  {
962  this->addSignature<Signature, SRet>(cb, symbol);
963  this->addSignature<Signature, SRet>(ptr, symbol);
964  return *this;
965  }
966 
967  inline FunctionBuilder& addDependency(const char* name) {
968  mCurrentSettings->mDeps.emplace_back(name); return *this;
969  }
970 
971  inline FunctionBuilder& setEmbedIR(bool on) { mCurrentSettings->mEmbedIR = on; return *this; }
972  inline FunctionBuilder& setConstantFold(bool on) { mCurrentSettings->mConstantFold = on; return *this; }
973  inline FunctionBuilder& setArgumentNames(const std::vector<const char*>& names) {
974  mCurrentSettings->mNames.reset(new std::vector<const char*>(names));
975  return *this;
976  }
977 
1041  inline FunctionBuilder&
1042  addParameterAttribute(const size_t idx, const llvm::Attribute::AttrKind attr) {
1043  mCurrentSettings->mParamAttrs[idx].emplace_back(attr);
1044  return *this;
1045  }
1046 
1047  inline FunctionBuilder&
1048  addReturnAttribute(const llvm::Attribute::AttrKind attr) {
1049  mCurrentSettings->mRetAttrs.emplace_back(attr);
1050  return *this;
1051  }
1052 
1053  inline FunctionBuilder&
1054  addFunctionAttribute(const llvm::Attribute::AttrKind attr) {
1055  mCurrentSettings->mFnAttrs.emplace_back(attr);
1056  return *this;
1057  }
1058 
1059  inline FunctionBuilder& setDocumentation(const char* doc) { mDoc = doc; return *this; }
1060  inline FunctionBuilder& setPreferredImpl(DeclPreferrence pref) { mDeclPref = pref; return *this; }
1061 
1062  inline FunctionGroup::UniquePtr get() const
1063  {
1064  for (auto& decl : mCFunctions) {
1065  const auto& s = mSettings.at(decl.get());
1066  decl->setDependencies(s->mDeps);
1067  decl->setConstantFold(s->mConstantFold);
1068  if (!s->mFnAttrs.empty()) decl->setFnAttributes(s->mFnAttrs);
1069  if (!s->mRetAttrs.empty()) decl->setRetAttributes(s->mRetAttrs);
1070  if (!s->mParamAttrs.empty()) {
1071  for (auto& idxAttrs : s->mParamAttrs) {
1072  if (idxAttrs.first > decl->size()) continue;
1073  decl->setParamAttributes(idxAttrs.first, idxAttrs.second);
1074  }
1075  }
1076  if (s->mNames) decl->setArgumentNames(*s->mNames);
1077  }
1078 
1079  for (auto& decl : mIRFunctions) {
1080  const auto& s = mSettings.at(decl.get());
1081  decl->setDependencies(s->mDeps);
1082  decl->setEmbedIR(s->mEmbedIR);
1083  if (!s->mFnAttrs.empty()) decl->setFnAttributes(s->mFnAttrs);
1084  if (!s->mRetAttrs.empty()) decl->setRetAttributes(s->mRetAttrs);
1085  if (!s->mParamAttrs.empty()) {
1086  for (auto& idxAttrs : s->mParamAttrs) {
1087  if (idxAttrs.first > decl->size()) continue;
1088  decl->setParamAttributes(idxAttrs.first, idxAttrs.second);
1089  }
1090  }
1091  if (s->mNames) decl->setArgumentNames(*s->mNames);
1092  }
1093 
1094  std::vector<Function::Ptr> functions;
1095 
1096  if (mDeclPref == DeclPreferrence::IR) {
1097  functions.insert(functions.end(), mIRFunctions.begin(), mIRFunctions.end());
1098  }
1099  if (mDeclPref == DeclPreferrence::C) {
1100  functions.insert(functions.end(), mCFunctions.begin(), mCFunctions.end());
1101  }
1102  if (functions.empty()) {
1103  functions.insert(functions.end(), mIRFunctions.begin(), mIRFunctions.end());
1104  functions.insert(functions.end(), mCFunctions.begin(), mCFunctions.end());
1105  }
1106 
1107  FunctionGroup::UniquePtr group(new FunctionGroup(mName, mDoc, functions));
1108  return group;
1109  }
1110 
1111 private:
1112 
1113  template <typename Signature>
1114  std::string genSymbol() const
1115  {
1116  using Traits = FunctionTraits<Signature>;
1117 
1118  std::string args;
1119  auto callback = [&args](auto type) {
1120  using Type = decltype(type);
1121  args += TypeToSymbol<Type>::s();
1122  };
1123 
1124  ArgumentIterator<Signature>::apply(callback, /*forwards*/true);
1128 
1129  // assemble the symbol
1130  return "ax." + std::string(this->mName) + "." +
1132  }
1133 
1134  const char* mName = "";
1135  const char* mDoc = "";
1136  DeclPreferrence mDeclPref = IR;
1137  std::vector<CFunctionBase::Ptr> mCFunctions = {};
1138  std::vector<IRFunctionBase::Ptr> mIRFunctions = {};
1139  std::map<const Function*, Settings::Ptr> mSettings = {};
1140  Settings::Ptr mCurrentSettings = nullptr;
1141 };
1142 
1143 } // namespace codegen
1144 } // namespace ax
1145 } // namespace OPENVDB_VERSION_NAME
1146 } // namespace openvdb
1147 
1148 #endif // OPENVDB_AX_CODEGEN_FUNCTION_TYPES_HAS_BEEN_INCLUDED
1149 
llvm::Function * create(llvm::Module &M) const
Convenience method which always uses the provided module to find the function or insert it if necessa...
Definition: FunctionTypes.h:312
static std::string s()
Definition: FunctionTypes.h:133
const char * doc() const
Definition: FunctionTypes.h:857
static std::string s()
Definition: FunctionTypes.h:132
FunctionBuilder & addSignature(const Signature *ptr, const char *symbol=nullptr)
Definition: FunctionTypes.h:935
llvm::Value * call(const std::vector< llvm::Value * > &args, llvm::IRBuilder<> &B, const bool cast) const override
Override of call which allocates the required SRET llvm::Value for this function. ...
Definition: FunctionTypes.h:532
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
FunctionBuilder & setEmbedIR(bool on)
Definition: FunctionTypes.h:971
llvm::Type * types(std::vector< llvm::Type * > &types, llvm::LLVMContext &C) const override
Populate a vector of llvm::Types which describe this function signature. This method is used by Funct...
Definition: FunctionTypes.h:627
static std::string s()
Definition: FunctionTypes.h:137
SRetFunction(Args &&...ts)
Forward all arguments to the derived class.
Definition: FunctionTypes.h:569
FunctionBuilder & addSignature(const IRFunctionBase::GeneratorCb &cb, const Signature *ptr, const char *symbol=nullptr)
Definition: FunctionTypes.h:960
void setEmbedIR(bool on)
Enable or disable the embedding of IR. Embedded IR is currently required for function which use paren...
Definition: FunctionTypes.h:694
void llvmTypeToString(const llvm::Type *const type, std::string &str)
Prints an llvm type to a std string.
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:70
CFunction(const std::string &symbol, const SignatureT function)
Definition: FunctionTypes.h:621
static std::string s()
Definition: FunctionTypes.h:140
Represents a concrete IR function with the first argument as its return type.
Definition: FunctionTypes.h:780
The base/abstract definition for an IR function.
Definition: FunctionTypes.h:673
CFunctionSRet(const std::string &symbol, const SignatureT function)
Definition: FunctionTypes.h:772
Templated interface class for SRET functions. This struct provides the interface for functions that w...
Definition: FunctionTypes.h:488
void setArgumentNames(std::vector< const char * > names)
Definition: FunctionTypes.h:420
const std::vector< const char * > & dependencies() const
Definition: FunctionTypes.h:422
void verifyResultType(const llvm::Type *result, const llvm::Type *expected) const
Definition: FunctionTypes.h:726
llvm::FunctionType * llvmFunctionTypeFromSignature(llvm::LLVMContext &C)
Generate an LLVM FunctionType from a function signature.
Definition: FunctionTypes.h:227
static void apply(const OpT &, const bool)
Definition: FunctionTypes.h:190
IRFunction(const std::string &symbol, const GeneratorCb &gen)
Definition: FunctionTypes.h:756
Consolidated llvm types for most supported types.
Represents a concrete C function binding.
Definition: FunctionTypes.h:607
bool hasEmbedIR() const
Definition: FunctionTypes.h:695
void printSignature(std::ostream &os, const std::vector< llvm::Type * > &types, const llvm::Type *returnType, const char *name=nullptr, const std::vector< const char * > &names={}, const bool axTypes=false)
Print a function signature to the provided ostream.
Represents a concrete C function binding with the first argument as its return type.
Definition: FunctionTypes.h:769
Type[SIZE] ArrayType
Definition: FunctionTypes.h:105
Templated function traits which provides compile-time index access to the types of the function signa...
Definition: ax/openvdb_ax/codegen/Types.h:259
std::function< llvm::Value *(const std::vector< llvm::Value * > &, llvm::IRBuilder<> &)> GeneratorCb
The IR callback function which will write the LLVM IR for this function&#39;s body.
Definition: FunctionTypes.h:687
FunctionBuilder(const char *name)
Definition: FunctionTypes.h:903
llvm::Value * call(const std::vector< llvm::Value * > &args, llvm::IRBuilder<> &B, const bool cast) const override
Uses the IRBuilder to create a call to this function with the given arguments, creating the function ...
Definition: FunctionTypes.h:637
typename ArgT::Type ArgumentValueType
Definition: FunctionTypes.h:171
std::shared_ptr< FunctionGroup > Ptr
Definition: FunctionTypes.h:792
Function::SignatureMatch match(const std::vector< llvm::Type * > &args, llvm::LLVMContext &C) const override
Override of match which inserts the SRET type such that the base class methods ignore it...
Definition: FunctionTypes.h:515
The base class for all C bindings.
Definition: FunctionTypes.h:573
FunctionBuilder & addDependency(const char *name)
Definition: FunctionTypes.h:967
llvm::Value * insertStaticAlloca(llvm::IRBuilder<> &B, llvm::Type *type, llvm::Value *size=nullptr)
Insert a stack allocation at the beginning of the current function of the provided type and size...
Definition: openvdb_ax/openvdb_ax/codegen/Utils.h:123
std::shared_ptr< Settings > Ptr
Definition: FunctionTypes.h:882
Definition: FunctionTypes.h:351
void setRetAttributes(const std::vector< llvm::Attribute::AttrKind > &in)
Definition: FunctionTypes.h:429
Alias mapping between two types, a frontend type T1 and a backend type T2. This class is the intended...
Definition: ax/openvdb_ax/codegen/Types.h:218
DeclPreferrence
Definition: FunctionTypes.h:876
uint64_t address() const override final
Returns the global address of this function.
Definition: FunctionTypes.h:632
std::shared_ptr< Function > Ptr
Definition: FunctionTypes.h:263
FunctionBuilder & addReturnAttribute(const llvm::Attribute::AttrKind attr)
Definition: FunctionTypes.h:1048
bool isDefault() const
Definition: FunctionTypes.h:884
static std::string s()
Definition: FunctionTypes.h:144
Constant folding support structure.
Definition: ConstantFolding.h:34
FunctionGroup(const char *name, const char *doc, const FunctionList &list)
Definition: FunctionTypes.h:796
void print(llvm::LLVMContext &C, std::ostream &os, const char *name=nullptr, const bool axTypes=true) const override
Override of print to avoid printing out the SRET type.
Definition: FunctionTypes.h:546
FunctionBuilder & addParameterAttribute(const size_t idx, const llvm::Attribute::AttrKind attr)
Definition: FunctionTypes.h:1042
Represents a concrete IR function.
Definition: FunctionTypes.h:751
Definition: openvdb/Exceptions.h:13
llvm::Type * llvmTypesFromSignature(llvm::LLVMContext &C, std::vector< llvm::Type * > *types=nullptr)
Populate a vector of llvm types from a function signature declaration.
Definition: FunctionTypes.h:203
Definition: ax/openvdb_ax/Exceptions.h:36
Object to array conversion methods to allow functions to return vector types. These containers provid...
Definition: FunctionTypes.h:102
const char * symbol() const
The function symbol name.
Definition: FunctionTypes.h:381
static std::string s()
Definition: FunctionTypes.h:134
Function(const size_t size, const std::string &symbol)
Definition: FunctionTypes.h:265
static std::string s()
Definition: FunctionTypes.h:139
The base/abstract representation of an AX function. Derived classes must implement the Function::type...
Definition: FunctionTypes.h:261
todo
Definition: FunctionTypes.h:790
LLVM type mapping from pod types.
Definition: ax/openvdb_ax/codegen/Types.h:54
const char * name() const
Definition: FunctionTypes.h:856
const char * argName(const size_t idx) const
Returns the descriptive name of the given argument index.
Definition: FunctionTypes.h:388
std::unique_ptr< FunctionGroup > UniquePtr
Definition: FunctionTypes.h:793
FunctionBuilder & setArgumentNames(const std::vector< const char * > &names)
Definition: FunctionTypes.h:973
T Type
Definition: FunctionTypes.h:103
The FunctionBuilder class provides a builder pattern framework to allow easy and valid construction o...
Definition: FunctionTypes.h:874
static std::string s()
Definition: FunctionTypes.h:135
static std::string s()
Definition: FunctionTypes.h:149
Constant folding for C++ bindings.
An extremely basic but native representation of a string class with SSO support. This exists to provi...
Definition: String.h:33
FunctionBuilder & setDocumentation(const char *doc)
Definition: FunctionTypes.h:1059
const GeneratorCb mGen
Definition: FunctionTypes.h:745
const FunctionList & list() const
Accessor to the underlying function signature list.
Definition: FunctionTypes.h:855
llvm::Value * fold(const std::vector< llvm::Value * > &args, llvm::LLVMContext &C) const override final
Definition: FunctionTypes.h:646
FunctionBuilder & setConstantFold(bool on)
Definition: FunctionTypes.h:972
std::vector< Function::Ptr > FunctionList
Definition: FunctionTypes.h:794
Type to symbol conversions - these characters are used to build each functions unique signature...
Definition: FunctionTypes.h:132
FunctionBuilder & setPreferredImpl(DeclPreferrence pref)
Definition: FunctionTypes.h:1060
IRFunctionBase(const std::string &symbol, const GeneratorCb &gen, const size_t size)
Definition: FunctionTypes.h:737
void setParamAttributes(const size_t i, const std::vector< llvm::Attribute::AttrKind > &in)
Definition: FunctionTypes.h:433
Utility code generation methods for performing various llvm operations.
void setFnAttributes(const std::vector< llvm::Attribute::AttrKind > &in)
Definition: FunctionTypes.h:425
void setDependencies(std::vector< const char * > deps)
Definition: FunctionTypes.h:423
SignatureMatch
The result type from calls to Function::match.
Definition: FunctionTypes.h:351
CFunctionBase(const size_t size, const std::string &symbol)
Definition: FunctionTypes.h:592
bool hasConstantFold() const
Definition: FunctionTypes.h:584
virtual llvm::Value * fold(const std::vector< llvm::Value * > &, llvm::LLVMContext &) const
Definition: FunctionTypes.h:586
size_t size() const
The number of arguments that this function has.
Definition: FunctionTypes.h:377
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
FunctionBuilder & addSignature(const IRFunctionBase::GeneratorCb &cb, const char *symbol=nullptr)
Definition: FunctionTypes.h:910
typename FunctionTraits< SignatureT >::template Arg< I-1 > ArgT
Definition: FunctionTypes.h:170
FunctionBuilder & addFunctionAttribute(const llvm::Attribute::AttrKind attr)
Definition: FunctionTypes.h:1054
void setConstantFold(bool on)
Definition: FunctionTypes.h:583
static void apply(const OpT &op, const bool forwards)
Definition: FunctionTypes.h:174
ArrayType mData
Definition: FunctionTypes.h:106
static std::string s()
Definition: FunctionTypes.h:138
IRFunctionSRet(const std::string &symbol, const IRFunctionBase::GeneratorCb &gen)
Definition: FunctionTypes.h:783
Templated argument iterator which implements various small functions per argument type...
Definition: FunctionTypes.h:168
void print(const ast::Node &node, const bool numberStatements=true, std::ostream &os=std::cout, const char *indent=" ")
Writes a descriptive printout of a Node hierarchy into a target stream.
bool hasParamAttribute(const size_t i, const llvm::Attribute::AttrKind &kind) const
Builder methods.
Definition: FunctionTypes.h:410
static std::string s()
Definition: FunctionTypes.h:136
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:178
llvm::Type * types(std::vector< llvm::Type * > &types, llvm::LLVMContext &C) const override
Populate a vector of llvm::Types which describe this function signature. This method is used by Funct...
Definition: FunctionTypes.h:760
bool mEmbedIR
Definition: FunctionTypes.h:746