OpenVDB  8.0.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<AXString> { 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 
304  virtual llvm::Function*
305  create(llvm::LLVMContext& C, llvm::Module* M = nullptr) const;
306 
310  llvm::Function* create(llvm::Module& M) const {
311  return this->create(M.getContext(), &M);
312  }
313 
335  virtual llvm::Value*
336  call(const std::vector<llvm::Value*>& args,
337  llvm::IRBuilder<>& B,
338  const bool cast = false) const;
339 
341  enum SignatureMatch { None = 0, Size, Implicit, Explicit };
342 
364  virtual SignatureMatch match(const std::vector<llvm::Type*>& inputs, llvm::LLVMContext& C) const;
365 
367  inline size_t size() const { return mSize; }
368 
371  inline const char* symbol() const { return mSymbol.c_str(); }
372 
378  inline const char* argName(const size_t idx) const {
379  return idx < mNames.size() ? mNames[idx] : "";
380  }
381 
393  virtual void print(llvm::LLVMContext& C,
394  std::ostream& os,
395  const char* name = nullptr,
396  const bool axTypes = true) const;
397 
399 
400  inline bool hasParamAttribute(const size_t i,
401  const llvm::Attribute::AttrKind& kind) const
402  {
403  if (!mAttributes) return false;
404  const auto iter = mAttributes->mParamAttrs.find(i);
405  if (iter == mAttributes->mParamAttrs.end()) return false;
406  const auto& vec = iter->second;
407  return std::find(vec.begin(), vec.end(), kind) != vec.end();
408  }
409 
410  inline void setArgumentNames(std::vector<const char*> names) { mNames = names; }
411 
412  const std::vector<const char*>& dependencies() const { return mDeps; }
413  inline void setDependencies(std::vector<const char*> deps) { mDeps = deps; }
414 
415  inline void setFnAttributes(const std::vector<llvm::Attribute::AttrKind>& in)
416  {
417  this->attrs().mFnAttrs = in;
418  }
419  inline void setRetAttributes(const std::vector<llvm::Attribute::AttrKind>& in)
420  {
421  this->attrs().mRetAttrs = in;
422  }
423  inline void setParamAttributes(const size_t i,
424  const std::vector<llvm::Attribute::AttrKind>& in)
425  {
426  this->attrs().mParamAttrs[i] = in;
427  }
428 
429 protected:
430 
438  static void cast(std::vector<llvm::Value*>& args,
439  const std::vector<llvm::Type*>& types,
440  llvm::IRBuilder<>& B);
441 
442 private:
443 
444  struct Attributes {
445  std::vector<llvm::Attribute::AttrKind> mFnAttrs, mRetAttrs;
446  std::map<size_t, std::vector<llvm::Attribute::AttrKind>> mParamAttrs;
447  };
448 
449  inline Attributes& attrs() {
450  if (!mAttributes) mAttributes.reset(new Attributes());
451  return *mAttributes;
452  }
453 
454  llvm::AttributeList flattenAttrs(llvm::LLVMContext& C) const;
455 
456  const size_t mSize;
457  const std::string mSymbol;
458  std::unique_ptr<Attributes> mAttributes;
459  std::vector<const char*> mNames;
460  std::vector<const char*> mDeps;
461 };
462 
477 template <typename SignatureT, typename DerivedFunction>
478 struct SRetFunction : public DerivedFunction
479 {
480  using Ptr = std::shared_ptr<SRetFunction<SignatureT, DerivedFunction>>;
482 
483  // check there actually are arguments
484  static_assert(Traits::N_ARGS > 0,
485  "SRET Function object has been setup with the first argument as the return "
486  "value, however the provided signature is empty.");
487 
488  // check no return value exists
489  static_assert(std::is_same<typename Traits::ReturnType, void>::value,
490  "SRET Function object has been setup with the first argument as the return "
491  "value and a non void return type.");
492 
493 private:
494 
495  using FirstArgument = typename Traits::template Arg<0>::Type;
496  static_assert(std::is_pointer<FirstArgument>::value,
497  "SRET Function object has been setup with the first argument as the return "
498  "value, but this argument it is not a pointer type.");
499  using SRetType = typename std::remove_pointer<FirstArgument>::type;
500 
501 public:
502 
505  Function::SignatureMatch match(const std::vector<llvm::Type*>& args,
506  llvm::LLVMContext& C) const override
507  {
508  // append return type and right rotate
509  std::vector<llvm::Type*> inputs(args);
510  inputs.emplace_back(LLVMType<SRetType*>::get(C));
511  std::rotate(inputs.rbegin(), inputs.rbegin() + 1, inputs.rend());
512  return DerivedFunction::match(inputs, C);
513  }
514 
521  llvm::Value*
522  call(const std::vector<llvm::Value*>& args,
523  llvm::IRBuilder<>& B,
524  const bool cast) const override
525  {
526  // append return value and right rotate
527  std::vector<llvm::Value*> inputs(args);
528  llvm::Type* sret = LLVMType<SRetType>::get(B.getContext());
529  inputs.emplace_back(insertStaticAlloca(B, sret));
530  std::rotate(inputs.rbegin(), inputs.rbegin() + 1, inputs.rend());
531  DerivedFunction::call(inputs, B, cast);
532  return inputs.front();
533  }
534 
536  void print(llvm::LLVMContext& C,
537  std::ostream& os,
538  const char* name = nullptr,
539  const bool axTypes = true) const override
540  {
541  std::vector<llvm::Type*> current;
542  llvm::Type* ret = this->types(current, C);
543  // left rotate
544  std::rotate(current.begin(), current.begin() + 1, current.end());
545  ret = current.back();
546  current.pop_back();
547 
548  std::vector<const char*> names;
549  names.reserve(this->size());
550  for (size_t i = 0; i < this->size()-1; ++i) {
551  names.emplace_back(this->argName(i));
552  }
553  printSignature(os, current, ret, name, names, axTypes);
554  }
555 
556 protected:
558  template <typename ...Args>
559  SRetFunction(Args&&... ts) : DerivedFunction(ts...) {}
560 };
561 
563 struct CFunctionBase : public Function
564 {
565  using Ptr = std::shared_ptr<CFunctionBase>;
566 
567  ~CFunctionBase() override = default;
568 
571  virtual uint64_t address() const = 0;
572 
573  inline void setConstantFold(bool on) { mConstantFold = on; }
574  inline bool hasConstantFold() const { return mConstantFold; }
575 
576  inline virtual llvm::Value* fold(const std::vector<llvm::Value*>&,
577  llvm::LLVMContext&) const {
578  return nullptr;
579  }
580 
581 protected:
582  CFunctionBase(const size_t size,
583  const std::string& symbol)
584  : Function(size, symbol)
585  , mConstantFold(false) {}
586 
587 private:
588  bool mConstantFold;
589 };
590 
596 template <typename SignatureT>
597 struct CFunction : public CFunctionBase
598 {
600  using Ptr = std::shared_ptr<CFunctionT>;
602 
603  // Assert that the return argument is not a pointer. Note that this is
604  // relaxed for IR functions where it's allowed if the function is embedded.
605  static_assert(!std::is_pointer<typename Traits::ReturnType>::value,
606  "CFunction object has been setup with a pointer return argument. C bindings "
607  "cannot return memory locations to LLVM - Consider using a CFunctionSRet.");
608 
609  CFunction(const std::string& symbol, const SignatureT function)
610  : CFunctionBase(Traits::N_ARGS, symbol)
611  , mFunction(function) {}
612 
613  ~CFunction() override = default;
614 
615  inline llvm::Type* types(std::vector<llvm::Type*>& types, llvm::LLVMContext& C) const override
616  {
617  return llvmTypesFromSignature<SignatureT>(C, &types);
618  }
619 
620  inline uint64_t address() const override final {
621  return reinterpret_cast<uint64_t>(mFunction);
622  }
623 
624  llvm::Value*
625  call(const std::vector<llvm::Value*>& args,
626  llvm::IRBuilder<>& B,
627  const bool cast) const override
628  {
629  llvm::Value* result = this->fold(args, B.getContext());
630  if (result) return result;
631  return Function::call(args, B, cast);
632  }
633 
634  llvm::Value* fold(const std::vector<llvm::Value*>& args, llvm::LLVMContext& C) const override final
635  {
636  auto allconst =
637  [](const std::vector<llvm::Value*>& vals) -> bool {
638  for (auto& value : vals) {
639  if (!llvm::isa<llvm::Constant>(value)) return false;
640  }
641  return true;
642  };
643 
644  if (!this->hasConstantFold()) return nullptr;
645  if (!allconst(args)) return nullptr;
646  std::vector<llvm::Constant*> constants;
647  constants.reserve(args.size());
648  for (auto& value : args) {
649  constants.emplace_back(llvm::cast<llvm::Constant>(value));
650  }
651 
652  // no guarantee that fold() will be able to cast all arguments
653  return ConstantFolder<SignatureT>::fold(constants, *mFunction, C);
654  }
655 
656 private:
657  const SignatureT* mFunction;
658 };
659 
661 struct IRFunctionBase : public Function
662 {
663  using Ptr = std::shared_ptr<IRFunctionBase>;
664 
674  using GeneratorCb = std::function<llvm::Value*
675  (const std::vector<llvm::Value*>&, llvm::IRBuilder<>&)>;
676 
677  llvm::Type* types(std::vector<llvm::Type*>& types,
678  llvm::LLVMContext& C) const override = 0;
679 
682  inline void setEmbedIR(bool on) { mEmbedIR = on; }
683  inline bool hasEmbedIR() const { return mEmbedIR; }
684 
697  llvm::Function*
698  create(llvm::LLVMContext& C, llvm::Module* M) const override;
699 
704  llvm::Value*
705  call(const std::vector<llvm::Value*>& args,
706  llvm::IRBuilder<>& B,
707  const bool cast) const override;
708 
709 protected:
710 
711  // @todo This should ideally live in FunctionGroup::execute, but the return
712  // type is allowed to differ for sret C bindings.
713  inline void
714  verifyResultType(const llvm::Type* result, const llvm::Type* expected) const
715  {
716  if (result == expected) return;
717  std::string source, target;
718  if (result) llvmTypeToString(result, source);
719  llvmTypeToString(expected, target);
720  OPENVDB_THROW(AXCodeGenError, "Function \"" + std::string(this->symbol()) +
721  "\" has been invoked with a mismatching return type. Expected: \"" +
722  target + "\", got \"" + source + "\".");
723  }
724 
725  IRFunctionBase(const std::string& symbol,
726  const GeneratorCb& gen,
727  const size_t size)
728  : Function(size, symbol)
729  , mGen(gen)
730  , mEmbedIR(false) {}
731  ~IRFunctionBase() override = default;
732 
734  bool mEmbedIR;
735 };
736 
738 template <typename SignatureT>
739 struct IRFunction : public IRFunctionBase
740 {
742  using Ptr = std::shared_ptr<IRFunction>;
743 
744  IRFunction(const std::string& symbol, const GeneratorCb& gen)
745  : IRFunctionBase(symbol, gen, Traits::N_ARGS) {}
746 
747  inline llvm::Type*
748  types(std::vector<llvm::Type*>& types, llvm::LLVMContext& C) const override
749  {
750  return llvmTypesFromSignature<SignatureT>(C, &types);
751  }
752 };
753 
756 template <typename SignatureT>
757 struct CFunctionSRet : public SRetFunction<SignatureT, CFunction<SignatureT>>
758 {
760  CFunctionSRet(const std::string& symbol, const SignatureT function)
761  : BaseT(symbol, function) {}
762  ~CFunctionSRet() override = default;
763 };
764 
767 template <typename SignatureT>
768 struct IRFunctionSRet : public SRetFunction<SignatureT, IRFunction<SignatureT>>
769 {
771  IRFunctionSRet(const std::string& symbol,
772  const IRFunctionBase::GeneratorCb& gen)
773  : BaseT(symbol, gen) {}
774  ~IRFunctionSRet() override = default;
775 };
776 
779 {
780  using Ptr = std::shared_ptr<FunctionGroup>;
781  using UniquePtr = std::unique_ptr<FunctionGroup>;
782  using FunctionList = std::vector<Function::Ptr>;
783 
784  FunctionGroup(const char* name,
785  const char* doc,
786  const FunctionList& list)
787  : mName(name)
788  , mDoc(doc)
789  , mFunctionList(list) {}
790  ~FunctionGroup() = default;
791 
807  match(const std::vector<llvm::Type*>& types,
808  llvm::LLVMContext& C,
809  Function::SignatureMatch* type = nullptr) const;
810 
822  llvm::Value*
823  execute(const std::vector<llvm::Value*>& args,
824  llvm::IRBuilder<>& B) const;
825 
828  inline const FunctionList& list() const { return mFunctionList; }
829  const char* name() const { return mName; }
830  const char* doc() const { return mDoc; }
831 
832 private:
833  const char* mName;
834  const char* mDoc;
835  const FunctionList mFunctionList;
836 };
837 
848 {
850  C, IR, Any
851  };
852 
853  struct Settings
854  {
855  using Ptr = std::shared_ptr<Settings>;
856 
857  inline bool isDefault() const {
858  if (mNames) return false;
859  if (!mDeps.empty()) return false;
860  if (mConstantFold || mEmbedIR) return false;
861  if (!mFnAttrs.empty()) return false;
862  if (!mRetAttrs.empty()) return false;
863  if (!mParamAttrs.empty()) return false;
864  return true;
865  }
866 
867  std::shared_ptr<std::vector<const char*>> mNames = nullptr;
868  std::vector<const char*> mDeps = {};
869  bool mConstantFold = false;
870  bool mEmbedIR = false;
871  std::vector<llvm::Attribute::AttrKind> mFnAttrs = {};
872  std::vector<llvm::Attribute::AttrKind> mRetAttrs = {};
873  std::map<size_t, std::vector<llvm::Attribute::AttrKind>> mParamAttrs = {};
874  };
875 
876  FunctionBuilder(const char* name)
877  : mName(name)
878  , mCurrentSettings(new Settings()) {}
879 
880 
881  template <typename Signature, bool SRet = false>
882  inline FunctionBuilder&
884  const char* symbol = nullptr)
885  {
886  using IRFType = typename std::conditional
888  using IRPtr = typename IRFType::Ptr;
889 
890  Settings::Ptr settings = mCurrentSettings;
891  if (!mCurrentSettings->isDefault()) {
892  settings.reset(new Settings());
893  }
894 
895  std::string s;
896  if (symbol) s = std::string(symbol);
897  else s = this->genSymbol<Signature>();
898 
899  auto ir = IRPtr(new IRFType(s, cb));
900  mIRFunctions.emplace_back(ir);
901  mSettings[ir.get()] = settings;
902  mCurrentSettings = settings;
903  return *this;
904  }
905 
906  template <typename Signature, bool SRet = false>
907  inline FunctionBuilder&
908  addSignature(const Signature* ptr,
909  const char* symbol = nullptr)
910  {
911  using CFType = typename std::conditional
913  using CPtr = typename CFType::Ptr;
914 
915  Settings::Ptr settings = mCurrentSettings;
916  if (!mCurrentSettings->isDefault()) {
917  settings.reset(new Settings());
918  }
919 
920  std::string s;
921  if (symbol) s = std::string(symbol);
922  else s = this->genSymbol<Signature>();
923 
924  auto c = CPtr(new CFType(s, ptr));
925  mCFunctions.emplace_back(c);
926  mSettings[c.get()] = settings;
927  mCurrentSettings = settings;
928  return *this;
929  }
930 
931  template <typename Signature, bool SRet = false>
932  inline FunctionBuilder&
933  addSignature(const IRFunctionBase::GeneratorCb& cb, const Signature* ptr, const char* symbol = nullptr)
934  {
935  this->addSignature<Signature, SRet>(cb, symbol);
936  this->addSignature<Signature, SRet>(ptr, symbol);
937  return *this;
938  }
939 
940  inline FunctionBuilder& addDependency(const char* name) {
941  mCurrentSettings->mDeps.emplace_back(name); return *this;
942  }
943 
944  inline FunctionBuilder& setEmbedIR(bool on) { mCurrentSettings->mEmbedIR = on; return *this; }
945  inline FunctionBuilder& setConstantFold(bool on) { mCurrentSettings->mConstantFold = on; return *this; }
946  inline FunctionBuilder& setArgumentNames(const std::vector<const char*>& names) {
947  mCurrentSettings->mNames.reset(new std::vector<const char*>(names));
948  return *this;
949  }
950 
1014  inline FunctionBuilder&
1015  addParameterAttribute(const size_t idx, const llvm::Attribute::AttrKind attr) {
1016  mCurrentSettings->mParamAttrs[idx].emplace_back(attr);
1017  return *this;
1018  }
1019 
1020  inline FunctionBuilder&
1021  addReturnAttribute(const llvm::Attribute::AttrKind attr) {
1022  mCurrentSettings->mRetAttrs.emplace_back(attr);
1023  return *this;
1024  }
1025 
1026  inline FunctionBuilder&
1027  addFunctionAttribute(const llvm::Attribute::AttrKind attr) {
1028  mCurrentSettings->mFnAttrs.emplace_back(attr);
1029  return *this;
1030  }
1031 
1032  inline FunctionBuilder& setDocumentation(const char* doc) { mDoc = doc; return *this; }
1033  inline FunctionBuilder& setPreferredImpl(DeclPreferrence pref) { mDeclPref = pref; return *this; }
1034 
1036  {
1037  for (auto& decl : mCFunctions) {
1038  const auto& s = mSettings.at(decl.get());
1039  decl->setDependencies(s->mDeps);
1040  decl->setConstantFold(s->mConstantFold);
1041  if (!s->mFnAttrs.empty()) decl->setFnAttributes(s->mFnAttrs);
1042  if (!s->mRetAttrs.empty()) decl->setRetAttributes(s->mRetAttrs);
1043  if (!s->mParamAttrs.empty()) {
1044  for (auto& idxAttrs : s->mParamAttrs) {
1045  if (idxAttrs.first > decl->size()) continue;
1046  decl->setParamAttributes(idxAttrs.first, idxAttrs.second);
1047  }
1048  }
1049  if (s->mNames) decl->setArgumentNames(*s->mNames);
1050  }
1051 
1052  for (auto& decl : mIRFunctions) {
1053  const auto& s = mSettings.at(decl.get());
1054  decl->setDependencies(s->mDeps);
1055  decl->setEmbedIR(s->mEmbedIR);
1056  if (!s->mFnAttrs.empty()) decl->setFnAttributes(s->mFnAttrs);
1057  if (!s->mRetAttrs.empty()) decl->setRetAttributes(s->mRetAttrs);
1058  if (!s->mParamAttrs.empty()) {
1059  for (auto& idxAttrs : s->mParamAttrs) {
1060  if (idxAttrs.first > decl->size()) continue;
1061  decl->setParamAttributes(idxAttrs.first, idxAttrs.second);
1062  }
1063  }
1064  if (s->mNames) decl->setArgumentNames(*s->mNames);
1065  }
1066 
1067  std::vector<Function::Ptr> functions;
1068 
1069  if (mDeclPref == DeclPreferrence::IR) {
1070  functions.insert(functions.end(), mIRFunctions.begin(), mIRFunctions.end());
1071  }
1072  if (mDeclPref == DeclPreferrence::C) {
1073  functions.insert(functions.end(), mCFunctions.begin(), mCFunctions.end());
1074  }
1075  if (functions.empty()) {
1076  functions.insert(functions.end(), mIRFunctions.begin(), mIRFunctions.end());
1077  functions.insert(functions.end(), mCFunctions.begin(), mCFunctions.end());
1078  }
1079 
1080  FunctionGroup::UniquePtr group(new FunctionGroup(mName, mDoc, functions));
1081  return group;
1082  }
1083 
1084 private:
1085 
1086  template <typename Signature>
1087  std::string genSymbol() const
1088  {
1089  using Traits = FunctionTraits<Signature>;
1090 
1091  std::string args;
1092  auto callback = [&args](auto type) {
1093  using Type = decltype(type);
1094  args += TypeToSymbol<Type>::s();
1095  };
1096 
1097  ArgumentIterator<Signature>::apply(callback, /*forwards*/true);
1101 
1102  // assemble the symbol
1103  return "ax." + std::string(this->mName) + "." +
1104  TypeToSymbol<typename Traits::ReturnType>::s() + args;
1105  }
1106 
1107  const char* mName = "";
1108  const char* mDoc = "";
1109  DeclPreferrence mDeclPref = IR;
1110  std::vector<CFunctionBase::Ptr> mCFunctions = {};
1111  std::vector<IRFunctionBase::Ptr> mIRFunctions = {};
1112  std::map<const Function*, Settings::Ptr> mSettings = {};
1113  Settings::Ptr mCurrentSettings = nullptr;
1114 };
1115 
1116 } // namespace codegen
1117 } // namespace ax
1118 } // namespace OPENVDB_VERSION_NAME
1119 } // namespace openvdb
1120 
1121 #endif // OPENVDB_AX_CODEGEN_FUNCTION_TYPES_HAS_BEEN_INCLUDED
1122 
Constant folding for C++ bindings.
Consolidated llvm types for most supported types.
Definition: ax/openvdb_ax/Exceptions.h:36
3x3 matrix class.
Definition: Mat3.h:29
4x4 -matrix class.
Definition: Mat4.h:24
Definition: Vec2.h:24
Definition: Vec3.h:24
Definition: Vec4.h:25
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
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
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.
llvm::FunctionType * llvmFunctionTypeFromSignature(llvm::LLVMContext &C)
Generate an LLVM FunctionType from a function signature.
Definition: FunctionTypes.h:227
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
Definition: openvdb/Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
Utility code generation methods for performing various llvm operations.
The backend representation of strings in AX. This is also how strings are passed from the AX code gen...
Definition: CustomData.h:31
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:239
Object to array conversion methods to allow functions to return vector types. These containers provid...
Definition: FunctionTypes.h:102
T Type
Definition: FunctionTypes.h:103
ArrayType mData
Definition: FunctionTypes.h:106
Type[SIZE] ArrayType
Definition: FunctionTypes.h:105
static void apply(const OpT &, const bool)
Definition: FunctionTypes.h:190
Templated argument iterator which implements various small functions per argument type,...
Definition: FunctionTypes.h:169
static void apply(const OpT &op, const bool forwards)
Definition: FunctionTypes.h:174
typename FunctionTraits< SignatureT >::template Arg< I-1 > ArgT
Definition: FunctionTypes.h:170
typename ArgT::Type ArgumentValueType
Definition: FunctionTypes.h:171
The base class for all C bindings.
Definition: FunctionTypes.h:564
bool hasConstantFold() const
Definition: FunctionTypes.h:574
void setConstantFold(bool on)
Definition: FunctionTypes.h:573
virtual uint64_t address() const =0
Returns the global address of this function.
CFunctionBase(const size_t size, const std::string &symbol)
Definition: FunctionTypes.h:582
virtual llvm::Value * fold(const std::vector< llvm::Value * > &, llvm::LLVMContext &) const
Definition: FunctionTypes.h:576
Represents a concrete C function binding with the first argument as its return type.
Definition: FunctionTypes.h:758
CFunctionSRet(const std::string &symbol, const SignatureT function)
Definition: FunctionTypes.h:760
Represents a concrete C function binding.
Definition: FunctionTypes.h:598
uint64_t address() const override final
Returns the global address of this function.
Definition: FunctionTypes.h:620
CFunction(const std::string &symbol, const SignatureT function)
Definition: FunctionTypes.h:609
llvm::Value * fold(const std::vector< llvm::Value * > &args, llvm::LLVMContext &C) const override final
Definition: FunctionTypes.h:634
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:615
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:625
Constant folding support structure.
Definition: ConstantFolding.h:35
std::shared_ptr< Settings > Ptr
Definition: FunctionTypes.h:855
bool isDefault() const
Definition: FunctionTypes.h:857
The FunctionBuilder class provides a builder pattern framework to allow easy and valid construction o...
Definition: FunctionTypes.h:848
FunctionGroup::UniquePtr get() const
Definition: FunctionTypes.h:1035
FunctionBuilder & setDocumentation(const char *doc)
Definition: FunctionTypes.h:1032
FunctionBuilder & setArgumentNames(const std::vector< const char * > &names)
Definition: FunctionTypes.h:946
FunctionBuilder & setEmbedIR(bool on)
Definition: FunctionTypes.h:944
DeclPreferrence
Definition: FunctionTypes.h:849
@ C
Definition: FunctionTypes.h:850
FunctionBuilder & addSignature(const IRFunctionBase::GeneratorCb &cb, const Signature *ptr, const char *symbol=nullptr)
Definition: FunctionTypes.h:933
FunctionBuilder & setConstantFold(bool on)
Definition: FunctionTypes.h:945
FunctionBuilder & addSignature(const IRFunctionBase::GeneratorCb &cb, const char *symbol=nullptr)
Definition: FunctionTypes.h:883
FunctionBuilder & addDependency(const char *name)
Definition: FunctionTypes.h:940
FunctionBuilder & addSignature(const Signature *ptr, const char *symbol=nullptr)
Definition: FunctionTypes.h:908
FunctionBuilder(const char *name)
Definition: FunctionTypes.h:876
FunctionBuilder & addFunctionAttribute(const llvm::Attribute::AttrKind attr)
Definition: FunctionTypes.h:1027
FunctionBuilder & addParameterAttribute(const size_t idx, const llvm::Attribute::AttrKind attr)
Definition: FunctionTypes.h:1015
FunctionBuilder & addReturnAttribute(const llvm::Attribute::AttrKind attr)
Definition: FunctionTypes.h:1021
FunctionBuilder & setPreferredImpl(DeclPreferrence pref)
Definition: FunctionTypes.h:1033
todo
Definition: FunctionTypes.h:779
const char * doc() const
Definition: FunctionTypes.h:830
const FunctionList & list() const
Accessor to the underlying function signature list.
Definition: FunctionTypes.h:828
std::vector< Function::Ptr > FunctionList
Definition: FunctionTypes.h:782
std::shared_ptr< FunctionGroup > Ptr
Definition: FunctionTypes.h:780
llvm::Value * execute(const std::vector< llvm::Value * > &args, llvm::IRBuilder<> &B) const
Given a vector of llvm values provided by the user, find the best possible function signature,...
std::unique_ptr< FunctionGroup > UniquePtr
Definition: FunctionTypes.h:781
const char * name() const
Definition: FunctionTypes.h:829
Function::Ptr match(const std::vector< llvm::Type * > &types, llvm::LLVMContext &C, Function::SignatureMatch *type=nullptr) const
Given a vector of llvm types, automatically returns the best possible function declaration from the s...
FunctionGroup(const char *name, const char *doc, const FunctionList &list)
Definition: FunctionTypes.h:784
Templated function traits which provides compile-time index access to the types of the function signa...
Definition: ax/openvdb_ax/codegen/Types.h:279
The base/abstract representation of an AX function. Derived classes must implement the Function::type...
Definition: FunctionTypes.h:262
virtual void print(llvm::LLVMContext &C, std::ostream &os, const char *name=nullptr, const bool axTypes=true) const
Print this function's signature to the provided ostream.
void setDependencies(std::vector< const char * > deps)
Definition: FunctionTypes.h:413
virtual llvm::Value * call(const std::vector< llvm::Value * > &args, llvm::IRBuilder<> &B, const bool cast=false) const
Uses the IRBuilder to create a call to this function with the given arguments, creating the function ...
size_t size() const
The number of arguments that this function has.
Definition: FunctionTypes.h:367
void setParamAttributes(const size_t i, const std::vector< llvm::Attribute::AttrKind > &in)
Definition: FunctionTypes.h:423
const char * symbol() const
The function symbol name.
Definition: FunctionTypes.h:371
static void cast(std::vector< llvm::Value * > &args, const std::vector< llvm::Type * > &types, llvm::IRBuilder<> &B)
Cast the provided arguments to the given type as supported by implicit casting of function types....
virtual llvm::Type * types(std::vector< llvm::Type * > &, llvm::LLVMContext &) const =0
Populate a vector of llvm::Types which describe this function signature. This method is used by Funct...
virtual llvm::Function * create(llvm::LLVMContext &C, llvm::Module *M=nullptr) const
Converts and creates this AX function into a llvm Function.
Function(const size_t size, const std::string &symbol)
Definition: FunctionTypes.h:265
void setRetAttributes(const std::vector< llvm::Attribute::AttrKind > &in)
Definition: FunctionTypes.h:419
const std::vector< const char * > & dependencies() const
Definition: FunctionTypes.h:412
void setFnAttributes(const std::vector< llvm::Attribute::AttrKind > &in)
Definition: FunctionTypes.h:415
std::shared_ptr< Function > Ptr
Definition: FunctionTypes.h:263
bool hasParamAttribute(const size_t i, const llvm::Attribute::AttrKind &kind) const
Builder methods.
Definition: FunctionTypes.h:400
virtual SignatureMatch match(const std::vector< llvm::Type * > &inputs, llvm::LLVMContext &C) const
The base implementation for determining how a vector of llvm arguments translates to this functions s...
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:310
const char * argName(const size_t idx) const
Returns the descriptive name of the given argument index.
Definition: FunctionTypes.h:378
SignatureMatch
The result type from calls to Function::match.
Definition: FunctionTypes.h:341
void setArgumentNames(std::vector< const char * > names)
Definition: FunctionTypes.h:410
The base/abstract definition for an IR function.
Definition: FunctionTypes.h:662
llvm::Function * create(llvm::LLVMContext &C, llvm::Module *M) const override
Override for the creation of an IR function. This ensures that the body and prototype of the function...
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's body.
Definition: FunctionTypes.h:675
bool hasEmbedIR() const
Definition: FunctionTypes.h:683
void setEmbedIR(bool on)
Enable or disable the embedding of IR. Embedded IR is currently required for function which use paren...
Definition: FunctionTypes.h:682
llvm::Type * types(std::vector< llvm::Type * > &types, llvm::LLVMContext &C) const override=0
Populate a vector of llvm::Types which describe this function signature. This method is used by Funct...
const GeneratorCb mGen
Definition: FunctionTypes.h:733
bool mEmbedIR
Definition: FunctionTypes.h:734
IRFunctionBase(const std::string &symbol, const GeneratorCb &gen, const size_t size)
Definition: FunctionTypes.h:725
void verifyResultType(const llvm::Type *result, const llvm::Type *expected) const
Definition: FunctionTypes.h:714
llvm::Value * call(const std::vector< llvm::Value * > &args, llvm::IRBuilder<> &B, const bool cast) const override
Override for call, which is only necessary if mEmbedIR is true, as the IR generation for embedded fun...
Represents a concrete IR function with the first argument as its return type.
Definition: FunctionTypes.h:769
IRFunctionSRet(const std::string &symbol, const IRFunctionBase::GeneratorCb &gen)
Definition: FunctionTypes.h:771
Represents a concrete IR function.
Definition: FunctionTypes.h:740
IRFunction(const std::string &symbol, const GeneratorCb &gen)
Definition: FunctionTypes.h:744
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:748
LLVM type mapping from pod types.
Definition: ax/openvdb_ax/codegen/Types.h:55
Templated interface class for SRET functions. This struct provides the interface for functions that w...
Definition: FunctionTypes.h:479
std::shared_ptr< SRetFunction< SignatureT, DerivedFunction > > Ptr
Definition: FunctionTypes.h:480
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:536
SRetFunction(Args &&... ts)
Forward all arguments to the derived class.
Definition: FunctionTypes.h:559
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:505
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:522
static std::string s()
Definition: FunctionTypes.h:140
static std::string s()
Definition: FunctionTypes.h:144
static std::string s()
Definition: FunctionTypes.h:149
static std::string s()
Definition: FunctionTypes.h:134
static std::string s()
Definition: FunctionTypes.h:139
static std::string s()
Definition: FunctionTypes.h:138
static std::string s()
Definition: FunctionTypes.h:135
static std::string s()
Definition: FunctionTypes.h:136
static std::string s()
Definition: FunctionTypes.h:137
static std::string s()
Definition: FunctionTypes.h:133
Type to symbol conversions - these characters are used to build each functions unique signature....
Definition: FunctionTypes.h:132
static std::string s()
Definition: FunctionTypes.h:132
Library and file format version numbers.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153