llvm/clang/lib/CodeGen/CGDecl.cpp

//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This contains code to emit Decl nodes as LLVM code.
//
//===----------------------------------------------------------------------===//

#include "CGBlocks.h"
#include "CGCXXABI.h"
#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGOpenCLRuntime.h"
#include "CGOpenMPRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "ConstantEmitter.h"
#include "EHScopeStack.h"
#include "PatternInit.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Sema/Sema.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Type.h"
#include <optional>

usingnamespaceclang;
usingnamespaceCodeGen;

static_assert;

void CodeGenFunction::EmitDecl(const Decl &D) {}

/// EmitVarDecl - This method handles emission of any variable declaration
/// inside a function, including static vars etc.
void CodeGenFunction::EmitVarDecl(const VarDecl &D) {}

static std::string getStaticDeclName(CodeGenModule &CGM, const VarDecl &D) {}

llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl(
    const VarDecl &D, llvm::GlobalValue::LinkageTypes Linkage) {}

/// AddInitializerToStaticVarDecl - Add the initializer for 'D' to the
/// global variable that has already been created for it.  If the initializer
/// has a different type than GV does, this may free GV and return a different
/// one.  Otherwise it just returns GV.
llvm::GlobalVariable *
CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
                                               llvm::GlobalVariable *GV) {}

void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
                                      llvm::GlobalValue::LinkageTypes Linkage) {}

namespace {
  struct DestroyObject final : EHScopeStack::Cleanup {};

  template <class Derived>
  struct DestroyNRVOVariable : EHScopeStack::Cleanup {};

  struct DestroyNRVOVariableCXX final
      : DestroyNRVOVariable<DestroyNRVOVariableCXX> {};

  struct DestroyNRVOVariableC final
      : DestroyNRVOVariable<DestroyNRVOVariableC> {};

  struct CallStackRestore final : EHScopeStack::Cleanup {};

  struct KmpcAllocFree final : EHScopeStack::Cleanup {};

  struct ExtendGCLifetime final : EHScopeStack::Cleanup {};

  struct CallCleanupFunction final : EHScopeStack::Cleanup {};
} // end anonymous namespace

/// EmitAutoVarWithLifetime - Does the setup required for an automatic
/// variable with lifetime.
static void EmitAutoVarWithLifetime(CodeGenFunction &CGF, const VarDecl &var,
                                    Address addr,
                                    Qualifiers::ObjCLifetime lifetime) {}

static bool isAccessedBy(const VarDecl &var, const Stmt *s) {}

static bool isAccessedBy(const ValueDecl *decl, const Expr *e) {}

static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF,
                                   const LValue &destLV, const Expr *init) {}

static void drillIntoBlockVariable(CodeGenFunction &CGF,
                                   LValue &lvalue,
                                   const VarDecl *var) {}

void CodeGenFunction::EmitNullabilityCheck(LValue LHS, llvm::Value *RHS,
                                           SourceLocation Loc) {}

void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
                                     LValue lvalue, bool capturedByInit) {}

/// Decide whether we can emit the non-zero parts of the specified initializer
/// with equal or fewer than NumStores scalar stores.
static bool canEmitInitWithFewStoresAfterBZero(llvm::Constant *Init,
                                               unsigned &NumStores) {}

/// For inits that canEmitInitWithFewStoresAfterBZero returned true for, emit
/// the scalar stores that would be required.
static void emitStoresForInitAfterBZero(CodeGenModule &CGM,
                                        llvm::Constant *Init, Address Loc,
                                        bool isVolatile, CGBuilderTy &Builder,
                                        bool IsAutoInit) {}

/// Decide whether we should use bzero plus some stores to initialize a local
/// variable instead of using a memcpy from a constant global.  It is beneficial
/// to use bzero if the global is all zeros, or mostly zeros and large.
static bool shouldUseBZeroPlusStoresToInitialize(llvm::Constant *Init,
                                                 uint64_t GlobalSize) {}

/// Decide whether we should use memset to initialize a local variable instead
/// of using a memcpy from a constant global. Assumes we've already decided to
/// not user bzero.
/// FIXME We could be more clever, as we are for bzero above, and generate
///       memset followed by stores. It's unclear that's worth the effort.
static llvm::Value *shouldUseMemSetToInitialize(llvm::Constant *Init,
                                                uint64_t GlobalSize,
                                                const llvm::DataLayout &DL) {}

/// Decide whether we want to split a constant structure or array store into a
/// sequence of its fields' stores. This may cost us code size and compilation
/// speed, but plays better with store optimizations.
static bool shouldSplitConstantStore(CodeGenModule &CGM,
                                     uint64_t GlobalByteSize) {}

enum class IsPattern {};

/// Generate a constant filled with either a pattern or zeroes.
static llvm::Constant *patternOrZeroFor(CodeGenModule &CGM, IsPattern isPattern,
                                        llvm::Type *Ty) {}

static llvm::Constant *constWithPadding(CodeGenModule &CGM, IsPattern isPattern,
                                        llvm::Constant *constant);

