1298 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// Internal per-function state used for AST-to-ClangIR code gen10//11//===----------------------------------------------------------------------===//12 13#include "CIRGenFunction.h"14 15#include "CIRGenCXXABI.h"16#include "CIRGenCall.h"17#include "CIRGenValue.h"18#include "mlir/IR/Location.h"19#include "clang/AST/ExprCXX.h"20#include "clang/AST/GlobalDecl.h"21#include "clang/CIR/MissingFeatures.h"22 23#include <cassert>24 25namespace clang::CIRGen {26 27CIRGenFunction::CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder,28 bool suppressNewContext)29 : CIRGenTypeCache(cgm), cgm{cgm}, builder(builder) {30 ehStack.setCGF(this);31}32 33CIRGenFunction::~CIRGenFunction() {}34 35// This is copied from clang/lib/CodeGen/CodeGenFunction.cpp36cir::TypeEvaluationKind CIRGenFunction::getEvaluationKind(QualType type) {37 type = type.getCanonicalType();38 while (true) {39 switch (type->getTypeClass()) {40#define TYPE(name, parent)41#define ABSTRACT_TYPE(name, parent)42#define NON_CANONICAL_TYPE(name, parent) case Type::name:43#define DEPENDENT_TYPE(name, parent) case Type::name:44#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(name, parent) case Type::name:45#include "clang/AST/TypeNodes.inc"46 llvm_unreachable("non-canonical or dependent type in IR-generation");47 48 case Type::Auto:49 case Type::DeducedTemplateSpecialization:50 llvm_unreachable("undeduced type in IR-generation");51 52 // Various scalar types.53 case Type::Builtin:54 case Type::Pointer:55 case Type::BlockPointer:56 case Type::LValueReference:57 case Type::RValueReference:58 case Type::MemberPointer:59 case Type::Vector:60 case Type::ExtVector:61 case Type::ConstantMatrix:62 case Type::FunctionProto:63 case Type::FunctionNoProto:64 case Type::Enum:65 case Type::ObjCObjectPointer:66 case Type::Pipe:67 case Type::BitInt:68 case Type::HLSLAttributedResource:69 case Type::HLSLInlineSpirv:70 return cir::TEK_Scalar;71 72 // Complexes.73 case Type::Complex:74 return cir::TEK_Complex;75 76 // Arrays, records, and Objective-C objects.77 case Type::ConstantArray:78 case Type::IncompleteArray:79 case Type::VariableArray:80 case Type::Record:81 case Type::ObjCObject:82 case Type::ObjCInterface:83 case Type::ArrayParameter:84 return cir::TEK_Aggregate;85 86 // We operate on atomic values according to their underlying type.87 case Type::Atomic:88 type = cast<AtomicType>(type)->getValueType();89 continue;90 }91 llvm_unreachable("unknown type kind!");92 }93}94 95mlir::Type CIRGenFunction::convertTypeForMem(QualType t) {96 return cgm.getTypes().convertTypeForMem(t);97}98 99mlir::Type CIRGenFunction::convertType(QualType t) {100 return cgm.getTypes().convertType(t);101}102 103mlir::Location CIRGenFunction::getLoc(SourceLocation srcLoc) {104 // Some AST nodes might contain invalid source locations (e.g.105 // CXXDefaultArgExpr), workaround that to still get something out.106 if (srcLoc.isValid()) {107 const SourceManager &sm = getContext().getSourceManager();108 PresumedLoc pLoc = sm.getPresumedLoc(srcLoc);109 StringRef filename = pLoc.getFilename();110 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),111 pLoc.getLine(), pLoc.getColumn());112 }113 // Do our best...114 assert(currSrcLoc && "expected to inherit some source location");115 return *currSrcLoc;116}117 118mlir::Location CIRGenFunction::getLoc(SourceRange srcLoc) {119 // Some AST nodes might contain invalid source locations (e.g.120 // CXXDefaultArgExpr), workaround that to still get something out.121 if (srcLoc.isValid()) {122 mlir::Location beg = getLoc(srcLoc.getBegin());123 mlir::Location end = getLoc(srcLoc.getEnd());124 SmallVector<mlir::Location, 2> locs = {beg, end};125 mlir::Attribute metadata;126 return mlir::FusedLoc::get(locs, metadata, &getMLIRContext());127 }128 if (currSrcLoc) {129 return *currSrcLoc;130 }131 // We're brave, but time to give up.132 return builder.getUnknownLoc();133}134 135mlir::Location CIRGenFunction::getLoc(mlir::Location lhs, mlir::Location rhs) {136 SmallVector<mlir::Location, 2> locs = {lhs, rhs};137 mlir::Attribute metadata;138 return mlir::FusedLoc::get(locs, metadata, &getMLIRContext());139}140 141bool CIRGenFunction::containsLabel(const Stmt *s, bool ignoreCaseStmts) {142 // Null statement, not a label!143 if (!s)144 return false;145 146 // If this is a label, we have to emit the code, consider something like:147 // if (0) { ... foo: bar(); } goto foo;148 //149 // TODO: If anyone cared, we could track __label__'s, since we know that you150 // can't jump to one from outside their declared region.151 if (isa<LabelStmt>(s))152 return true;153 154 // If this is a case/default statement, and we haven't seen a switch, we155 // have to emit the code.156 if (isa<SwitchCase>(s) && !ignoreCaseStmts)157 return true;158 159 // If this is a switch statement, we want to ignore case statements when we160 // recursively process the sub-statements of the switch. If we haven't161 // encountered a switch statement, we treat case statements like labels, but162 // if we are processing a switch statement, case statements are expected.163 if (isa<SwitchStmt>(s))164 ignoreCaseStmts = true;165 166 // Scan subexpressions for verboten labels.167 return std::any_of(s->child_begin(), s->child_end(),168 [=](const Stmt *subStmt) {169 return containsLabel(subStmt, ignoreCaseStmts);170 });171}172 173/// If the specified expression does not fold to a constant, or if it does but174/// contains a label, return false. If it constant folds return true and set175/// the boolean result in Result.176bool CIRGenFunction::constantFoldsToBool(const Expr *cond, bool &resultBool,177 bool allowLabels) {178 llvm::APSInt resultInt;179 if (!constantFoldsToSimpleInteger(cond, resultInt, allowLabels))180 return false;181 182 resultBool = resultInt.getBoolValue();183 return true;184}185 186/// If the specified expression does not fold to a constant, or if it does187/// fold but contains a label, return false. If it constant folds, return188/// true and set the folded value.189bool CIRGenFunction::constantFoldsToSimpleInteger(const Expr *cond,190 llvm::APSInt &resultInt,191 bool allowLabels) {192 // FIXME: Rename and handle conversion of other evaluatable things193 // to bool.194 Expr::EvalResult result;195 if (!cond->EvaluateAsInt(result, getContext()))196 return false; // Not foldable, not integer or not fully evaluatable.197 198 llvm::APSInt intValue = result.Val.getInt();199 if (!allowLabels && containsLabel(cond))200 return false; // Contains a label.201 202 resultInt = intValue;203 return true;204}205 206void CIRGenFunction::emitAndUpdateRetAlloca(QualType type, mlir::Location loc,207 CharUnits alignment) {208 if (!type->isVoidType()) {209 mlir::Value addr = emitAlloca("__retval", convertType(type), loc, alignment,210 /*insertIntoFnEntryBlock=*/false);211 fnRetAlloca = addr;212 returnValue = Address(addr, alignment);213 }214}215 216void CIRGenFunction::declare(mlir::Value addrVal, const Decl *var, QualType ty,217 mlir::Location loc, CharUnits alignment,218 bool isParam) {219 assert(isa<NamedDecl>(var) && "Needs a named decl");220 assert(!symbolTable.count(var) && "not supposed to be available just yet");221 222 auto allocaOp = addrVal.getDefiningOp<cir::AllocaOp>();223 assert(allocaOp && "expected cir::AllocaOp");224 225 if (isParam)226 allocaOp.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));227 if (ty->isReferenceType() || ty.isConstQualified())228 allocaOp.setConstantAttr(mlir::UnitAttr::get(&getMLIRContext()));229 230 symbolTable.insert(var, allocaOp);231}232 233void CIRGenFunction::LexicalScope::cleanup() {234 CIRGenBuilderTy &builder = cgf.builder;235 LexicalScope *localScope = cgf.curLexScope;236 237 auto applyCleanup = [&]() {238 if (performCleanup) {239 // ApplyDebugLocation240 assert(!cir::MissingFeatures::generateDebugInfo());241 forceCleanup();242 }243 };244 245 // Cleanup are done right before codegen resumes a scope. This is where246 // objects are destroyed. Process all return blocks.247 // TODO(cir): Handle returning from a switch statement through a cleanup248 // block. We can't simply jump to the cleanup block, because the cleanup block249 // is not part of the case region. Either reemit all cleanups in the return250 // block or wait for MLIR structured control flow to support early exits.251 llvm::SmallVector<mlir::Block *> retBlocks;252 for (mlir::Block *retBlock : localScope->getRetBlocks()) {253 mlir::OpBuilder::InsertionGuard guard(builder);254 builder.setInsertionPointToEnd(retBlock);255 retBlocks.push_back(retBlock);256 mlir::Location retLoc = localScope->getRetLoc(retBlock);257 emitReturn(retLoc);258 }259 260 auto insertCleanupAndLeave = [&](mlir::Block *insPt) {261 mlir::OpBuilder::InsertionGuard guard(builder);262 builder.setInsertionPointToEnd(insPt);263 264 // If we still don't have a cleanup block, it means that `applyCleanup`265 // below might be able to get us one.266 mlir::Block *cleanupBlock = localScope->getCleanupBlock(builder);267 268 // Leverage and defers to RunCleanupsScope's dtor and scope handling.269 applyCleanup();270 271 // If we now have one after `applyCleanup`, hook it up properly.272 if (!cleanupBlock && localScope->getCleanupBlock(builder)) {273 cleanupBlock = localScope->getCleanupBlock(builder);274 cir::BrOp::create(builder, insPt->back().getLoc(), cleanupBlock);275 if (!cleanupBlock->mightHaveTerminator()) {276 mlir::OpBuilder::InsertionGuard guard(builder);277 builder.setInsertionPointToEnd(cleanupBlock);278 cir::YieldOp::create(builder, localScope->endLoc);279 }280 }281 282 if (localScope->depth == 0) {283 // Reached the end of the function.284 // Special handling only for single return block case285 if (localScope->getRetBlocks().size() == 1) {286 mlir::Block *retBlock = localScope->getRetBlocks()[0];287 mlir::Location retLoc = localScope->getRetLoc(retBlock);288 if (retBlock->getUses().empty()) {289 retBlock->erase();290 } else {291 // Thread return block via cleanup block.292 if (cleanupBlock) {293 for (mlir::BlockOperand &blockUse : retBlock->getUses()) {294 cir::BrOp brOp = mlir::cast<cir::BrOp>(blockUse.getOwner());295 brOp.setSuccessor(cleanupBlock);296 }297 }298 299 cir::BrOp::create(builder, retLoc, retBlock);300 return;301 }302 }303 emitImplicitReturn();304 return;305 }306 307 // End of any local scope != function308 // Ternary ops have to deal with matching arms for yielding types309 // and do return a value, it must do its own cir.yield insertion.310 if (!localScope->isTernary() && !insPt->mightHaveTerminator()) {311 !retVal ? cir::YieldOp::create(builder, localScope->endLoc)312 : cir::YieldOp::create(builder, localScope->endLoc, retVal);313 }314 };315 316 // If a cleanup block has been created at some point, branch to it317 // and set the insertion point to continue at the cleanup block.318 // Terminators are then inserted either in the cleanup block or319 // inline in this current block.320 mlir::Block *cleanupBlock = localScope->getCleanupBlock(builder);321 if (cleanupBlock)322 insertCleanupAndLeave(cleanupBlock);323 324 // Now deal with any pending block wrap up like implicit end of325 // scope.326 327 mlir::Block *curBlock = builder.getBlock();328 if (isGlobalInit() && !curBlock)329 return;330 if (curBlock->mightHaveTerminator() && curBlock->getTerminator())331 return;332 333 // Get rid of any empty block at the end of the scope.334 bool entryBlock = builder.getInsertionBlock()->isEntryBlock();335 if (!entryBlock && curBlock->empty()) {336 curBlock->erase();337 for (mlir::Block *retBlock : retBlocks) {338 if (retBlock->getUses().empty())339 retBlock->erase();340 }341 return;342 }343 344 // If there's a cleanup block, branch to it, nothing else to do.345 if (cleanupBlock) {346 cir::BrOp::create(builder, curBlock->back().getLoc(), cleanupBlock);347 return;348 }349 350 // No pre-existent cleanup block, emit cleanup code and yield/return.351 insertCleanupAndLeave(curBlock);352}353 354cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {355 CIRGenBuilderTy &builder = cgf.getBuilder();356 357 // If we are on a coroutine, add the coro_end builtin call.358 assert(!cir::MissingFeatures::coroEndBuiltinCall());359 360 auto fn = dyn_cast<cir::FuncOp>(cgf.curFn);361 assert(fn && "emitReturn from non-function");362 if (!fn.getFunctionType().hasVoidReturn()) {363 // Load the value from `__retval` and return it via the `cir.return` op.364 auto value = cir::LoadOp::create(365 builder, loc, fn.getFunctionType().getReturnType(), *cgf.fnRetAlloca);366 return cir::ReturnOp::create(builder, loc,367 llvm::ArrayRef(value.getResult()));368 }369 return cir::ReturnOp::create(builder, loc);370}371 372// This is copied from CodeGenModule::MayDropFunctionReturn. This is a373// candidate for sharing between CIRGen and CodeGen.374static bool mayDropFunctionReturn(const ASTContext &astContext,375 QualType returnType) {376 // We can't just discard the return value for a record type with a complex377 // destructor or a non-trivially copyable type.378 if (const auto *classDecl = returnType->getAsCXXRecordDecl())379 return classDecl->hasTrivialDestructor();380 return returnType.isTriviallyCopyableType(astContext);381}382 383void CIRGenFunction::LexicalScope::emitImplicitReturn() {384 CIRGenBuilderTy &builder = cgf.getBuilder();385 LexicalScope *localScope = cgf.curLexScope;386 387 const auto *fd = cast<clang::FunctionDecl>(cgf.curGD.getDecl());388 389 // In C++, flowing off the end of a non-void function is always undefined390 // behavior. In C, flowing off the end of a non-void function is undefined391 // behavior only if the non-existent return value is used by the caller.392 // That influences whether the terminating op is trap, unreachable, or393 // return.394 if (cgf.getLangOpts().CPlusPlus && !fd->hasImplicitReturnZero() &&395 !cgf.sawAsmBlock && !fd->getReturnType()->isVoidType() &&396 builder.getInsertionBlock()) {397 bool shouldEmitUnreachable =398 cgf.cgm.getCodeGenOpts().StrictReturn ||399 !mayDropFunctionReturn(fd->getASTContext(), fd->getReturnType());400 401 if (shouldEmitUnreachable) {402 assert(!cir::MissingFeatures::sanitizers());403 if (cgf.cgm.getCodeGenOpts().OptimizationLevel == 0)404 cir::TrapOp::create(builder, localScope->endLoc);405 else406 cir::UnreachableOp::create(builder, localScope->endLoc);407 builder.clearInsertionPoint();408 return;409 }410 }411 412 (void)emitReturn(localScope->endLoc);413}414 415cir::TryOp CIRGenFunction::LexicalScope::getClosestTryParent() {416 LexicalScope *scope = this;417 while (scope) {418 if (scope->isTry())419 return scope->getTry();420 scope = scope->parentScope;421 }422 return nullptr;423}424 425void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType,426 cir::FuncOp fn, cir::FuncType funcType,427 FunctionArgList args, SourceLocation loc,428 SourceLocation startLoc) {429 assert(!curFn &&430 "CIRGenFunction can only be used for one function at a time");431 432 curFn = fn;433 434 const Decl *d = gd.getDecl();435 436 didCallStackSave = false;437 curCodeDecl = d;438 const auto *fd = dyn_cast_or_null<FunctionDecl>(d);439 curFuncDecl = d->getNonClosureContext();440 441 prologueCleanupDepth = ehStack.stable_begin();442 443 mlir::Block *entryBB = &fn.getBlocks().front();444 builder.setInsertionPointToStart(entryBB);445 446 // TODO(cir): this should live in `emitFunctionProlog447 // Declare all the function arguments in the symbol table.448 for (const auto nameValue : llvm::zip(args, entryBB->getArguments())) {449 const VarDecl *paramVar = std::get<0>(nameValue);450 mlir::Value paramVal = std::get<1>(nameValue);451 CharUnits alignment = getContext().getDeclAlign(paramVar);452 mlir::Location paramLoc = getLoc(paramVar->getSourceRange());453 paramVal.setLoc(paramLoc);454 455 mlir::Value addrVal =456 emitAlloca(cast<NamedDecl>(paramVar)->getName(),457 convertType(paramVar->getType()), paramLoc, alignment,458 /*insertIntoFnEntryBlock=*/true);459 460 declare(addrVal, paramVar, paramVar->getType(), paramLoc, alignment,461 /*isParam=*/true);462 463 setAddrOfLocalVar(paramVar, Address(addrVal, alignment));464 465 bool isPromoted = isa<ParmVarDecl>(paramVar) &&466 cast<ParmVarDecl>(paramVar)->isKNRPromoted();467 assert(!cir::MissingFeatures::constructABIArgDirectExtend());468 if (isPromoted)469 cgm.errorNYI(fd->getSourceRange(), "Function argument demotion");470 471 // Location of the store to the param storage tracked as beginning of472 // the function body.473 mlir::Location fnBodyBegin = getLoc(fd->getBody()->getBeginLoc());474 builder.CIRBaseBuilderTy::createStore(fnBodyBegin, paramVal, addrVal);475 }476 assert(builder.getInsertionBlock() && "Should be valid");477 478 // When the current function is not void, create an address to store the479 // result value.480 if (!returnType->isVoidType())481 emitAndUpdateRetAlloca(returnType, getLoc(fd->getBody()->getEndLoc()),482 getContext().getTypeAlignInChars(returnType));483 484 if (isa_and_nonnull<CXXMethodDecl>(d) &&485 cast<CXXMethodDecl>(d)->isInstance()) {486 cgm.getCXXABI().emitInstanceFunctionProlog(loc, *this);487 488 const auto *md = cast<CXXMethodDecl>(d);489 if (md->getParent()->isLambda() && md->getOverloadedOperator() == OO_Call) {490 // We're in a lambda.491 auto fn = dyn_cast<cir::FuncOp>(curFn);492 assert(fn && "lambda in non-function region");493 fn.setLambda(true);494 495 // Figure out the captures.496 md->getParent()->getCaptureFields(lambdaCaptureFields,497 lambdaThisCaptureField);498 if (lambdaThisCaptureField) {499 // If the lambda captures the object referred to by '*this' - either by500 // value or by reference, make sure CXXThisValue points to the correct501 // object.502 503 // Get the lvalue for the field (which is a copy of the enclosing object504 // or contains the address of the enclosing object).505 LValue thisFieldLValue =506 emitLValueForLambdaField(lambdaThisCaptureField);507 if (!lambdaThisCaptureField->getType()->isPointerType()) {508 // If the enclosing object was captured by value, just use its509 // address. Sign this pointer.510 cxxThisValue = thisFieldLValue.getPointer();511 } else {512 // Load the lvalue pointed to by the field, since '*this' was captured513 // by reference.514 cxxThisValue =515 emitLoadOfLValue(thisFieldLValue, SourceLocation()).getValue();516 }517 }518 for (auto *fd : md->getParent()->fields()) {519 if (fd->hasCapturedVLAType())520 cgm.errorNYI(loc, "lambda captured VLA type");521 }522 } else {523 // Not in a lambda; just use 'this' from the method.524 // FIXME: Should we generate a new load for each use of 'this'? The fast525 // register allocator would be happier...526 cxxThisValue = cxxabiThisValue;527 }528 529 assert(!cir::MissingFeatures::sanitizers());530 assert(!cir::MissingFeatures::emitTypeCheck());531 }532}533 534void CIRGenFunction::finishFunction(SourceLocation endLoc) {535 // Pop any cleanups that might have been associated with the536 // parameters. Do this in whatever block we're currently in; it's537 // important to do this before we enter the return block or return538 // edges will be *really* confused.539 // TODO(cir): Use prologueCleanupDepth here.540 bool hasCleanups = ehStack.stable_begin() != prologueCleanupDepth;541 if (hasCleanups) {542 assert(!cir::MissingFeatures::generateDebugInfo());543 // FIXME(cir): should we clearInsertionPoint? breaks many testcases544 popCleanupBlocks(prologueCleanupDepth);545 }546}547 548mlir::LogicalResult CIRGenFunction::emitFunctionBody(const clang::Stmt *body) {549 // We start with function level scope for variables.550 SymTableScopeTy varScope(symbolTable);551 552 if (const CompoundStmt *block = dyn_cast<CompoundStmt>(body))553 return emitCompoundStmtWithoutScope(*block);554 555 return emitStmt(body, /*useCurrentScope=*/true);556}557 558static void eraseEmptyAndUnusedBlocks(cir::FuncOp func) {559 // Remove any leftover blocks that are unreachable and empty, since they do560 // not represent unreachable code useful for warnings nor anything deemed561 // useful in general.562 SmallVector<mlir::Block *> blocksToDelete;563 for (mlir::Block &block : func.getBlocks()) {564 if (block.empty() && block.getUses().empty())565 blocksToDelete.push_back(&block);566 }567 for (mlir::Block *block : blocksToDelete)568 block->erase();569}570 571cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl gd, cir::FuncOp fn,572 cir::FuncType funcType) {573 const auto *funcDecl = cast<FunctionDecl>(gd.getDecl());574 curGD = gd;575 576 if (funcDecl->isInlineBuiltinDeclaration()) {577 // When generating code for a builtin with an inline declaration, use a578 // mangled name to hold the actual body, while keeping an external579 // declaration in case the function pointer is referenced somewhere.580 std::string fdInlineName = (cgm.getMangledName(funcDecl) + ".inline").str();581 cir::FuncOp clone =582 mlir::cast_or_null<cir::FuncOp>(cgm.getGlobalValue(fdInlineName));583 if (!clone) {584 mlir::OpBuilder::InsertionGuard guard(builder);585 builder.setInsertionPoint(fn);586 clone = cir::FuncOp::create(builder, fn.getLoc(), fdInlineName,587 fn.getFunctionType());588 clone.setLinkage(cir::GlobalLinkageKind::InternalLinkage);589 clone.setSymVisibility("private");590 clone.setInlineKind(cir::InlineKind::AlwaysInline);591 }592 fn.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);593 fn.setSymVisibility("private");594 fn = clone;595 } else {596 // Detect the unusual situation where an inline version is shadowed by a597 // non-inline version. In that case we should pick the external one598 // everywhere. That's GCC behavior too.599 for (const FunctionDecl *pd = funcDecl->getPreviousDecl(); pd;600 pd = pd->getPreviousDecl()) {601 if (LLVM_UNLIKELY(pd->isInlineBuiltinDeclaration())) {602 std::string inlineName = funcDecl->getName().str() + ".inline";603 if (auto inlineFn = mlir::cast_or_null<cir::FuncOp>(604 cgm.getGlobalValue(inlineName))) {605 // Replace all uses of the .inline function with the regular function606 // FIXME: This performs a linear walk over the module. Introduce some607 // caching here.608 if (inlineFn609 .replaceAllSymbolUses(fn.getSymNameAttr(), cgm.getModule())610 .failed())611 llvm_unreachable("Failed to replace inline builtin symbol uses");612 inlineFn.erase();613 }614 break;615 }616 }617 }618 619 SourceLocation loc = funcDecl->getLocation();620 Stmt *body = funcDecl->getBody();621 SourceRange bodyRange =622 body ? body->getSourceRange() : funcDecl->getLocation();623 624 SourceLocRAIIObject fnLoc{*this, loc.isValid() ? getLoc(loc)625 : builder.getUnknownLoc()};626 627 auto validMLIRLoc = [&](clang::SourceLocation clangLoc) {628 return clangLoc.isValid() ? getLoc(clangLoc) : builder.getUnknownLoc();629 };630 const mlir::Location fusedLoc = mlir::FusedLoc::get(631 &getMLIRContext(),632 {validMLIRLoc(bodyRange.getBegin()), validMLIRLoc(bodyRange.getEnd())});633 mlir::Block *entryBB = fn.addEntryBlock();634 635 FunctionArgList args;636 QualType retTy = buildFunctionArgList(gd, args);637 638 // Create a scope in the symbol table to hold variable declarations.639 SymTableScopeTy varScope(symbolTable);640 {641 LexicalScope lexScope(*this, fusedLoc, entryBB);642 643 // Emit the standard function prologue.644 startFunction(gd, retTy, fn, funcType, args, loc, bodyRange.getBegin());645 646 // Save parameters for coroutine function.647 if (body && isa_and_nonnull<CoroutineBodyStmt>(body))648 llvm::append_range(fnArgs, funcDecl->parameters());649 650 if (isa<CXXDestructorDecl>(funcDecl)) {651 emitDestructorBody(args);652 } else if (isa<CXXConstructorDecl>(funcDecl)) {653 emitConstructorBody(args);654 } else if (getLangOpts().CUDA && !getLangOpts().CUDAIsDevice &&655 funcDecl->hasAttr<CUDAGlobalAttr>()) {656 getCIRGenModule().errorNYI(bodyRange, "CUDA kernel");657 } else if (isa<CXXMethodDecl>(funcDecl) &&658 cast<CXXMethodDecl>(funcDecl)->isLambdaStaticInvoker()) {659 // The lambda static invoker function is special, because it forwards or660 // clones the body of the function call operator (but is actually661 // static).662 emitLambdaStaticInvokeBody(cast<CXXMethodDecl>(funcDecl));663 } else if (funcDecl->isDefaulted() && isa<CXXMethodDecl>(funcDecl) &&664 (cast<CXXMethodDecl>(funcDecl)->isCopyAssignmentOperator() ||665 cast<CXXMethodDecl>(funcDecl)->isMoveAssignmentOperator())) {666 // Implicit copy-assignment gets the same special treatment as implicit667 // copy-constructors.668 emitImplicitAssignmentOperatorBody(args);669 } else if (body) {670 // Emit standard function body.671 if (mlir::failed(emitFunctionBody(body))) {672 return nullptr;673 }674 } else {675 // Anything without a body should have been handled above.676 llvm_unreachable("no definition for normal function");677 }678 679 if (mlir::failed(fn.verifyBody()))680 return nullptr;681 682 finishFunction(bodyRange.getEnd());683 }684 685 eraseEmptyAndUnusedBlocks(fn);686 return fn;687}688 689void CIRGenFunction::emitConstructorBody(FunctionArgList &args) {690 assert(!cir::MissingFeatures::sanitizers());691 const auto *ctor = cast<CXXConstructorDecl>(curGD.getDecl());692 CXXCtorType ctorType = curGD.getCtorType();693 694 assert((cgm.getTarget().getCXXABI().hasConstructorVariants() ||695 ctorType == Ctor_Complete) &&696 "can only generate complete ctor for this ABI");697 698 cgm.setCXXSpecialMemberAttr(cast<cir::FuncOp>(curFn), ctor);699 700 if (ctorType == Ctor_Complete && isConstructorDelegationValid(ctor) &&701 cgm.getTarget().getCXXABI().hasConstructorVariants()) {702 emitDelegateCXXConstructorCall(ctor, Ctor_Base, args, ctor->getEndLoc());703 return;704 }705 706 const FunctionDecl *definition = nullptr;707 Stmt *body = ctor->getBody(definition);708 assert(definition == ctor && "emitting wrong constructor body");709 710 if (isa_and_nonnull<CXXTryStmt>(body)) {711 cgm.errorNYI(ctor->getSourceRange(), "emitConstructorBody: try body");712 return;713 }714 715 assert(!cir::MissingFeatures::incrementProfileCounter());716 assert(!cir::MissingFeatures::runCleanupsScope());717 718 // TODO: in restricted cases, we can emit the vbase initializers of a719 // complete ctor and then delegate to the base ctor.720 721 // Emit the constructor prologue, i.e. the base and member initializers.722 emitCtorPrologue(ctor, ctorType, args);723 724 // TODO(cir): propagate this result via mlir::logical result. Just unreachable725 // now just to have it handled.726 if (mlir::failed(emitStmt(body, true))) {727 cgm.errorNYI(ctor->getSourceRange(),728 "emitConstructorBody: emit body statement failed.");729 return;730 }731}732 733/// Emits the body of the current destructor.734void CIRGenFunction::emitDestructorBody(FunctionArgList &args) {735 const CXXDestructorDecl *dtor = cast<CXXDestructorDecl>(curGD.getDecl());736 CXXDtorType dtorType = curGD.getDtorType();737 738 cgm.setCXXSpecialMemberAttr(cast<cir::FuncOp>(curFn), dtor);739 740 // For an abstract class, non-base destructors are never used (and can't741 // be emitted in general, because vbase dtors may not have been validated742 // by Sema), but the Itanium ABI doesn't make them optional and Clang may743 // in fact emit references to them from other compilations, so emit them744 // as functions containing a trap instruction.745 if (dtorType != Dtor_Base && dtor->getParent()->isAbstract()) {746 cgm.errorNYI(dtor->getSourceRange(), "abstract base class destructors");747 return;748 }749 750 Stmt *body = dtor->getBody();751 assert(body && !cir::MissingFeatures::incrementProfileCounter());752 753 // The call to operator delete in a deleting destructor happens754 // outside of the function-try-block, which means it's always755 // possible to delegate the destructor body to the complete756 // destructor. Do so.757 if (dtorType == Dtor_Deleting) {758 RunCleanupsScope dtorEpilogue(*this);759 enterDtorCleanups(dtor, Dtor_Deleting);760 if (haveInsertPoint()) {761 QualType thisTy = dtor->getFunctionObjectParameterType();762 emitCXXDestructorCall(dtor, Dtor_Complete, /*forVirtualBase=*/false,763 /*delegating=*/false, loadCXXThisAddress(), thisTy);764 }765 return;766 }767 768 // If the body is a function-try-block, enter the try before769 // anything else.770 const bool isTryBody = isa_and_nonnull<CXXTryStmt>(body);771 if (isTryBody)772 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");773 774 assert(!cir::MissingFeatures::sanitizers());775 776 // Enter the epilogue cleanups.777 RunCleanupsScope dtorEpilogue(*this);778 779 // If this is the complete variant, just invoke the base variant;780 // the epilogue will destruct the virtual bases. But we can't do781 // this optimization if the body is a function-try-block, because782 // we'd introduce *two* handler blocks. In the Microsoft ABI, we783 // always delegate because we might not have a definition in this TU.784 switch (dtorType) {785 case Dtor_Unified:786 llvm_unreachable("not expecting a unified dtor");787 case Dtor_Comdat:788 llvm_unreachable("not expecting a COMDAT");789 case Dtor_Deleting:790 llvm_unreachable("already handled deleting case");791 792 case Dtor_Complete:793 assert((body || getTarget().getCXXABI().isMicrosoft()) &&794 "can't emit a dtor without a body for non-Microsoft ABIs");795 796 // Enter the cleanup scopes for virtual bases.797 enterDtorCleanups(dtor, Dtor_Complete);798 799 if (!isTryBody) {800 QualType thisTy = dtor->getFunctionObjectParameterType();801 emitCXXDestructorCall(dtor, Dtor_Base, /*forVirtualBase=*/false,802 /*delegating=*/false, loadCXXThisAddress(), thisTy);803 break;804 }805 806 // Fallthrough: act like we're in the base variant.807 [[fallthrough]];808 809 case Dtor_Base:810 assert(body);811 812 // Enter the cleanup scopes for fields and non-virtual bases.813 enterDtorCleanups(dtor, Dtor_Base);814 815 assert(!cir::MissingFeatures::vtableInitialization());816 817 if (isTryBody) {818 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");819 } else if (body) {820 (void)emitStmt(body, /*useCurrentScope=*/true);821 } else {822 assert(dtor->isImplicit() && "bodyless dtor not implicit");823 // nothing to do besides what's in the epilogue824 }825 // -fapple-kext must inline any call to this dtor into826 // the caller's body.827 assert(!cir::MissingFeatures::appleKext());828 829 break;830 }831 832 // Jump out through the epilogue cleanups.833 dtorEpilogue.forceCleanup();834 835 // Exit the try if applicable.836 if (isTryBody)837 cgm.errorNYI(dtor->getSourceRange(), "function-try-block destructor");838}839 840/// Given a value of type T* that may not be to a complete object, construct841/// an l-vlaue withi the natural pointee alignment of T.842LValue CIRGenFunction::makeNaturalAlignPointeeAddrLValue(mlir::Value val,843 QualType ty) {844 // FIXME(cir): is it safe to assume Op->getResult(0) is valid? Perhaps845 // assert on the result type first.846 LValueBaseInfo baseInfo;847 assert(!cir::MissingFeatures::opTBAA());848 CharUnits align = cgm.getNaturalTypeAlignment(ty, &baseInfo);849 return makeAddrLValue(Address(val, align), ty, baseInfo);850}851 852LValue CIRGenFunction::makeNaturalAlignAddrLValue(mlir::Value val,853 QualType ty) {854 LValueBaseInfo baseInfo;855 CharUnits alignment = cgm.getNaturalTypeAlignment(ty, &baseInfo);856 Address addr(val, convertTypeForMem(ty), alignment);857 assert(!cir::MissingFeatures::opTBAA());858 return makeAddrLValue(addr, ty, baseInfo);859}860 861clang::QualType CIRGenFunction::buildFunctionArgList(clang::GlobalDecl gd,862 FunctionArgList &args) {863 const auto *fd = cast<FunctionDecl>(gd.getDecl());864 QualType retTy = fd->getReturnType();865 866 const auto *md = dyn_cast<CXXMethodDecl>(fd);867 if (md && md->isInstance()) {868 if (cgm.getCXXABI().hasThisReturn(gd))869 cgm.errorNYI(fd->getSourceRange(), "this return");870 else if (cgm.getCXXABI().hasMostDerivedReturn(gd))871 cgm.errorNYI(fd->getSourceRange(), "most derived return");872 cgm.getCXXABI().buildThisParam(*this, args);873 }874 875 if (const auto *cd = dyn_cast<CXXConstructorDecl>(fd))876 if (cd->getInheritedConstructor())877 cgm.errorNYI(fd->getSourceRange(),878 "buildFunctionArgList: inherited constructor");879 880 for (auto *param : fd->parameters())881 args.push_back(param);882 883 if (md && (isa<CXXConstructorDecl>(md) || isa<CXXDestructorDecl>(md)))884 cgm.getCXXABI().addImplicitStructorParams(*this, retTy, args);885 886 return retTy;887}888 889/// Emit code to compute a designator that specifies the location890/// of the expression.891/// FIXME: document this function better.892LValue CIRGenFunction::emitLValue(const Expr *e) {893 // FIXME: ApplyDebugLocation DL(*this, e);894 switch (e->getStmtClass()) {895 default:896 getCIRGenModule().errorNYI(e->getSourceRange(),897 std::string("l-value not implemented for '") +898 e->getStmtClassName() + "'");899 return LValue();900 case Expr::ConditionalOperatorClass:901 return emitConditionalOperatorLValue(cast<ConditionalOperator>(e));902 case Expr::BinaryConditionalOperatorClass:903 return emitConditionalOperatorLValue(cast<BinaryConditionalOperator>(e));904 case Expr::ArraySubscriptExprClass:905 return emitArraySubscriptExpr(cast<ArraySubscriptExpr>(e));906 case Expr::ExtVectorElementExprClass:907 return emitExtVectorElementExpr(cast<ExtVectorElementExpr>(e));908 case Expr::UnaryOperatorClass:909 return emitUnaryOpLValue(cast<UnaryOperator>(e));910 case Expr::StringLiteralClass:911 return emitStringLiteralLValue(cast<StringLiteral>(e));912 case Expr::MemberExprClass:913 return emitMemberExpr(cast<MemberExpr>(e));914 case Expr::CompoundLiteralExprClass:915 return emitCompoundLiteralLValue(cast<CompoundLiteralExpr>(e));916 case Expr::PredefinedExprClass:917 return emitPredefinedLValue(cast<PredefinedExpr>(e));918 case Expr::BinaryOperatorClass:919 return emitBinaryOperatorLValue(cast<BinaryOperator>(e));920 case Expr::CompoundAssignOperatorClass: {921 QualType ty = e->getType();922 if (ty->getAs<AtomicType>()) {923 cgm.errorNYI(e->getSourceRange(),924 "CompoundAssignOperator with AtomicType");925 return LValue();926 }927 if (!ty->isAnyComplexType())928 return emitCompoundAssignmentLValue(cast<CompoundAssignOperator>(e));929 930 return emitComplexCompoundAssignmentLValue(cast<CompoundAssignOperator>(e));931 }932 case Expr::CallExprClass:933 case Expr::CXXMemberCallExprClass:934 case Expr::CXXOperatorCallExprClass:935 case Expr::UserDefinedLiteralClass:936 return emitCallExprLValue(cast<CallExpr>(e));937 case Expr::ExprWithCleanupsClass: {938 const auto *cleanups = cast<ExprWithCleanups>(e);939 RunCleanupsScope scope(*this);940 LValue lv = emitLValue(cleanups->getSubExpr());941 assert(!cir::MissingFeatures::cleanupWithPreservedValues());942 return lv;943 }944 case Expr::CXXDefaultArgExprClass: {945 auto *dae = cast<CXXDefaultArgExpr>(e);946 CXXDefaultArgExprScope scope(*this, dae);947 return emitLValue(dae->getExpr());948 }949 case Expr::ParenExprClass:950 return emitLValue(cast<ParenExpr>(e)->getSubExpr());951 case Expr::GenericSelectionExprClass:952 return emitLValue(cast<GenericSelectionExpr>(e)->getResultExpr());953 case Expr::DeclRefExprClass:954 return emitDeclRefLValue(cast<DeclRefExpr>(e));955 case Expr::CStyleCastExprClass:956 case Expr::CXXStaticCastExprClass:957 case Expr::CXXDynamicCastExprClass:958 case Expr::ImplicitCastExprClass:959 return emitCastLValue(cast<CastExpr>(e));960 case Expr::MaterializeTemporaryExprClass:961 return emitMaterializeTemporaryExpr(cast<MaterializeTemporaryExpr>(e));962 case Expr::OpaqueValueExprClass:963 return emitOpaqueValueLValue(cast<OpaqueValueExpr>(e));964 case Expr::ChooseExprClass:965 return emitLValue(cast<ChooseExpr>(e)->getChosenSubExpr());966 }967}968 969static std::string getVersionedTmpName(llvm::StringRef name, unsigned cnt) {970 SmallString<256> buffer;971 llvm::raw_svector_ostream out(buffer);972 out << name << cnt;973 return std::string(out.str());974}975 976std::string CIRGenFunction::getCounterRefTmpAsString() {977 return getVersionedTmpName("ref.tmp", counterRefTmp++);978}979 980std::string CIRGenFunction::getCounterAggTmpAsString() {981 return getVersionedTmpName("agg.tmp", counterAggTmp++);982}983 984void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr,985 QualType ty) {986 // Ignore empty classes in C++.987 if (getLangOpts().CPlusPlus)988 if (const auto *rd = ty->getAsCXXRecordDecl(); rd && rd->isEmpty())989 return;990 991 // Cast the dest ptr to the appropriate i8 pointer type.992 if (builder.isInt8Ty(destPtr.getElementType())) {993 cgm.errorNYI(loc, "Cast the dest ptr to the appropriate i8 pointer type");994 }995 996 // Get size and alignment info for this aggregate.997 const CharUnits size = getContext().getTypeSizeInChars(ty);998 if (size.isZero()) {999 // But note that getTypeInfo returns 0 for a VLA.1000 if (isa<VariableArrayType>(getContext().getAsArrayType(ty))) {1001 cgm.errorNYI(loc,1002 "emitNullInitialization for zero size VariableArrayType");1003 } else {1004 return;1005 }1006 }1007 1008 // If the type contains a pointer to data member we can't memset it to zero.1009 // Instead, create a null constant and copy it to the destination.1010 // TODO: there are other patterns besides zero that we can usefully memset,1011 // like -1, which happens to be the pattern used by member-pointers.1012 if (!cgm.getTypes().isZeroInitializable(ty)) {1013 cgm.errorNYI(loc, "type is not zero initializable");1014 }1015 1016 // In LLVM Codegen: otherwise, just memset the whole thing to zero using1017 // Builder.CreateMemSet. In CIR just emit a store of #cir.zero to the1018 // respective address.1019 // Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, false);1020 const mlir::Value zeroValue = builder.getNullValue(convertType(ty), loc);1021 builder.createStore(loc, zeroValue, destPtr);1022}1023 1024// TODO(cir): should be shared with LLVM codegen.1025bool CIRGenFunction::shouldNullCheckClassCastValue(const CastExpr *ce) {1026 const Expr *e = ce->getSubExpr();1027 1028 if (ce->getCastKind() == CK_UncheckedDerivedToBase)1029 return false;1030 1031 if (isa<CXXThisExpr>(e->IgnoreParens())) {1032 // We always assume that 'this' is never null.1033 return false;1034 }1035 1036 if (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(ce)) {1037 // And that glvalue casts are never null.1038 if (ice->isGLValue())1039 return false;1040 }1041 1042 return true;1043}1044 1045/// Computes the length of an array in elements, as well as the base1046/// element type and a properly-typed first element pointer.1047mlir::Value1048CIRGenFunction::emitArrayLength(const clang::ArrayType *origArrayType,1049 QualType &baseType, Address &addr) {1050 const clang::ArrayType *arrayType = origArrayType;1051 1052 // If it's a VLA, we have to load the stored size. Note that1053 // this is the size of the VLA in bytes, not its size in elements.1054 if (isa<VariableArrayType>(arrayType)) {1055 assert(cir::MissingFeatures::vlas());1056 cgm.errorNYI(*currSrcLoc, "VLAs");1057 return builder.getConstInt(*currSrcLoc, sizeTy, 0);1058 }1059 1060 uint64_t countFromCLAs = 1;1061 QualType eltType;1062 1063 auto cirArrayType = mlir::dyn_cast<cir::ArrayType>(addr.getElementType());1064 1065 while (cirArrayType) {1066 assert(isa<ConstantArrayType>(arrayType));1067 countFromCLAs *= cirArrayType.getSize();1068 eltType = arrayType->getElementType();1069 1070 cirArrayType =1071 mlir::dyn_cast<cir::ArrayType>(cirArrayType.getElementType());1072 1073 arrayType = getContext().getAsArrayType(arrayType->getElementType());1074 assert((!cirArrayType || arrayType) &&1075 "CIR and Clang types are out-of-sync");1076 }1077 1078 if (arrayType) {1079 // From this point onwards, the Clang array type has been emitted1080 // as some other type (probably a packed struct). Compute the array1081 // size, and just emit the 'begin' expression as a bitcast.1082 cgm.errorNYI(*currSrcLoc, "length for non-array underlying types");1083 }1084 1085 baseType = eltType;1086 return builder.getConstInt(*currSrcLoc, sizeTy, countFromCLAs);1087}1088 1089mlir::Value CIRGenFunction::emitAlignmentAssumption(1090 mlir::Value ptrValue, QualType ty, SourceLocation loc,1091 SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue) {1092 assert(!cir::MissingFeatures::sanitizers());1093 return cir::AssumeAlignedOp::create(builder, getLoc(assumptionLoc), ptrValue,1094 alignment, offsetValue);1095}1096 1097mlir::Value CIRGenFunction::emitAlignmentAssumption(1098 mlir::Value ptrValue, const Expr *expr, SourceLocation assumptionLoc,1099 int64_t alignment, mlir::Value offsetValue) {1100 QualType ty = expr->getType();1101 SourceLocation loc = expr->getExprLoc();1102 return emitAlignmentAssumption(ptrValue, ty, loc, assumptionLoc, alignment,1103 offsetValue);1104}1105 1106CIRGenFunction::VlaSizePair CIRGenFunction::getVLASize(QualType type) {1107 const VariableArrayType *vla =1108 cgm.getASTContext().getAsVariableArrayType(type);1109 assert(vla && "type was not a variable array type!");1110 return getVLASize(vla);1111}1112 1113CIRGenFunction::VlaSizePair1114CIRGenFunction::getVLASize(const VariableArrayType *type) {1115 // The number of elements so far; always size_t.1116 mlir::Value numElements;1117 1118 QualType elementType;1119 do {1120 elementType = type->getElementType();1121 mlir::Value vlaSize = vlaSizeMap[type->getSizeExpr()];1122 assert(vlaSize && "no size for VLA!");1123 assert(vlaSize.getType() == sizeTy);1124 1125 if (!numElements) {1126 numElements = vlaSize;1127 } else {1128 // It's undefined behavior if this wraps around, so mark it that way.1129 // FIXME: Teach -fsanitize=undefined to trap this.1130 1131 numElements =1132 builder.createMul(numElements.getLoc(), numElements, vlaSize,1133 cir::OverflowBehavior::NoUnsignedWrap);1134 }1135 } while ((type = getContext().getAsVariableArrayType(elementType)));1136 1137 assert(numElements && "Undefined elements number");1138 return {numElements, elementType};1139}1140 1141CIRGenFunction::VlaSizePair1142CIRGenFunction::getVLAElements1D(const VariableArrayType *vla) {1143 mlir::Value vlaSize = vlaSizeMap[vla->getSizeExpr()];1144 assert(vlaSize && "no size for VLA!");1145 assert(vlaSize.getType() == sizeTy);1146 return {vlaSize, vla->getElementType()};1147}1148 1149// TODO(cir): Most of this function can be shared between CIRGen1150// and traditional LLVM codegen1151void CIRGenFunction::emitVariablyModifiedType(QualType type) {1152 assert(type->isVariablyModifiedType() &&1153 "Must pass variably modified type to EmitVLASizes!");1154 1155 // We're going to walk down into the type and look for VLA1156 // expressions.1157 do {1158 assert(type->isVariablyModifiedType());1159 1160 const Type *ty = type.getTypePtr();1161 switch (ty->getTypeClass()) {1162 case Type::CountAttributed:1163 case Type::PackIndexing:1164 case Type::ArrayParameter:1165 case Type::HLSLAttributedResource:1166 case Type::HLSLInlineSpirv:1167 case Type::PredefinedSugar:1168 cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType");1169 break;1170 1171#define TYPE(Class, Base)1172#define ABSTRACT_TYPE(Class, Base)1173#define NON_CANONICAL_TYPE(Class, Base)1174#define DEPENDENT_TYPE(Class, Base) case Type::Class:1175#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)1176#include "clang/AST/TypeNodes.inc"1177 llvm_unreachable(1178 "dependent type must be resolved before the CIR codegen");1179 1180 // These types are never variably-modified.1181 case Type::Builtin:1182 case Type::Complex:1183 case Type::Vector:1184 case Type::ExtVector:1185 case Type::ConstantMatrix:1186 case Type::Record:1187 case Type::Enum:1188 case Type::Using:1189 case Type::TemplateSpecialization:1190 case Type::ObjCTypeParam:1191 case Type::ObjCObject:1192 case Type::ObjCInterface:1193 case Type::ObjCObjectPointer:1194 case Type::BitInt:1195 llvm_unreachable("type class is never variably-modified!");1196 1197 case Type::Adjusted:1198 type = cast<clang::AdjustedType>(ty)->getAdjustedType();1199 break;1200 1201 case Type::Decayed:1202 type = cast<clang::DecayedType>(ty)->getPointeeType();1203 break;1204 1205 case Type::Pointer:1206 type = cast<clang::PointerType>(ty)->getPointeeType();1207 break;1208 1209 case Type::BlockPointer:1210 type = cast<clang::BlockPointerType>(ty)->getPointeeType();1211 break;1212 1213 case Type::LValueReference:1214 case Type::RValueReference:1215 type = cast<clang::ReferenceType>(ty)->getPointeeType();1216 break;1217 1218 case Type::MemberPointer:1219 type = cast<clang::MemberPointerType>(ty)->getPointeeType();1220 break;1221 1222 case Type::ConstantArray:1223 case Type::IncompleteArray:1224 // Losing element qualification here is fine.1225 type = cast<clang::ArrayType>(ty)->getElementType();1226 break;1227 1228 case Type::VariableArray: {1229 // Losing element qualification here is fine.1230 const VariableArrayType *vat = cast<clang::VariableArrayType>(ty);1231 1232 // Unknown size indication requires no size computation.1233 // Otherwise, evaluate and record it.1234 if (const Expr *sizeExpr = vat->getSizeExpr()) {1235 // It's possible that we might have emitted this already,1236 // e.g. with a typedef and a pointer to it.1237 mlir::Value &entry = vlaSizeMap[sizeExpr];1238 if (!entry) {1239 mlir::Value size = emitScalarExpr(sizeExpr);1240 assert(!cir::MissingFeatures::sanitizers());1241 1242 // Always zexting here would be wrong if it weren't1243 // undefined behavior to have a negative bound.1244 // FIXME: What about when size's type is larger than size_t?1245 entry = builder.createIntCast(size, sizeTy);1246 }1247 }1248 type = vat->getElementType();1249 break;1250 }1251 1252 case Type::FunctionProto:1253 case Type::FunctionNoProto:1254 type = cast<clang::FunctionType>(ty)->getReturnType();1255 break;1256 1257 case Type::Paren:1258 case Type::TypeOf:1259 case Type::UnaryTransform:1260 case Type::Attributed:1261 case Type::BTFTagAttributed:1262 case Type::SubstTemplateTypeParm:1263 case Type::MacroQualified:1264 // Keep walking after single level desugaring.1265 type = type.getSingleStepDesugaredType(getContext());1266 break;1267 1268 case Type::Typedef:1269 case Type::Decltype:1270 case Type::Auto:1271 case Type::DeducedTemplateSpecialization:1272 // Stop walking: nothing to do.1273 return;1274 1275 case Type::TypeOfExpr:1276 // Stop walking: emit typeof expression.1277 emitIgnoredExpr(cast<clang::TypeOfExprType>(ty)->getUnderlyingExpr());1278 return;1279 1280 case Type::Atomic:1281 type = cast<clang::AtomicType>(ty)->getValueType();1282 break;1283 1284 case Type::Pipe:1285 type = cast<clang::PipeType>(ty)->getElementType();1286 break;1287 }1288 } while (type->isVariablyModifiedType());1289}1290 1291Address CIRGenFunction::emitVAListRef(const Expr *e) {1292 if (getContext().getBuiltinVaListType()->isArrayType())1293 return emitPointerWithAlignment(e);1294 return emitLValue(e).getAddress();1295}1296 1297} // namespace clang::CIRGen1298