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