blob: 406026b0b9f276febcc677bff971c1a7321ff1d6 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This contains code to emit Decl nodes as CIR code.
//
//===----------------------------------------------------------------------===//
#include "CIRGenFunction.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/CIR/MissingFeatures.h"
using namespace clang;
using namespace clang::CIRGen;
void CIRGenFunction::emitAutoVarAlloca(const VarDecl &d) {
QualType ty = d.getType();
if (ty.getAddressSpace() != LangAS::Default)
cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: address space");
auto loc = getLoc(d.getSourceRange());
if (d.isEscapingByref())
cgm.errorNYI(d.getSourceRange(),
"emitAutoVarDecl: decl escaping by reference");
CharUnits alignment = getContext().getDeclAlign(&d);
// If the type is variably-modified, emit all the VLA sizes for it.
if (ty->isVariablyModifiedType())
cgm.errorNYI(d.getSourceRange(), "emitAutoVarDecl: variably modified type");
Address address = Address::invalid();
if (!ty->isConstantSizeType())
cgm.errorNYI(d.getSourceRange(), "emitAutoVarDecl: non-constant size type");
// A normal fixed sized variable becomes an alloca in the entry block,
mlir::Type allocaTy = convertTypeForMem(ty);
// Create the temp alloca and declare variable using it.
address = createTempAlloca(allocaTy, alignment, loc, d.getName());
declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()), alignment);
setAddrOfLocalVar(&d, address);
}
void CIRGenFunction::emitAutoVarInit(const clang::VarDecl &d) {
QualType type = d.getType();
// If this local has an initializer, emit it now.
const Expr *init = d.getInit();
if (init || !type.isPODType(getContext())) {
cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit");
}
}
void CIRGenFunction::emitAutoVarCleanups(const clang::VarDecl &d) {
// Check the type for a cleanup.
if (d.needsDestruction(getContext()))
cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: type cleanup");
assert(!cir::MissingFeatures::opAllocaPreciseLifetime());
// Handle the cleanup attribute.
if (d.hasAttr<CleanupAttr>())
cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: CleanupAttr");
}
/// Emit code and set up symbol table for a variable declaration with auto,
/// register, or no storage class specifier. These turn into simple stack
/// objects, globals depending on target.
void CIRGenFunction::emitAutoVarDecl(const VarDecl &d) {
emitAutoVarAlloca(d);
emitAutoVarInit(d);
emitAutoVarCleanups(d);
}
void CIRGenFunction::emitVarDecl(const VarDecl &d) {
// If the declaration has external storage, don't emit it now, allow it to be
// emitted lazily on its first use.
if (d.hasExternalStorage())
return;
if (d.getStorageDuration() != SD_Automatic)
cgm.errorNYI(d.getSourceRange(), "emitVarDecl automatic storage duration");
if (d.getType().getAddressSpace() == LangAS::opencl_local)
cgm.errorNYI(d.getSourceRange(), "emitVarDecl openCL address space");
assert(d.hasLocalStorage());
assert(!cir::MissingFeatures::opAllocaVarDeclContext());
return emitAutoVarDecl(d);
}
void CIRGenFunction::emitDecl(const Decl &d) {
switch (d.getKind()) {
case Decl::Var: {
const VarDecl &vd = cast<VarDecl>(d);
assert(vd.isLocalVarDecl() &&
"Should not see file-scope variables inside a function!");
emitVarDecl(vd);
return;
}
default:
cgm.errorNYI(d.getSourceRange(), "emitDecl: unhandled decl type");
}
}