/// Helper function for constWithPadding() to deal with padding in structures.
static llvm::Constant *constStructWithPadding(CodeGenModule &CGM,
                                              IsPattern isPattern,
                                              llvm::StructType *STy,
                                              llvm::Constant *constant) {}

/// Replace all padding bytes in a given constant with either a pattern byte or
/// 0x00.
static llvm::Constant *constWithPadding(CodeGenModule &CGM, IsPattern isPattern,
                                        llvm::Constant *constant) {}

Address CodeGenModule::createUnnamedGlobalFrom(const VarDecl &D,
                                               llvm::Constant *Constant,
                                               CharUnits Align) {}

static Address createUnnamedGlobalForMemcpyFrom(CodeGenModule &CGM,
                                                const VarDecl &D,
                                                CGBuilderTy &Builder,
                                                llvm::Constant *Constant,
                                                CharUnits Align) {}

static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
                                  Address Loc, bool isVolatile,
                                  CGBuilderTy &Builder,
                                  llvm::Constant *constant, bool IsAutoInit) {}

static void emitStoresForZeroInit(CodeGenModule &CGM, const VarDecl &D,
                                  Address Loc, bool isVolatile,
                                  CGBuilderTy &Builder) {}

static void emitStoresForPatternInit(CodeGenModule &CGM, const VarDecl &D,
                                     Address Loc, bool isVolatile,
                                     CGBuilderTy &Builder) {}

static bool containsUndef(llvm::Constant *constant) {}

static llvm::Constant *replaceUndef(CodeGenModule &CGM, IsPattern isPattern,
                                    llvm::Constant *constant) {}

/// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a
/// variable declaration with auto, register, or no storage class specifier.
/// These turn into simple stack objects, or GlobalValues depending on target.
void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {}

/// Emit a lifetime.begin marker if some criteria are satisfied.
/// \return a pointer to the temporary size Value if a marker was emitted, null
/// otherwise
llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size,
                                                llvm::Value *Addr) {}

void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {}

void CodeGenFunction::EmitAndRegisterVariableArrayDimensions(
    CGDebugInfo *DI, const VarDecl &D, bool EmitDebugInfo) {}

/// EmitAutoVarAlloca - Emit the alloca and debug information for a
/// local variable.  Does not emit initialization or destruction.
CodeGenFunction::AutoVarEmission
CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {}

static bool isCapturedBy(const VarDecl &, const Expr *);

/// Determines whether the given __block variable is potentially
/// captured by the given statement.
static bool isCapturedBy(const VarDecl &Var, const Stmt *S) {}

/// Determines whether the given __block variable is potentially
/// captured by the given expression.
static bool isCapturedBy(const VarDecl &Var, const Expr *E) {}

/// Determine whether the given initializer is trivial in the sense
/// that it requires no code to be generated.
bool CodeGenFunction::isTrivialInitializer(const Expr *Init) {}

void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type,
                                                      const VarDecl &D,
                                                      Address Loc) {}

void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {}

/// Emit an expression as an initializer for an object (variable, field, etc.)
/// at the given location.  The expression is not necessarily the normal
/// initializer for the object, and the address is not necessarily
/// its normal location.
///
/// \param init the initializing expression
/// \param D the object to act as if we're initializing
/// \param lvalue the lvalue to initialize
/// \param capturedByInit true if \p D is a __block variable
///   whose address is potentially changed by the initializer
void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D,
                                     LValue lvalue, bool capturedByInit) {}

/// Enter a destroy cleanup for the given local variable.
void CodeGenFunction::emitAutoVarTypeCleanup(
                            const CodeGenFunction::AutoVarEmission &emission,
                            QualType::DestructionKind dtorKind) {}

void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {}

CodeGenFunction::Destroyer *
CodeGenFunction::getDestroyer(QualType::DestructionKind kind) {}

/// pushEHDestroy - Push the standard destructor for the given type as
/// an EH-only cleanup.
void CodeGenFunction::pushEHDestroy(QualType::DestructionKind dtorKind,
                                    Address addr, QualType type) {}

/// pushDestroy - Push the standard destructor for the given type as
/// at least a normal cleanup.
void CodeGenFunction::pushDestroy(QualType::DestructionKind dtorKind,
                                  Address addr, QualType type) {}

void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, Address addr,
                                  QualType type, Destroyer *destroyer,
                                  bool useEHCleanupForArray) {}

// Pushes a destroy and defers its deactivation until its
// CleanupDeactivationScope is exited.
void CodeGenFunction::pushDestroyAndDeferDeactivation(
    QualType::DestructionKind dtorKind, Address addr, QualType type) {}

void CodeGenFunction::pushDestroyAndDeferDeactivation(
    CleanupKind cleanupKind, Address addr, QualType type, Destroyer *destroyer,
    bool useEHCleanupForArray) {}

void CodeGenFunction::pushStackRestore(CleanupKind Kind, Address SPMem) {}

