Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
90 changes: 48 additions & 42 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 @@ -198,7 +199,12 @@ static void emitDeclInit(CIRGenFunction &CGF, const VarDecl *D,
AggValueSlot::DoesNotOverlap));
return;
case cir::TEK_Scalar:
CGF.emitScalarInit(Init, CGF.getLoc(D->getLocation()), lv, false);
if (lv.isObjCStrong())
llvm_unreachable("NYI");
else if (lv.isObjCWeak())
llvm_unreachable("NYI");
else
CGF.emitScalarInit(Init, CGF.getLoc(D->getLocation()), lv, false);
return;
case cir::TEK_Complex:
llvm_unreachable("complext evaluation NYI");
Expand Down Expand Up @@ -329,57 +335,25 @@ 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);
llvm::SaveAndRestore<CIRGenFunction *> savedCGF(CurCGF, &cgf);
CurCGF->CurFn = addr;

CIRGenFunction::SourceLocRAIIObject fnLoc{cgf,
getLoc(varDecl->getLocation())};

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 @@ -395,9 +369,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 @@ -417,5 +392,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
Loading
Loading