1*0fca6ea1SDimitry Andric //===--- FunctionPointer.h - Types for the constexpr VM ---------*- C++ -*-===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric 906c3fb27SDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_FUNCTION_POINTER_H 1006c3fb27SDimitry Andric #define LLVM_CLANG_AST_INTERP_FUNCTION_POINTER_H 1106c3fb27SDimitry Andric 1206c3fb27SDimitry Andric #include "Function.h" 1306c3fb27SDimitry Andric #include "Primitives.h" 1406c3fb27SDimitry Andric #include "clang/AST/APValue.h" 1506c3fb27SDimitry Andric 1606c3fb27SDimitry Andric namespace clang { 1706c3fb27SDimitry Andric class ASTContext; 1806c3fb27SDimitry Andric namespace interp { 1906c3fb27SDimitry Andric 2006c3fb27SDimitry Andric class FunctionPointer final { 2106c3fb27SDimitry Andric private: 2206c3fb27SDimitry Andric const Function *Func; 23*0fca6ea1SDimitry Andric bool Valid; 2406c3fb27SDimitry Andric 2506c3fb27SDimitry Andric public: 26*0fca6ea1SDimitry Andric FunctionPointer(const Function *Func) : Func(Func), Valid(true) { 27*0fca6ea1SDimitry Andric assert(Func); 28*0fca6ea1SDimitry Andric } 29*0fca6ea1SDimitry Andric 30*0fca6ea1SDimitry Andric FunctionPointer(uintptr_t IntVal = 0, const Descriptor *Desc = nullptr) 31*0fca6ea1SDimitry Andric : Func(reinterpret_cast<const Function *>(IntVal)), Valid(false) {} 3206c3fb27SDimitry Andric 3306c3fb27SDimitry Andric const Function *getFunction() const { return Func; } 34*0fca6ea1SDimitry Andric bool isZero() const { return !Func; } 35*0fca6ea1SDimitry Andric bool isValid() const { return Valid; } 36*0fca6ea1SDimitry Andric bool isWeak() const { 37*0fca6ea1SDimitry Andric if (!Func || !Valid) 38*0fca6ea1SDimitry Andric return false; 3906c3fb27SDimitry Andric 40*0fca6ea1SDimitry Andric return Func->getDecl()->isWeak(); 41*0fca6ea1SDimitry Andric } 42*0fca6ea1SDimitry Andric 43*0fca6ea1SDimitry Andric APValue toAPValue(const ASTContext &) const { 4406c3fb27SDimitry Andric if (!Func) 4506c3fb27SDimitry Andric return APValue(static_cast<Expr *>(nullptr), CharUnits::Zero(), {}, 4606c3fb27SDimitry Andric /*OnePastTheEnd=*/false, /*IsNull=*/true); 4706c3fb27SDimitry Andric 48*0fca6ea1SDimitry Andric if (!Valid) 49*0fca6ea1SDimitry Andric return APValue(static_cast<Expr *>(nullptr), 50*0fca6ea1SDimitry Andric CharUnits::fromQuantity(getIntegerRepresentation()), {}, 51*0fca6ea1SDimitry Andric /*OnePastTheEnd=*/false, /*IsNull=*/false); 52*0fca6ea1SDimitry Andric 5306c3fb27SDimitry Andric return APValue(Func->getDecl(), CharUnits::Zero(), {}, 5406c3fb27SDimitry Andric /*OnePastTheEnd=*/false, /*IsNull=*/false); 5506c3fb27SDimitry Andric } 5606c3fb27SDimitry Andric 5706c3fb27SDimitry Andric void print(llvm::raw_ostream &OS) const { 5806c3fb27SDimitry Andric OS << "FnPtr("; 59*0fca6ea1SDimitry Andric if (Func && Valid) 6006c3fb27SDimitry Andric OS << Func->getName(); 61*0fca6ea1SDimitry Andric else if (Func) 62*0fca6ea1SDimitry Andric OS << reinterpret_cast<uintptr_t>(Func); 6306c3fb27SDimitry Andric else 6406c3fb27SDimitry Andric OS << "nullptr"; 6506c3fb27SDimitry Andric OS << ")"; 6606c3fb27SDimitry Andric } 6706c3fb27SDimitry Andric 6806c3fb27SDimitry Andric std::string toDiagnosticString(const ASTContext &Ctx) const { 6906c3fb27SDimitry Andric if (!Func) 7006c3fb27SDimitry Andric return "nullptr"; 7106c3fb27SDimitry Andric 72*0fca6ea1SDimitry Andric return toAPValue(Ctx).getAsString(Ctx, Func->getDecl()->getType()); 73*0fca6ea1SDimitry Andric } 74*0fca6ea1SDimitry Andric 75*0fca6ea1SDimitry Andric uint64_t getIntegerRepresentation() const { 76*0fca6ea1SDimitry Andric return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Func)); 7706c3fb27SDimitry Andric } 7806c3fb27SDimitry Andric 7906c3fb27SDimitry Andric ComparisonCategoryResult compare(const FunctionPointer &RHS) const { 8006c3fb27SDimitry Andric if (Func == RHS.Func) 8106c3fb27SDimitry Andric return ComparisonCategoryResult::Equal; 8206c3fb27SDimitry Andric return ComparisonCategoryResult::Unordered; 8306c3fb27SDimitry Andric } 8406c3fb27SDimitry Andric }; 8506c3fb27SDimitry Andric 8606c3fb27SDimitry Andric inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, 8706c3fb27SDimitry Andric FunctionPointer FP) { 8806c3fb27SDimitry Andric FP.print(OS); 8906c3fb27SDimitry Andric return OS; 9006c3fb27SDimitry Andric } 9106c3fb27SDimitry Andric 9206c3fb27SDimitry Andric } // namespace interp 9306c3fb27SDimitry Andric } // namespace clang 9406c3fb27SDimitry Andric 9506c3fb27SDimitry Andric #endif 96