brintos

brintos / llvm-project-archived public Read only

0
0
Text · 47.1 KiB · 22128ed Raw
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