void CodeGenFunction::pushKmpcAllocFree(
    CleanupKind Kind, std::pair<llvm::Value *, llvm::Value *> AddrSizePair) {}

void CodeGenFunction::pushLifetimeExtendedDestroy(CleanupKind cleanupKind,
                                                  Address addr, QualType type,
                                                  Destroyer *destroyer,
                                                  bool useEHCleanupForArray) {}

/// emitDestroy - Immediately perform the destruction of the given
/// object.
///
/// \param addr - the address of the object; a type*
/// \param type - the type of the object; if an array type, all
///   objects are destroyed in reverse order
/// \param destroyer - the function to call to destroy individual
///   elements
/// \param useEHCleanupForArray - whether an EH cleanup should be
///   used when destroying array elements, in case one of the
///   destructions throws an exception
void CodeGenFunction::emitDestroy(Address addr, QualType type,
                                  Destroyer *destroyer,
                                  bool useEHCleanupForArray) {}

/// emitArrayDestroy - Destroys all the elements of the given array,
/// beginning from last to first.  The array cannot be zero-length.
///
/// \param begin - a type* denoting the first element of the array
/// \param end - a type* denoting one past the end of the array
/// \param elementType - the element type of the array
/// \param destroyer - the function to call to destroy elements
/// \param useEHCleanup - whether to push an EH cleanup to destroy
///   the remaining elements in case the destruction of a single
///   element throws
void CodeGenFunction::emitArrayDestroy(llvm::Value *begin,
                                       llvm::Value *end,
                                       QualType elementType,
                                       CharUnits elementAlign,
                                       Destroyer *destroyer,
                                       bool checkZeroLength,
                                       bool useEHCleanup) {}

/// Perform partial array destruction as if in an EH cleanup.  Unlike
/// emitArrayDestroy, the element type here may still be an array type.
static void emitPartialArrayDestroy(CodeGenFunction &CGF,
                                    llvm::Value *begin, llvm::Value *end,
                                    QualType type, CharUnits elementAlign,
                                    CodeGenFunction::Destroyer *destroyer) {}

namespace {
  /// RegularPartialArrayDestroy - a cleanup which performs a partial
  /// array destroy where the end pointer is regularly determined and
  /// does not need to be loaded from a local.
  class RegularPartialArrayDestroy final : public EHScopeStack::Cleanup {};

  /// IrregularPartialArrayDestroy - a cleanup which performs a
  /// partial array destroy where the end pointer is irregularly
  /// determined and must be loaded from a local.
  class IrregularPartialArrayDestroy final : public EHScopeStack::Cleanup {};
} // end anonymous namespace

/// pushIrregularPartialArrayCleanup - Push a NormalAndEHCleanup to
/// destroy already-constructed elements of the given array.  The cleanup may be
/// popped with DeactivateCleanupBlock or PopCleanupBlock.
///
/// \param elementType - the immediate element type of the array;
///   possibly still an array type
void CodeGenFunction::pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin,
                                                       Address arrayEndPointer,
                                                       QualType elementType,
                                                       CharUnits elementAlign,
                                                       Destroyer *destroyer) {}

/// pushRegularPartialArrayCleanup - Push an EH cleanup to destroy
/// already-constructed elements of the given array.  The cleanup
/// may be popped with DeactivateCleanupBlock or PopCleanupBlock.
///
/// \param elementType - the immediate element type of the array;
///   possibly still an array type
void CodeGenFunction::pushRegularPartialArrayCleanup(llvm::Value *arrayBegin,
                                                     llvm::Value *arrayEnd,
                                                     QualType elementType,
                                                     CharUnits elementAlign,
                                                     Destroyer *destroyer) {}

/// Lazily declare the @llvm.lifetime.start intrinsic.
llvm::Function *CodeGenModule::getLLVMLifetimeStartFn() {}

/// Lazily declare the @llvm.lifetime.end intrinsic.
llvm::Function *CodeGenModule::getLLVMLifetimeEndFn() {}

namespace {
  /// A cleanup to perform a release of an object at the end of a
  /// function.  This is used to balance out the incoming +1 of a
  /// ns_consumed argument when we can't reasonably do that just by
  /// not doing the initial retain for a __block argument.
  struct ConsumeARCParameter final : EHScopeStack::Cleanup {};
} // end anonymous namespace

/// Emit an alloca (or GlobalValue depending on target)
/// for the specified parameter and set up LocalDeclMap.
void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
                                   unsigned ArgNo) {}

void CodeGenModule::EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D,
                                            CodeGenFunction *CGF) {}

void CodeGenModule::EmitOMPDeclareMapper(const OMPDeclareMapperDecl *D,
                                         CodeGenFunction *CGF) {}

void CodeGenModule::EmitOMPRequiresDecl(const OMPRequiresDecl *D) {}

void CodeGenModule::EmitOMPAllocateDecl(const OMPAllocateDecl *D) {}

std::optional<CharUnits>
CodeGenModule::getOMPAllocateAlignment(const VarDecl *VD) {}