brintos

brintos / llvm-project-archived public Read only

0
0
Text · 37.2 KiB · e0e4f67 Raw
997 lines · cpp
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// This contains code to emit Decl nodes as CIR code.10//11//===----------------------------------------------------------------------===//12 13#include "CIRGenConstantEmitter.h"14#include "CIRGenFunction.h"15#include "mlir/IR/Location.h"16#include "clang/AST/Attr.h"17#include "clang/AST/Decl.h"18#include "clang/AST/DeclOpenACC.h"19#include "clang/AST/Expr.h"20#include "clang/AST/ExprCXX.h"21#include "clang/CIR/MissingFeatures.h"22 23using namespace clang;24using namespace clang::CIRGen;25 26CIRGenFunction::AutoVarEmission27CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,28                                  mlir::OpBuilder::InsertPoint ip) {29  QualType ty = d.getType();30  if (ty.getAddressSpace() != LangAS::Default)31    cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: address space");32 33  mlir::Location loc = getLoc(d.getSourceRange());34  bool nrvo =35      getContext().getLangOpts().ElideConstructors && d.isNRVOVariable();36 37  CIRGenFunction::AutoVarEmission emission(d);38  emission.isEscapingByRef = d.isEscapingByref();39  if (emission.isEscapingByRef)40    cgm.errorNYI(d.getSourceRange(),41                 "emitAutoVarDecl: decl escaping by reference");42 43  CharUnits alignment = getContext().getDeclAlign(&d);44 45  // If the type is variably-modified, emit all the VLA sizes for it.46  if (ty->isVariablyModifiedType())47    emitVariablyModifiedType(ty);48 49  assert(!cir::MissingFeatures::openMP());50 51  Address address = Address::invalid();52  if (ty->isConstantSizeType()) {53    // If this value is an array, struct, or vector with a statically54    // determinable constant initializer, there are optimizations we can do.55    //56    // TODO: We should constant-evaluate the initializer of any variable,57    // as long as it is initialized by a constant expression. Currently,58    // isConstantInitializer produces wrong answers for structs with59    // reference or bitfield members, and a few other cases, and checking60    // for POD-ness protects us from some of these.61    if (d.getInit() &&62        (ty->isArrayType() || ty->isRecordType() || ty->isVectorType()) &&63        (d.isConstexpr() ||64         ((ty.isPODType(getContext()) ||65           getContext().getBaseElementType(ty)->isObjCObjectPointerType()) &&66          d.getInit()->isConstantInitializer(getContext(), false)))) {67 68      // If the variable's a const type, and it's neither an NRVO69      // candidate nor a __block variable and has no mutable members,70      // emit it as a global instead.71      // Exception is if a variable is located in non-constant address space72      // in OpenCL.73      // TODO(cir): perhaps we don't need this at all at CIR since this can74      // be done as part of lowering down to LLVM.75      bool needsDtor =76          d.needsDestruction(getContext()) == QualType::DK_cxx_destructor;77      if ((!getContext().getLangOpts().OpenCL ||78           ty.getAddressSpace() == LangAS::opencl_constant) &&79          (cgm.getCodeGenOpts().MergeAllConstants && !nrvo &&80           !d.isEscapingByref() &&81           ty.isConstantStorage(getContext(), true, !needsDtor))) {82        cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: type constant");83      }84      // Otherwise, tell the initialization code that we're in this case.85      emission.isConstantAggregate = true;86    }87 88    // A normal fixed sized variable becomes an alloca in the entry block,89    // unless:90    // - it's an NRVO variable.91    // - we are compiling OpenMP and it's an OpenMP local variable.92    if (nrvo) {93      // The named return value optimization: allocate this variable in the94      // return slot, so that we can elide the copy when returning this95      // variable (C++0x [class.copy]p34).96      address = returnValue;97 98      if (const RecordDecl *rd = ty->getAsRecordDecl()) {99        if (const auto *cxxrd = dyn_cast<CXXRecordDecl>(rd);100            (cxxrd && !cxxrd->hasTrivialDestructor()) ||101            rd->isNonTrivialToPrimitiveDestroy())102          cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: set NRVO flag");103      }104    } else {105      // A normal fixed sized variable becomes an alloca in the entry block,106      mlir::Type allocaTy = convertTypeForMem(ty);107      // Create the temp alloca and declare variable using it.108      address = createTempAlloca(allocaTy, alignment, loc, d.getName(),109                                 /*arraySize=*/nullptr, /*alloca=*/nullptr, ip);110      declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()),111              alignment);112    }113  } else {114    // Non-constant size type115    assert(!cir::MissingFeatures::openMP());116    if (!didCallStackSave) {117      // Save the stack.118      cir::PointerType defaultTy = allocaInt8PtrTy;119      CharUnits align = CharUnits::fromQuantity(120          cgm.getDataLayout().getAlignment(defaultTy, false));121      Address stack = createTempAlloca(defaultTy, align, loc, "saved_stack");122 123      mlir::Value v = builder.createStackSave(loc, defaultTy);124      assert(v.getType() == allocaInt8PtrTy);125      builder.createStore(loc, v, stack);126 127      didCallStackSave = true;128 129      // Push a cleanup block and restore the stack there.130      // FIXME: in general circumstances, this should be an EH cleanup.131      pushStackRestore(NormalCleanup, stack);132    }133 134    VlaSizePair vlaSize = getVLASize(ty);135    mlir::Type memTy = convertTypeForMem(vlaSize.type);136 137    // Allocate memory for the array.138    address =139        createTempAlloca(memTy, alignment, loc, d.getName(), vlaSize.numElts,140                         /*alloca=*/nullptr, builder.saveInsertionPoint());141 142    // If we have debug info enabled, properly describe the VLA dimensions for143    // this type by registering the vla size expression for each of the144    // dimensions.145    assert(!cir::MissingFeatures::generateDebugInfo());146  }147 148  emission.addr = address;149  setAddrOfLocalVar(&d, address);150 151  return emission;152}153 154/// Determine whether the given initializer is trivial in the sense155/// that it requires no code to be generated.156bool CIRGenFunction::isTrivialInitializer(const Expr *init) {157  if (!init)158    return true;159 160  if (const CXXConstructExpr *construct = dyn_cast<CXXConstructExpr>(init))161    if (CXXConstructorDecl *constructor = construct->getConstructor())162      if (constructor->isTrivial() && constructor->isDefaultConstructor() &&163          !construct->requiresZeroInitialization())164        return true;165 166  return false;167}168 169static void emitStoresForConstant(CIRGenModule &cgm, const VarDecl &d,170                                  Address addr, bool isVolatile,171                                  CIRGenBuilderTy &builder,172                                  mlir::TypedAttr constant) {173  mlir::Type ty = constant.getType();174  cir::CIRDataLayout layout{cgm.getModule()};175  uint64_t constantSize = layout.getTypeAllocSize(ty);176  if (!constantSize)177    return;178  assert(!cir::MissingFeatures::addAutoInitAnnotation());179  assert(!cir::MissingFeatures::vectorConstants());180  assert(!cir::MissingFeatures::shouldUseBZeroPlusStoresToInitialize());181  assert(!cir::MissingFeatures::shouldUseMemSetToInitialize());182  assert(!cir::MissingFeatures::shouldSplitConstantStore());183  assert(!cir::MissingFeatures::shouldCreateMemCpyFromGlobal());184  // In CIR we want to emit a store for the whole thing, later lowering185  // prepare to LLVM should unwrap this into the best policy (see asserts186  // above).187  //188  // FIXME(cir): This is closer to memcpy behavior but less optimal, instead of189  // copy from a global, we just create a cir.const out of it.190 191  if (addr.getElementType() != ty)192    addr = addr.withElementType(builder, ty);193 194  // If the address is an alloca, set the init attribute.195  // The address is usually and alloca, but there is at least one case where196  // emitAutoVarInit is called from the OpenACC codegen with an address that197  // is not an alloca.198  auto allocaOp = addr.getDefiningOp<cir::AllocaOp>();199  if (allocaOp)200    allocaOp.setInitAttr(mlir::UnitAttr::get(&cgm.getMLIRContext()));201 202  // There are cases where OpenACC codegen calls emitAutoVarInit with a203  // temporary decl that doesn't have a source range set.204  mlir::Location loc = builder.getUnknownLoc();205  if (d.getSourceRange().isValid())206    loc = cgm.getLoc(d.getSourceRange());207  builder.createStore(loc, builder.getConstant(loc, constant), addr);208}209 210void CIRGenFunction::emitAutoVarInit(211    const CIRGenFunction::AutoVarEmission &emission) {212  assert(emission.variable && "emission was not valid!");213 214  // If this was emitted as a global constant, we're done.215  if (emission.wasEmittedAsGlobal())216    return;217 218  const VarDecl &d = *emission.variable;219 220  QualType type = d.getType();221 222  // If this local has an initializer, emit it now.223  const Expr *init = d.getInit();224 225  // Initialize the variable here if it doesn't have a initializer and it is a226  // C struct that is non-trivial to initialize or an array containing such a227  // struct.228  if (!init && type.isNonTrivialToPrimitiveDefaultInitialize() ==229                   QualType::PDIK_Struct) {230    cgm.errorNYI(d.getSourceRange(),231                 "emitAutoVarInit: non-trivial to default initialize");232    return;233  }234 235  const Address addr = emission.addr;236 237  // Check whether this is a byref variable that's potentially238  // captured and moved by its own initializer.  If so, we'll need to239  // emit the initializer first, then copy into the variable.240  assert(!cir::MissingFeatures::opAllocaCaptureByInit());241 242  // Note: constexpr already initializes everything correctly.243  LangOptions::TrivialAutoVarInitKind trivialAutoVarInit =244      (d.isConstexpr()245           ? LangOptions::TrivialAutoVarInitKind::Uninitialized246           : (d.getAttr<UninitializedAttr>()247                  ? LangOptions::TrivialAutoVarInitKind::Uninitialized248                  : getContext().getLangOpts().getTrivialAutoVarInit()));249 250  auto initializeWhatIsTechnicallyUninitialized = [&](Address addr) {251    if (trivialAutoVarInit ==252        LangOptions::TrivialAutoVarInitKind::Uninitialized)253      return;254 255    cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: trivial initialization");256  };257 258  if (isTrivialInitializer(init)) {259    initializeWhatIsTechnicallyUninitialized(addr);260    return;261  }262 263  mlir::Attribute constant;264  if (emission.isConstantAggregate ||265      d.mightBeUsableInConstantExpressions(getContext())) {266    // FIXME: Differently from LLVM we try not to emit / lower too much267    // here for CIR since we are interested in seeing the ctor in some268    // analysis later on. So CIR's implementation of ConstantEmitter will269    // frequently return an empty Attribute, to signal we want to codegen270    // some trivial ctor calls and whatnots.271    constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(d);272    if (constant && !mlir::isa<cir::ZeroAttr>(constant) &&273        (trivialAutoVarInit !=274         LangOptions::TrivialAutoVarInitKind::Uninitialized)) {275      cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: constant aggregate");276      return;277    }278  }279 280  // NOTE(cir): In case we have a constant initializer, we can just emit a281  // store. But, in CIR, we wish to retain any ctor calls, so if it is a282  // CXX temporary object creation, we ensure the ctor call is used deferring283  // its removal/optimization to the CIR lowering.284  if (!constant || isa<CXXTemporaryObjectExpr>(init)) {285    initializeWhatIsTechnicallyUninitialized(addr);286    LValue lv = makeAddrLValue(addr, type, AlignmentSource::Decl);287    emitExprAsInit(init, &d, lv);288 289    if (!emission.wasEmittedAsOffloadClause()) {290      // In case lv has uses it means we indeed initialized something291      // out of it while trying to build the expression, mark it as such.292      mlir::Value val = lv.getAddress().getPointer();293      assert(val && "Should have an address");294      auto allocaOp = val.getDefiningOp<cir::AllocaOp>();295      assert(allocaOp && "Address should come straight out of the alloca");296 297      if (!allocaOp.use_empty())298        allocaOp.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));299    }300 301    return;302  }303 304  // FIXME(cir): migrate most of this file to use mlir::TypedAttr directly.305  auto typedConstant = mlir::dyn_cast<mlir::TypedAttr>(constant);306  assert(typedConstant && "expected typed attribute");307  if (!emission.isConstantAggregate) {308    // For simple scalar/complex initialization, store the value directly.309    LValue lv = makeAddrLValue(addr, type);310    assert(init && "expected initializer");311    mlir::Location initLoc = getLoc(init->getSourceRange());312    // lv.setNonGC(true);313    return emitStoreThroughLValue(314        RValue::get(builder.getConstant(initLoc, typedConstant)), lv);315  }316 317  emitStoresForConstant(cgm, d, addr, type.isVolatileQualified(), builder,318                        typedConstant);319}320 321void CIRGenFunction::emitAutoVarCleanups(322    const CIRGenFunction::AutoVarEmission &emission) {323  const VarDecl &d = *emission.variable;324 325  // Check the type for a cleanup.326  if (QualType::DestructionKind dtorKind = d.needsDestruction(getContext()))327    emitAutoVarTypeCleanup(emission, dtorKind);328 329  assert(!cir::MissingFeatures::opAllocaPreciseLifetime());330 331  // Handle the cleanup attribute.332  if (d.hasAttr<CleanupAttr>())333    cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: CleanupAttr");334}335 336/// Emit code and set up symbol table for a variable declaration with auto,337/// register, or no storage class specifier. These turn into simple stack338/// objects, globals depending on target.339void CIRGenFunction::emitAutoVarDecl(const VarDecl &d) {340  CIRGenFunction::AutoVarEmission emission = emitAutoVarAlloca(d);341  emitAutoVarInit(emission);342  emitAutoVarCleanups(emission);343}344 345void CIRGenFunction::emitVarDecl(const VarDecl &d) {346  // If the declaration has external storage, don't emit it now, allow it to be347  // emitted lazily on its first use.348  if (d.hasExternalStorage())349    return;350 351  if (d.getStorageDuration() != SD_Automatic) {352    // Static sampler variables translated to function calls.353    if (d.getType()->isSamplerT()) {354      // Nothing needs to be done here, but let's flag it as an error until we355      // have a test. It requires OpenCL support.356      cgm.errorNYI(d.getSourceRange(), "emitVarDecl static sampler type");357      return;358    }359 360    cir::GlobalLinkageKind linkage =361        cgm.getCIRLinkageVarDefinition(&d, /*IsConstant=*/false);362 363    // FIXME: We need to force the emission/use of a guard variable for364    // some variables even if we can constant-evaluate them because365    // we can't guarantee every translation unit will constant-evaluate them.366 367    return emitStaticVarDecl(d, linkage);368  }369 370  if (d.getType().getAddressSpace() == LangAS::opencl_local)371    cgm.errorNYI(d.getSourceRange(), "emitVarDecl openCL address space");372 373  assert(d.hasLocalStorage());374 375  CIRGenFunction::VarDeclContext varDeclCtx{*this, &d};376  return emitAutoVarDecl(d);377}378 379static std::string getStaticDeclName(CIRGenModule &cgm, const VarDecl &d) {380  if (cgm.getLangOpts().CPlusPlus)381    return cgm.getMangledName(&d).str();382 383  // If this isn't C++, we don't need a mangled name, just a pretty one.384  assert(!d.isExternallyVisible() && "name shouldn't matter");385  std::string contextName;386  const DeclContext *dc = d.getDeclContext();387  if (auto *cd = dyn_cast<CapturedDecl>(dc))388    dc = cast<DeclContext>(cd->getNonClosureContext());389  if (const auto *fd = dyn_cast<FunctionDecl>(dc))390    contextName = std::string(cgm.getMangledName(fd));391  else if (isa<BlockDecl>(dc))392    cgm.errorNYI(d.getSourceRange(), "block decl context for static var");393  else if (isa<ObjCMethodDecl>(dc))394    cgm.errorNYI(d.getSourceRange(), "ObjC decl context for static var");395  else396    cgm.errorNYI(d.getSourceRange(), "Unknown context for static var decl");397 398  contextName += "." + d.getNameAsString();399  return contextName;400}401 402// TODO(cir): LLVM uses a Constant base class. Maybe CIR could leverage an403// interface for all constants?404cir::GlobalOp405CIRGenModule::getOrCreateStaticVarDecl(const VarDecl &d,406                                       cir::GlobalLinkageKind linkage) {407  // In general, we don't always emit static var decls once before we reference408  // them. It is possible to reference them before emitting the function that409  // contains them, and it is possible to emit the containing function multiple410  // times.411  if (cir::GlobalOp existingGV = getStaticLocalDeclAddress(&d))412    return existingGV;413 414  QualType ty = d.getType();415  assert(ty->isConstantSizeType() && "VLAs can't be static");416 417  // Use the label if the variable is renamed with the asm-label extension.418  if (d.hasAttr<AsmLabelAttr>())419    errorNYI(d.getSourceRange(), "getOrCreateStaticVarDecl: asm label");420 421  std::string name = getStaticDeclName(*this, d);422 423  mlir::Type lty = getTypes().convertTypeForMem(ty);424  assert(!cir::MissingFeatures::addressSpace());425 426  if (d.hasAttr<LoaderUninitializedAttr>() || d.hasAttr<CUDASharedAttr>())427    errorNYI(d.getSourceRange(),428             "getOrCreateStaticVarDecl: LoaderUninitializedAttr");429  assert(!cir::MissingFeatures::addressSpace());430 431  mlir::Attribute init = builder.getZeroInitAttr(convertType(ty));432 433  cir::GlobalOp gv = builder.createVersionedGlobal(434      getModule(), getLoc(d.getLocation()), name, lty, false, linkage);435  // TODO(cir): infer visibility from linkage in global op builder.436  gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));437  gv.setInitialValueAttr(init);438  gv.setAlignment(getASTContext().getDeclAlign(&d).getAsAlign().value());439 440  if (supportsCOMDAT() && gv.isWeakForLinker())441    gv.setComdat(true);442 443  assert(!cir::MissingFeatures::opGlobalThreadLocal());444 445  setGVProperties(gv, &d);446 447  // OG checks if the expected address space, denoted by the type, is the448  // same as the actual address space indicated by attributes. If they aren't449  // the same, an addrspacecast is emitted when this variable is accessed.450  // In CIR however, cir.get_global already carries that information in451  // !cir.ptr type - if this global is in OpenCL local address space, then its452  // type would be !cir.ptr<..., addrspace(offload_local)>. Therefore we don't453  // need an explicit address space cast in CIR: they will get emitted when454  // lowering to LLVM IR.455 456  // Ensure that the static local gets initialized by making sure the parent457  // function gets emitted eventually.458  const Decl *dc = cast<Decl>(d.getDeclContext());459 460  // We can't name blocks or captured statements directly, so try to emit their461  // parents.462  if (isa<BlockDecl>(dc) || isa<CapturedDecl>(dc)) {463    dc = dc->getNonClosureContext();464    // FIXME: Ensure that global blocks get emitted.465    if (!dc)466      errorNYI(d.getSourceRange(), "non-closure context");467  }468 469  GlobalDecl gd;470  if (isa<CXXConstructorDecl>(dc))471    errorNYI(d.getSourceRange(), "C++ constructors static var context");472  else if (isa<CXXDestructorDecl>(dc))473    errorNYI(d.getSourceRange(), "C++ destructors static var context");474  else if (const auto *fd = dyn_cast<FunctionDecl>(dc))475    gd = GlobalDecl(fd);476  else {477    // Don't do anything for Obj-C method decls or global closures. We should478    // never defer them.479    assert(isa<ObjCMethodDecl>(dc) && "unexpected parent code decl");480  }481  if (gd.getDecl() && cir::MissingFeatures::openMP()) {482    // Disable emission of the parent function for the OpenMP device codegen.483    errorNYI(d.getSourceRange(), "OpenMP");484  }485 486  return gv;487}488 489/// Add the initializer for 'd' to the global variable that has already been490/// created for it. If the initializer has a different type than gv does, this491/// may free gv and return a different one. Otherwise it just returns gv.492cir::GlobalOp CIRGenFunction::addInitializerToStaticVarDecl(493    const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr) {494  ConstantEmitter emitter(*this);495  mlir::TypedAttr init =496      mlir::cast<mlir::TypedAttr>(emitter.tryEmitForInitializer(d));497 498  // If constant emission failed, then this should be a C++ static499  // initializer.500  if (!init) {501    cgm.errorNYI(d.getSourceRange(), "static var without initializer");502    return gv;503  }504 505  // TODO(cir): There should be debug code here to assert that the decl size506  // matches the CIR data layout type alloc size, but the code for calculating507  // the type alloc size is not implemented yet.508  assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());509 510  // The initializer may differ in type from the global. Rewrite511  // the global to match the initializer.  (We have to do this512  // because some types, like unions, can't be completely represented513  // in the LLVM type system.)514  if (gv.getSymType() != init.getType()) {515    gv.setSymType(init.getType());516 517    // Normally this should be done with a call to cgm.replaceGlobal(oldGV, gv),518    // but since at this point the current block hasn't been really attached,519    // there's no visibility into the GetGlobalOp corresponding to this Global.520    // Given those constraints, thread in the GetGlobalOp and update it521    // directly.522    assert(!cir::MissingFeatures::addressSpace());523    gvAddr.getAddr().setType(builder.getPointerTo(init.getType()));524  }525 526  bool needsDtor =527      d.needsDestruction(getContext()) == QualType::DK_cxx_destructor;528 529  gv.setConstant(d.getType().isConstantStorage(530      getContext(), /*ExcludeCtor=*/true, !needsDtor));531  gv.setInitialValueAttr(init);532 533  emitter.finalize(gv);534 535  if (needsDtor) {536    // We have a constant initializer, but a nontrivial destructor. We still537    // need to perform a guarded "initialization" in order to register the538    // destructor.539    cgm.errorNYI(d.getSourceRange(), "C++ guarded init");540  }541 542  return gv;543}544 545void CIRGenFunction::emitStaticVarDecl(const VarDecl &d,546                                       cir::GlobalLinkageKind linkage) {547  // Check to see if we already have a global variable for this548  // declaration.  This can happen when double-emitting function549  // bodies, e.g. with complete and base constructors.550  cir::GlobalOp globalOp = cgm.getOrCreateStaticVarDecl(d, linkage);551  // TODO(cir): we should have a way to represent global ops as values without552  // having to emit a get global op. Sometimes these emissions are not used.553  mlir::Value addr = builder.createGetGlobal(globalOp);554  auto getAddrOp = addr.getDefiningOp<cir::GetGlobalOp>();555  assert(getAddrOp && "expected cir::GetGlobalOp");556 557  CharUnits alignment = getContext().getDeclAlign(&d);558 559  // Store into LocalDeclMap before generating initializer to handle560  // circular references.561  mlir::Type elemTy = convertTypeForMem(d.getType());562  setAddrOfLocalVar(&d, Address(addr, elemTy, alignment));563 564  // We can't have a VLA here, but we can have a pointer to a VLA,565  // even though that doesn't really make any sense.566  // Make sure to evaluate VLA bounds now so that we have them for later.567  if (d.getType()->isVariablyModifiedType()) {568    cgm.errorNYI(d.getSourceRange(),569                 "emitStaticVarDecl: variably modified type");570  }571 572  // Save the type in case adding the initializer forces a type change.573  mlir::Type expectedType = addr.getType();574 575  cir::GlobalOp var = globalOp;576 577  assert(!cir::MissingFeatures::cudaSupport());578 579  // If this value has an initializer, emit it.580  if (d.getInit())581    var = addInitializerToStaticVarDecl(d, var, getAddrOp);582 583  var.setAlignment(alignment.getAsAlign().value());584 585  // There are a lot of attributes that need to be handled here. Until586  // we start to support them, we just report an error if there are any.587  if (d.hasAttrs())588    cgm.errorNYI(d.getSourceRange(), "static var with attrs");589 590  if (cgm.getCodeGenOpts().KeepPersistentStorageVariables)591    cgm.errorNYI(d.getSourceRange(), "static var keep persistent storage");592 593  // From traditional codegen:594  // We may have to cast the constant because of the initializer595  // mismatch above.596  //597  // FIXME: It is really dangerous to store this in the map; if anyone598  // RAUW's the GV uses of this constant will be invalid.599  mlir::Value castedAddr =600      builder.createBitcast(getAddrOp.getAddr(), expectedType);601  localDeclMap.find(&d)->second = Address(castedAddr, elemTy, alignment);602  cgm.setStaticLocalDeclAddress(&d, var);603 604  assert(!cir::MissingFeatures::sanitizers());605  assert(!cir::MissingFeatures::generateDebugInfo());606}607 608void CIRGenFunction::emitScalarInit(const Expr *init, mlir::Location loc,609                                    LValue lvalue, bool capturedByInit) {610  assert(!cir::MissingFeatures::objCLifetime());611 612  SourceLocRAIIObject locRAII{*this, loc};613  mlir::Value value = emitScalarExpr(init);614  if (capturedByInit) {615    cgm.errorNYI(init->getSourceRange(), "emitScalarInit: captured by init");616    return;617  }618  assert(!cir::MissingFeatures::emitNullabilityCheck());619  emitStoreThroughLValue(RValue::get(value), lvalue, true);620}621 622void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d,623                                    LValue lvalue, bool capturedByInit) {624  SourceLocRAIIObject loc{*this, getLoc(init->getSourceRange())};625  if (capturedByInit) {626    cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");627    return;628  }629 630  QualType type = d->getType();631 632  if (type->isReferenceType()) {633    RValue rvalue = emitReferenceBindingToExpr(init);634    if (capturedByInit)635      cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");636    emitStoreThroughLValue(rvalue, lvalue);637    return;638  }639  switch (CIRGenFunction::getEvaluationKind(type)) {640  case cir::TEK_Scalar:641    emitScalarInit(init, getLoc(d->getSourceRange()), lvalue);642    return;643  case cir::TEK_Complex: {644    mlir::Value complex = emitComplexExpr(init);645    if (capturedByInit)646      cgm.errorNYI(init->getSourceRange(),647                   "emitExprAsInit: complex type captured by init");648    mlir::Location loc = getLoc(init->getExprLoc());649    emitStoreOfComplex(loc, complex, lvalue,650                       /*isInit*/ true);651    return;652  }653  case cir::TEK_Aggregate:654    // The overlap flag here should be calculated.655    assert(!cir::MissingFeatures::aggValueSlotMayOverlap());656    emitAggExpr(init,657                AggValueSlot::forLValue(lvalue, AggValueSlot::IsDestructed,658                                        AggValueSlot::IsNotAliased,659                                        AggValueSlot::MayOverlap));660    return;661  }662  llvm_unreachable("bad evaluation kind");663}664 665void CIRGenFunction::emitDecl(const Decl &d, bool evaluateConditionDecl) {666  switch (d.getKind()) {667  case Decl::BuiltinTemplate:668  case Decl::TranslationUnit:669  case Decl::ExternCContext:670  case Decl::Namespace:671  case Decl::UnresolvedUsingTypename:672  case Decl::ClassTemplateSpecialization:673  case Decl::ClassTemplatePartialSpecialization:674  case Decl::VarTemplateSpecialization:675  case Decl::VarTemplatePartialSpecialization:676  case Decl::TemplateTypeParm:677  case Decl::UnresolvedUsingValue:678  case Decl::NonTypeTemplateParm:679  case Decl::CXXDeductionGuide:680  case Decl::CXXMethod:681  case Decl::CXXConstructor:682  case Decl::CXXDestructor:683  case Decl::CXXConversion:684  case Decl::Field:685  case Decl::MSProperty:686  case Decl::IndirectField:687  case Decl::ObjCIvar:688  case Decl::ObjCAtDefsField:689  case Decl::ParmVar:690  case Decl::ImplicitParam:691  case Decl::ClassTemplate:692  case Decl::VarTemplate:693  case Decl::FunctionTemplate:694  case Decl::TypeAliasTemplate:695  case Decl::TemplateTemplateParm:696  case Decl::ObjCMethod:697  case Decl::ObjCCategory:698  case Decl::ObjCProtocol:699  case Decl::ObjCInterface:700  case Decl::ObjCCategoryImpl:701  case Decl::ObjCImplementation:702  case Decl::ObjCProperty:703  case Decl::ObjCCompatibleAlias:704  case Decl::PragmaComment:705  case Decl::PragmaDetectMismatch:706  case Decl::AccessSpec:707  case Decl::LinkageSpec:708  case Decl::Export:709  case Decl::ObjCPropertyImpl:710  case Decl::FileScopeAsm:711  case Decl::Friend:712  case Decl::FriendTemplate:713  case Decl::Block:714  case Decl::OutlinedFunction:715  case Decl::Captured:716  case Decl::UsingShadow:717  case Decl::ConstructorUsingShadow:718  case Decl::ObjCTypeParam:719  case Decl::Binding:720  case Decl::UnresolvedUsingIfExists:721  case Decl::HLSLBuffer:722  case Decl::HLSLRootSignature:723    llvm_unreachable("Declaration should not be in declstmts!");724 725  case Decl::Function:     // void X();726  case Decl::EnumConstant: // enum ? { X = ? }727  case Decl::StaticAssert: // static_assert(X, ""); [C++0x]728  case Decl::Label:        // __label__ x;729  case Decl::Import:730  case Decl::MSGuid: // __declspec(uuid("..."))731  case Decl::TemplateParamObject:732  case Decl::OMPThreadPrivate:733  case Decl::OMPGroupPrivate:734  case Decl::OMPAllocate:735  case Decl::OMPCapturedExpr:736  case Decl::OMPRequires:737  case Decl::Empty:738  case Decl::Concept:739  case Decl::LifetimeExtendedTemporary:740  case Decl::RequiresExprBody:741  case Decl::UnnamedGlobalConstant:742    // None of these decls require codegen support.743    return;744 745  case Decl::Enum:      // enum X;746  case Decl::Record:    // struct/union/class X;747  case Decl::CXXRecord: // struct/union/class X; [C++]748  case Decl::NamespaceAlias:749  case Decl::Using:          // using X; [C++]750  case Decl::UsingEnum:      // using enum X; [C++]751  case Decl::UsingDirective: // using namespace X; [C++]752    assert(!cir::MissingFeatures::generateDebugInfo());753    return;754  case Decl::Var:755  case Decl::Decomposition: {756    const VarDecl &vd = cast<VarDecl>(d);757    assert(vd.isLocalVarDecl() &&758           "Should not see file-scope variables inside a function!");759    emitVarDecl(vd);760    if (evaluateConditionDecl)761      maybeEmitDeferredVarDeclInit(&vd);762    return;763  }764  case Decl::OpenACCDeclare:765    emitOpenACCDeclare(cast<OpenACCDeclareDecl>(d));766    return;767  case Decl::OpenACCRoutine:768    emitOpenACCRoutine(cast<OpenACCRoutineDecl>(d));769    return;770  case Decl::Typedef:     // typedef int X;771  case Decl::TypeAlias: { // using X = int; [C++0x]772    QualType ty = cast<TypedefNameDecl>(d).getUnderlyingType();773    assert(!cir::MissingFeatures::generateDebugInfo());774    if (ty->isVariablyModifiedType())775      cgm.errorNYI(d.getSourceRange(), "emitDecl: variably modified type");776    return;777  }778  case Decl::ImplicitConceptSpecialization:779  case Decl::TopLevelStmt:780  case Decl::UsingPack:781  case Decl::OMPDeclareMapper:782  case Decl::OMPDeclareReduction:783    cgm.errorNYI(d.getSourceRange(),784                 std::string("emitDecl: unhandled decl type: ") +785                     d.getDeclKindName());786  }787}788 789void CIRGenFunction::emitNullabilityCheck(LValue lhs, mlir::Value rhs,790                                          SourceLocation loc) {791  if (!sanOpts.has(SanitizerKind::NullabilityAssign))792    return;793 794  assert(!cir::MissingFeatures::sanitizers());795}796 797namespace {798struct DestroyObject final : EHScopeStack::Cleanup {799  DestroyObject(Address addr, QualType type,800                CIRGenFunction::Destroyer *destroyer)801      : addr(addr), type(type), destroyer(destroyer) {}802 803  Address addr;804  QualType type;805  CIRGenFunction::Destroyer *destroyer;806 807  void emit(CIRGenFunction &cgf) override {808    cgf.emitDestroy(addr, type, destroyer);809  }810};811 812struct CallStackRestore final : EHScopeStack::Cleanup {813  Address stack;814  CallStackRestore(Address stack) : stack(stack) {}815  void emit(CIRGenFunction &cgf) override {816    mlir::Location loc = stack.getPointer().getLoc();817    mlir::Value v = cgf.getBuilder().createLoad(loc, stack);818    cgf.getBuilder().createStackRestore(loc, v);819  }820};821} // namespace822 823/// Push the standard destructor for the given type as824/// at least a normal cleanup.825void CIRGenFunction::pushDestroy(QualType::DestructionKind dtorKind,826                                 Address addr, QualType type) {827  assert(dtorKind && "cannot push destructor for trivial type");828 829  CleanupKind cleanupKind = getCleanupKind(dtorKind);830  pushDestroy(cleanupKind, addr, type, getDestroyer(dtorKind));831}832 833void CIRGenFunction::pushDestroy(CleanupKind cleanupKind, Address addr,834                                 QualType type, Destroyer *destroyer) {835  pushFullExprCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);836}837 838/// Destroys all the elements of the given array, beginning from last to first.839/// The array cannot be zero-length.840///841/// \param begin - a type* denoting the first element of the array842/// \param numElements - the number of elements in the array843/// \param elementType - the element type of the array844/// \param destroyer - the function to call to destroy elements845void CIRGenFunction::emitArrayDestroy(mlir::Value begin,846                                      mlir::Value numElements,847                                      QualType elementType,848                                      CharUnits elementAlign,849                                      Destroyer *destroyer) {850  assert(!elementType->isArrayType());851 852  // Differently from LLVM traditional codegen, use a higher level853  // representation instead of lowering directly to a loop.854  mlir::Type cirElementType = convertTypeForMem(elementType);855  cir::PointerType ptrToElmType = builder.getPointerTo(cirElementType);856 857  uint64_t size = 0;858 859  // Optimize for a constant array size.860  if (auto constantCount = numElements.getDefiningOp<cir::ConstantOp>()) {861    if (auto constIntAttr = constantCount.getValueAttr<cir::IntAttr>())862      size = constIntAttr.getUInt();863  } else {864    cgm.errorNYI(begin.getDefiningOp()->getLoc(),865                 "dynamic-length array expression");866  }867 868  auto arrayTy = cir::ArrayType::get(cirElementType, size);869  mlir::Value arrayOp = builder.createPtrBitcast(begin, arrayTy);870 871  // Emit the dtor call that will execute for every array element.872  cir::ArrayDtor::create(873      builder, *currSrcLoc, arrayOp,874      [&](mlir::OpBuilder &b, mlir::Location loc) {875        auto arg = b.getInsertionBlock()->addArgument(ptrToElmType, loc);876        Address curAddr = Address(arg, cirElementType, elementAlign);877        assert(!cir::MissingFeatures::dtorCleanups());878 879        // Perform the actual destruction there.880        destroyer(*this, curAddr, elementType);881 882        cir::YieldOp::create(builder, loc);883      });884}885 886/// Immediately perform the destruction of the given object.887///888/// \param addr - the address of the object; a type*889/// \param type - the type of the object; if an array type, all890///   objects are destroyed in reverse order891/// \param destroyer - the function to call to destroy individual892///   elements893void CIRGenFunction::emitDestroy(Address addr, QualType type,894                                 Destroyer *destroyer) {895  const ArrayType *arrayType = getContext().getAsArrayType(type);896  if (!arrayType)897    return destroyer(*this, addr, type);898 899  mlir::Value length = emitArrayLength(arrayType, type, addr);900 901  CharUnits elementAlign = addr.getAlignment().alignmentOfArrayElement(902      getContext().getTypeSizeInChars(type));903 904  auto constantCount = length.getDefiningOp<cir::ConstantOp>();905  if (!constantCount) {906    assert(!cir::MissingFeatures::vlas());907    cgm.errorNYI("emitDestroy: variable length array");908    return;909  }910 911  auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constantCount.getValue());912  // If it's constant zero, we can just skip the entire thing.913  if (constIntAttr && constIntAttr.getUInt() == 0)914    return;915 916  mlir::Value begin = addr.getPointer();917  emitArrayDestroy(begin, length, type, elementAlign, destroyer);918 919  // If the array destroy didn't use the length op, we can erase it.920  if (constantCount.use_empty())921    constantCount.erase();922}923 924CIRGenFunction::Destroyer *925CIRGenFunction::getDestroyer(QualType::DestructionKind kind) {926  switch (kind) {927  case QualType::DK_none:928    llvm_unreachable("no destroyer for trivial dtor");929  case QualType::DK_cxx_destructor:930    return destroyCXXObject;931  case QualType::DK_objc_strong_lifetime:932  case QualType::DK_objc_weak_lifetime:933  case QualType::DK_nontrivial_c_struct:934    cgm.errorNYI("getDestroyer: other destruction kind");935    return nullptr;936  }937  llvm_unreachable("Unknown DestructionKind");938}939 940void CIRGenFunction::pushStackRestore(CleanupKind kind, Address spMem) {941  ehStack.pushCleanup<CallStackRestore>(kind, spMem);942}943 944/// Enter a destroy cleanup for the given local variable.945void CIRGenFunction::emitAutoVarTypeCleanup(946    const CIRGenFunction::AutoVarEmission &emission,947    QualType::DestructionKind dtorKind) {948  assert(dtorKind != QualType::DK_none);949 950  // Note that for __block variables, we want to destroy the951  // original stack object, not the possibly forwarded object.952  Address addr = emission.getObjectAddress(*this);953 954  const VarDecl *var = emission.variable;955  QualType type = var->getType();956 957  CleanupKind cleanupKind = NormalAndEHCleanup;958  CIRGenFunction::Destroyer *destroyer = nullptr;959 960  switch (dtorKind) {961  case QualType::DK_none:962    llvm_unreachable("no cleanup for trivially-destructible variable");963 964  case QualType::DK_cxx_destructor:965    // If there's an NRVO flag on the emission, we need a different966    // cleanup.967    if (emission.nrvoFlag) {968      cgm.errorNYI(var->getSourceRange(), "emitAutoVarTypeCleanup: NRVO");969      return;970    }971    // Otherwise, this is handled below.972    break;973 974  case QualType::DK_objc_strong_lifetime:975  case QualType::DK_objc_weak_lifetime:976  case QualType::DK_nontrivial_c_struct:977    cgm.errorNYI(var->getSourceRange(),978                 "emitAutoVarTypeCleanup: other dtor kind");979    return;980  }981 982  // If we haven't chosen a more specific destroyer, use the default.983  if (!destroyer)984    destroyer = getDestroyer(dtorKind);985 986  assert(!cir::MissingFeatures::ehCleanupFlags());987  ehStack.pushCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);988}989 990void CIRGenFunction::maybeEmitDeferredVarDeclInit(const VarDecl *vd) {991  if (auto *dd = dyn_cast_if_present<DecompositionDecl>(vd)) {992    for (auto *b : dd->flat_bindings())993      if (auto *hd = b->getHoldingVar())994        emitVarDecl(*hd);995  }996}997