brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.7 KiB · 55b3d97 Raw
268 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// These classes wrap the information about a call or function10// definition used to handle ABI compliancy.11//12//===----------------------------------------------------------------------===//13 14#ifndef CLANG_LIB_CODEGEN_CIRGENCALL_H15#define CLANG_LIB_CODEGEN_CIRGENCALL_H16 17#include "CIRGenValue.h"18#include "mlir/IR/Operation.h"19#include "clang/AST/GlobalDecl.h"20#include "llvm/ADT/SmallVector.h"21 22namespace clang::CIRGen {23 24class CIRGenFunction;25 26/// Abstract information about a function or function prototype.27class CIRGenCalleeInfo {28  const clang::FunctionProtoType *calleeProtoTy;29  clang::GlobalDecl calleeDecl;30 31public:32  explicit CIRGenCalleeInfo() : calleeProtoTy(nullptr), calleeDecl() {}33  CIRGenCalleeInfo(const clang::FunctionProtoType *calleeProtoTy,34                   clang::GlobalDecl calleeDecl)35      : calleeProtoTy(calleeProtoTy), calleeDecl(calleeDecl) {}36  CIRGenCalleeInfo(clang::GlobalDecl calleeDecl)37      : calleeProtoTy(nullptr), calleeDecl(calleeDecl) {}38 39  const clang::FunctionProtoType *getCalleeFunctionProtoType() const {40    return calleeProtoTy;41  }42  clang::GlobalDecl getCalleeDecl() const { return calleeDecl; }43};44 45class CIRGenCallee {46  enum class SpecialKind : uintptr_t {47    Invalid,48    Builtin,49    PseudoDestructor,50    Virtual,51 52    Last = Virtual53  };54 55  struct BuiltinInfoStorage {56    const clang::FunctionDecl *decl;57    unsigned id;58  };59  struct PseudoDestructorInfoStorage {60    const clang::CXXPseudoDestructorExpr *expr;61  };62  struct VirtualInfoStorage {63    const clang::CallExpr *ce;64    clang::GlobalDecl md;65    Address addr;66    cir::FuncType fTy;67  };68 69  SpecialKind kindOrFunctionPtr;70 71  union {72    CIRGenCalleeInfo abstractInfo;73    BuiltinInfoStorage builtinInfo;74    PseudoDestructorInfoStorage pseudoDestructorInfo;75    VirtualInfoStorage virtualInfo;76  };77 78  explicit CIRGenCallee(SpecialKind kind) : kindOrFunctionPtr(kind) {}79 80public:81  CIRGenCallee() : kindOrFunctionPtr(SpecialKind::Invalid) {}82 83  CIRGenCallee(const CIRGenCalleeInfo &abstractInfo, mlir::Operation *funcPtr)84      : kindOrFunctionPtr(SpecialKind(reinterpret_cast<uintptr_t>(funcPtr))),85        abstractInfo(abstractInfo) {86    assert(funcPtr && "configuring callee without function pointer");87  }88 89  static CIRGenCallee90  forDirect(mlir::Operation *funcPtr,91            const CIRGenCalleeInfo &abstractInfo = CIRGenCalleeInfo()) {92    return CIRGenCallee(abstractInfo, funcPtr);93  }94 95  bool isBuiltin() const { return kindOrFunctionPtr == SpecialKind::Builtin; }96 97  const clang::FunctionDecl *getBuiltinDecl() const {98    assert(isBuiltin());99    return builtinInfo.decl;100  }101  unsigned getBuiltinID() const {102    assert(isBuiltin());103    return builtinInfo.id;104  }105 106  static CIRGenCallee forBuiltin(unsigned builtinID,107                                 const clang::FunctionDecl *builtinDecl) {108    CIRGenCallee result(SpecialKind::Builtin);109    result.builtinInfo.decl = builtinDecl;110    result.builtinInfo.id = builtinID;111    return result;112  }113 114  static CIRGenCallee115  forPseudoDestructor(const clang::CXXPseudoDestructorExpr *expr) {116    CIRGenCallee result(SpecialKind::PseudoDestructor);117    result.pseudoDestructorInfo.expr = expr;118    return result;119  }120 121  bool isPseudoDestructor() const {122    return kindOrFunctionPtr == SpecialKind::PseudoDestructor;123  }124 125  const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const {126    assert(isPseudoDestructor());127    return pseudoDestructorInfo.expr;128  }129 130  bool isOrdinary() const {131    return uintptr_t(kindOrFunctionPtr) > uintptr_t(SpecialKind::Last);132  }133 134  /// If this is a delayed callee computation of some sort, prepare a concrete135  /// callee136  CIRGenCallee prepareConcreteCallee(CIRGenFunction &cgf) const;137 138  CIRGenCalleeInfo getAbstractInfo() const {139    if (isVirtual())140      return virtualInfo.md;141    assert(isOrdinary());142    return abstractInfo;143  }144 145  mlir::Operation *getFunctionPointer() const {146    assert(isOrdinary());147    return reinterpret_cast<mlir::Operation *>(kindOrFunctionPtr);148  }149 150  bool isVirtual() const { return kindOrFunctionPtr == SpecialKind::Virtual; }151 152  static CIRGenCallee forVirtual(const clang::CallExpr *ce,153                                 clang::GlobalDecl md, Address addr,154                                 cir::FuncType fTy) {155    CIRGenCallee result(SpecialKind::Virtual);156    result.virtualInfo.ce = ce;157    result.virtualInfo.md = md;158    result.virtualInfo.addr = addr;159    result.virtualInfo.fTy = fTy;160    return result;161  }162 163  const clang::CallExpr *getVirtualCallExpr() const {164    assert(isVirtual());165    return virtualInfo.ce;166  }167 168  clang::GlobalDecl getVirtualMethodDecl() const {169    assert(isVirtual());170    return virtualInfo.md;171  }172 173  Address getThisAddress() const {174    assert(isVirtual());175    return virtualInfo.addr;176  }177 178  cir::FuncType getVirtualFunctionType() const {179    assert(isVirtual());180    return virtualInfo.fTy;181  }182 183  void setFunctionPointer(mlir::Operation *functionPtr) {184    assert(isOrdinary());185    kindOrFunctionPtr = SpecialKind(reinterpret_cast<uintptr_t>(functionPtr));186  }187};188 189/// Type for representing both the decl and type of parameters to a function.190/// The decl must be either a ParmVarDecl or ImplicitParamDecl.191class FunctionArgList : public llvm::SmallVector<const clang::VarDecl *, 16> {};192 193struct CallArg {194private:195  union {196    RValue rv;197    LValue lv; // This argument is semantically a load from this l-value198  };199  bool hasLV;200 201  /// A data-flow flag to make sure getRValue and/or copyInto are not202  /// called twice for duplicated IR emission.203  [[maybe_unused]] mutable bool isUsed;204 205public:206  clang::QualType ty;207 208  CallArg(RValue rv, clang::QualType ty)209      : rv(rv), hasLV(false), isUsed(false), ty(ty) {}210 211  CallArg(LValue lv, clang::QualType ty)212      : lv(lv), hasLV(true), isUsed(false), ty(ty) {}213 214  bool hasLValue() const { return hasLV; }215 216  LValue getKnownLValue() const {217    assert(hasLV && !isUsed);218    return lv;219  }220 221  RValue getKnownRValue() const {222    assert(!hasLV && !isUsed);223    return rv;224  }225 226  bool isAggregate() const { return hasLV || rv.isAggregate(); }227 228  void copyInto(CIRGenFunction &cgf, Address addr, mlir::Location loc) const;229};230 231class CallArgList : public llvm::SmallVector<CallArg, 8> {232public:233  void add(RValue rvalue, clang::QualType type) { emplace_back(rvalue, type); }234 235  void addUncopiedAggregate(LValue lvalue, clang::QualType type) {236    emplace_back(lvalue, type);237  }238 239  /// Add all the arguments from another CallArgList to this one. After doing240  /// this, the old CallArgList retains its list of arguments, but must not241  /// be used to emit a call.242  void addFrom(const CallArgList &other) {243    insert(end(), other.begin(), other.end());244    // Classic codegen has handling for these here. We may not need it here for245    // CIR, but if not we should implement equivalent handling in lowering.246    assert(!cir::MissingFeatures::writebacks());247    assert(!cir::MissingFeatures::cleanupsToDeactivate());248    assert(!cir::MissingFeatures::stackBase());249  }250};251 252/// Contains the address where the return value of a function can be stored, and253/// whether the address is volatile or not.254class ReturnValueSlot {255  Address addr = Address::invalid();256 257public:258  ReturnValueSlot() = default;259  ReturnValueSlot(Address addr) : addr(addr) {}260 261  bool isNull() const { return !addr.isValid(); }262  Address getValue() const { return addr; }263};264 265} // namespace clang::CIRGen266 267#endif // CLANG_LIB_CODEGEN_CIRGENCALL_H268