Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CIR][CodeGen] Support static local variables #1224

Open
wants to merge 14 commits into
base: spr/lanza/main.circodegen-static-local-variables
Choose a base branch
from
6 changes: 6 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class StructLayout;
class CIRDataLayout {
bool bigEndian = false;

unsigned defaultGlobalsAddrSpace = 0;

/// Primitive type alignment data. This is sorted by type and bit
/// width during construction.
llvm::DataLayout::PrimitiveSpec StructAlignment;
Expand Down Expand Up @@ -106,6 +108,10 @@ class CIRDataLayout {
cir::IntType::get(Ty.getContext(), getPointerTypeSizeInBits(Ty), false);
return IntTy;
}

unsigned getDefaultGlobalsAddressSpace() const {
return defaultGlobalsAddrSpace;
}
};

/// Used to lazily calculate structure layout information for a target machine,
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -2418,6 +2418,7 @@ def GlobalOp : CIR_Op<"global",
UnitAttr:$comdat,
UnitAttr:$constant,
UnitAttr:$dsolocal,
UnitAttr:$static_local,
OptionalAttr<I64Attr>:$alignment,
OptionalAttr<ASTVarDeclInterface>:$ast,
OptionalAttr<StrAttr>:$section,
Expand Down Expand Up @@ -2503,7 +2504,9 @@ def GetGlobalOp : CIR_Op<"get_global",
```
}];

let arguments = (ins FlatSymbolRefAttr:$name, UnitAttr:$tls);
let arguments = (ins FlatSymbolRefAttr:$name,
UnitAttr:$tls,
UnitAttr:$static_local);
let results = (outs Res<CIR_PointerType, "", []>:$addr);

let assemblyFormat = [{
Expand Down
32 changes: 32 additions & 0 deletions clang/include/clang/CIR/Interfaces/ASTAttrInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,42 @@ let cppNamespace = "::cir" in {
MangleCtx->mangleDynamicInitializer($_attr.getAst(), Out);
}]
>,
InterfaceMethod<"", "void", "mangleStaticGuardVariable", (ins "llvm::raw_ostream&":$Out), [{}],
/*defaultImplementation=*/ [{
std::unique_ptr<clang::MangleContext> mangleCtx(
$_attr.getAst()->getASTContext().createMangleContext());
mangleCtx->mangleDynamicInitializer($_attr.getAst(), Out);
}]
>,
InterfaceMethod<"", "clang::VarDecl::TLSKind", "getTLSKind", (ins), [{}],
/*defaultImplementation=*/ [{
return $_attr.getAst()->getTLSKind();
}]
>,
InterfaceMethod<"", "bool", "isInline", (ins), [{}],
/*defaultImplementation=*/ [{
return $_attr.getAst()->isInline();
}]
>,
InterfaceMethod<"", "clang::TemplateSpecializationKind", "getTemplateSpecializationKind", (ins), [{}],
/*defaultImplementation=*/ [{
return $_attr.getAst()->getTemplateSpecializationKind();
}]
>,
InterfaceMethod<"", "bool", "isLocalVarDecl", (ins), [{}],
/*defaultImplementation=*/ [{
return $_attr.getAst()->isLocalVarDecl();
}]
>,
InterfaceMethod<"", "clang::SourceLocation", "getLocation", (ins), [{}],
/*defaultImplementation=*/ [{
return $_attr.getAst()->getLocation();
}]
>,
InterfaceMethod<"", "const clang::VarDecl *", "getRawDecl", (ins), [{}],
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bcardosolopes Thoughts on this? This wasn't scaling to the real world. e.g. functions that take a VarDecl as an argument.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After you latest update you can probably ditch this altogether

/*defaultImplementation=*/ [{
return $_attr.getAst();
}]
>
];
}
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ struct MissingFeatures {
static bool setFunctionAttributes() { return false; }
static bool attributeBuiltin() { return false; }
static bool attributeNoBuiltin() { return false; }
static bool functionIndexAttribute() { return false; }
static bool noUnwindAttribute() { return false; }
static bool parameterAttributes() { return false; }
static bool minLegalVectorWidthAttr() { return false; }
static bool vscaleRangeAttr() { return false; }
Expand Down Expand Up @@ -151,6 +153,7 @@ struct MissingFeatures {

// Folding methods.
static bool foldBinOpFMF() { return false; }
static bool folder() { return false; }

// Fast math.
static bool fastMathGuard() { return false; }
Expand Down Expand Up @@ -454,6 +457,10 @@ struct MissingFeatures {
static bool mustProgress() { return false; }

static bool skipTempCopy() { return false; }

static bool addressSpaceInGlobalVar() { return false; }

static bool useARMGuardVarABI() { return false; }
};

} // namespace cir
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/CIR/CodeGen/Address.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ class Address {
mlir::Type ElementType;
clang::CharUnits Alignment;

/// Offset from the base pointer. This is non-null only when the base pointer
/// is signed.
mlir::Attribute offset = nullptr;

protected:
Address(std::nullptr_t) : ElementType(nullptr) {}

Expand Down Expand Up @@ -134,6 +138,8 @@ class Address {
return *this;
}

bool hasOffset() const { return bool(offset); }

/// Get the operation which defines this address.
mlir::Operation *getDefiningOp() const {
if (!isValid())
Expand Down
60 changes: 60 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "clang/CIR/Dialect/IR/FPEnv.h"

#include "mlir/IR/Attributes.h"
#include "mlir/IR/Block.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
Expand Down Expand Up @@ -817,6 +818,35 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return Address{createImagPtr(loc, addr.getPointer()), addr.getAlignment()};
}

/// Return a boolean value testing if \p arg == 0.
mlir::Value createIsNull(mlir::Location loc, mlir::Value arg,
const llvm::Twine &name = "") {
return createICmpEQ(loc, arg, getNullValue(arg.getType(), loc), name);
}

/// Return a boolean value testing if \p arg != 0.
mlir::Value createIsNotNull(mlir::Location loc, mlir::Value arg,
const llvm::Twine &name = "") {
return createICmpNE(loc, arg, getNullValue(arg.getType(), loc), name);
}

mlir::Value createICmpEQ(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
const llvm::Twine &name = "") {
return createICmp(loc, cir::CmpOpKind::eq, lhs, rhs, name);
}
mlir::Value createICmpNE(mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
const llvm::Twine &name = "") {
return createICmp(loc, cir::CmpOpKind::ne, lhs, rhs, name);
}

mlir::Value createICmp(mlir::Location loc, cir::CmpOpKind kind,
mlir::Value lhs, mlir::Value rhs,
const llvm::Twine &name = "") {
if (cir::MissingFeatures::folder())
llvm_unreachable("NYI");
return createCompare(loc, kind, lhs, rhs);
}

/// Cast the element type of the given address to a different type,
/// preserving information like the alignment.
Address createElementBitCast(mlir::Location loc, Address addr,
Expand Down Expand Up @@ -1044,6 +1074,36 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
/// pointed to by arrayPtr.
mlir::Value maybeBuildArrayDecay(mlir::Location loc, mlir::Value arrayPtr,
mlir::Type eltTy);

/// Create an unconditional branch op.
cir::BrOp createBr(mlir::Location loc, mlir::Block *dest) {
assert(!cir::MissingFeatures::metaDataNode());
return create<cir::BrOp>(loc, dest);
}

/// Create a conditional branch operation
cir::BrCondOp createCondBr(mlir::Location loc, mlir::Value condition,
mlir::Block *trueBlock, mlir::Block *falseBlock) {
if (cir::MissingFeatures::metaDataNode())
llvm_unreachable("NYI");
return create<cir::BrCondOp>(loc, condition, trueBlock, falseBlock);
}

/// createBasicBlock - Create an MLIR block
mlir::Block *createBasicBlock(cir::FuncOp parent = nullptr,
mlir::Block *before = nullptr) {
auto *b = new mlir::Block();
if (parent) {

if (before == nullptr)
before = &*parent.end();

parent.getFunctionBody().getBlocks().insert(
mlir::Region::iterator(before), b);
}

return b;
}
};

} // namespace clang::CIRGen
Expand Down
81 changes: 41 additions & 40 deletions clang/lib/CIR/CodeGen/CIRGenCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "CIRGenModule.h"

#include "clang/AST/GlobalDecl.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
#include <cassert>
Expand Down Expand Up @@ -335,11 +336,6 @@ void CIRGenModule::emitCXXGlobalVarDeclInit(const VarDecl *varDecl,
// expects "this" in the "generic" address space.
assert(!cir::MissingFeatures::addressSpace());

if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd &&
varDecl->hasAttr<OMPThreadPrivateDeclAttr>()) {
llvm_unreachable("NYI");
}

assert(varDecl && " Expected a global declaration!");
CIRGenFunction cgf{*this, builder, true};
llvm::SaveAndRestore<CIRGenFunction *> savedCGF(CurCGF, &cgf);
Expand All @@ -350,42 +346,15 @@ void CIRGenModule::emitCXXGlobalVarDeclInit(const VarDecl *varDecl,

addr.setAstAttr(cir::ASTVarDeclAttr::get(&getMLIRContext(), varDecl));

if (ty->isReferenceType()) {
mlir::OpBuilder::InsertionGuard guard(builder);
auto *block = builder.createBlock(&addr.getCtorRegion());
CIRGenFunction::LexicalScope lexScope{*CurCGF, addr.getLoc(),
builder.getInsertionBlock()};
lexScope.setAsGlobalInit();
builder.setInsertionPointToStart(block);
auto getGlobal = builder.createGetGlobal(addr);

Address declAddr(getGlobal, getGlobal.getType(),
getASTContext().getDeclAlign(varDecl));
assert(performInit && "cannot have constant initializer which needs "
"destruction for reference");
RValue rv = cgf.emitReferenceBindingToExpr(init);
{
mlir::OpBuilder::InsertionGuard guard(builder);
mlir::Operation *rvalueDefOp = rv.getScalarVal().getDefiningOp();
if (rvalueDefOp && rvalueDefOp->getBlock()) {
mlir::Block *rvalSrcBlock = rvalueDefOp->getBlock();
if (!rvalSrcBlock->empty() && isa<cir::YieldOp>(rvalSrcBlock->back())) {
auto &front = rvalSrcBlock->front();
getGlobal.getDefiningOp()->moveBefore(&front);
auto yield = cast<cir::YieldOp>(rvalSrcBlock->back());
builder.setInsertionPoint(yield);
}
}
cgf.emitStoreOfScalar(rv.getScalarVal(), declAddr, false, ty);
if (!ty->isReferenceType()) {
if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd &&
varDecl->hasAttr<OMPThreadPrivateDeclAttr>()) {
llvm_unreachable("NYI");
}
builder.setInsertionPointToEnd(block);
builder.create<cir::YieldOp>(addr->getLoc());
} else {

bool needsDtor = varDecl->needsDestruction(getASTContext()) ==
QualType::DK_cxx_destructor;
// PerformInit, constant store invariant / destroy handled below.
bool isConstantStorage =
varDecl->getType().isConstantStorage(getASTContext(), true, !needsDtor);
if (performInit) {
mlir::OpBuilder::InsertionGuard guard(builder);
auto *block = builder.createBlock(&addr.getCtorRegion());
Expand All @@ -401,9 +370,10 @@ void CIRGenModule::emitCXXGlobalVarDeclInit(const VarDecl *varDecl,
builder.create<cir::YieldOp>(addr->getLoc());
}

if (isConstantStorage) {
// TODO: this leads to a missing feature in the moment, probably also need
// a LexicalScope to be inserted here.
if (varDecl->getType().isConstantStorage(getASTContext(), true,
!needsDtor)) {
// TODO(CIR): this leads to a missing feature in the moment, probably also
// need a LexicalScope to be inserted here.
emitDeclInvariant(cgf, varDecl);
} else {
// If not constant storage we'll emit this regardless of NeedsDtor value.
Expand All @@ -423,5 +393,36 @@ void CIRGenModule::emitCXXGlobalVarDeclInit(const VarDecl *varDecl,
} else
builder.create<cir::YieldOp>(addr->getLoc());
}
return;
}

mlir::OpBuilder::InsertionGuard guard(builder);
auto *block = builder.createBlock(&addr.getCtorRegion());
CIRGenFunction::LexicalScope lexScope{*CurCGF, addr.getLoc(),
builder.getInsertionBlock()};
lexScope.setAsGlobalInit();
builder.setInsertionPointToStart(block);
auto getGlobal = builder.createGetGlobal(addr);

Address declAddr(getGlobal, getGlobal.getType(),
getASTContext().getDeclAlign(varDecl));
assert(performInit && "cannot have constant initializer which needs "
"destruction for reference");
RValue rv = cgf.emitReferenceBindingToExpr(init);
{
mlir::OpBuilder::InsertionGuard guard(builder);
mlir::Operation *rvalueDefOp = rv.getScalarVal().getDefiningOp();
if (rvalueDefOp && rvalueDefOp->getBlock()) {
mlir::Block *rvalSrcBlock = rvalueDefOp->getBlock();
if (!rvalSrcBlock->empty() && isa<cir::YieldOp>(rvalSrcBlock->back())) {
auto &front = rvalSrcBlock->front();
getGlobal.getDefiningOp()->moveBefore(&front);
auto yield = cast<cir::YieldOp>(rvalSrcBlock->back());
builder.setInsertionPoint(yield);
}
}
cgf.emitStoreOfScalar(rv.getScalarVal(), declAddr, false, ty);
}
builder.setInsertionPointToEnd(block);
builder.create<cir::YieldOp>(addr->getLoc());
}
13 changes: 13 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenCXXABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,19 @@ class CIRGenCXXABI {
bool ForVirtualBase, bool Delegating,
Address This, QualType ThisTy) = 0;

/*************************** Static local guards ****************************/

/// Emits the guarded initializer and destructor setup for the given
/// variable, given that it couldn't be emitted as a constant.
/// If \p PerformInit is false, the initialization has been folded to a
/// constant and should not be performed.
///
/// The variable may be:
/// - a static local variable
/// - a static data member of a class template instantiation
virtual void emitGuardedInit(CIRGenFunction &cgf, const VarDecl &varDecl,
cir::GlobalOp globalOp, bool performInit) = 0;

/// Emit code to force the execution of a destructor during global
/// teardown. The default implementation of this uses atexit.
///
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//

#include "CIRGenCall.h"
#include "CIRGenBuilder.h"
#include "CIRGenCXXABI.h"
#include "CIRGenFunction.h"
Expand All @@ -19,8 +20,10 @@
#include "TargetInfo.h"

#include "clang/AST/Attr.h"
#include "clang/AST/Attrs.inc"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/CIR/ABIArgInfo.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/FnInfoOpts.h"
Expand All @@ -31,6 +34,7 @@
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Location.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/IR/Types.h"
#include "clang/CIR/MissingFeatures.h"
Expand Down Expand Up @@ -938,6 +942,13 @@ mlir::Value CIRGenFunction::emitRuntimeCall(mlir::Location loc,
return call->getResult(0);
}

mlir::Value CIRGenFunction::emitNounwindRuntimeCall(
mlir::Location loc, cir::FuncOp callee, ArrayRef<mlir::Value> args) {
mlir::Value call = emitRuntimeCall(loc, callee, args);
assert(!cir::MissingFeatures::noUnwindAttribute());
return call;
}

void CIRGenFunction::emitCallArg(CallArgList &args, const Expr *E,
QualType type) {
// TODO: Add the DisableDebugLocationUpdates helper
Expand Down
Loading
Loading