Skip to content

Commit 614adaa

Browse files
committed
Update on "[CIR][Bugfix] Fix cir.array getTypeSizeInBits method"
Constant initialization of static local arrays would fail due to a mismatch between the variable and the initializer type size. This patch fixes the data layout interface implementation for the cir.array type. A complete array in C/C++ should have its type size in bits equal to the size of the array times the size of the element type. [ghstack-poisoned]
2 parents d0a1d1e + 80c64d2 commit 614adaa

File tree

12 files changed

+123
-33
lines changed

12 files changed

+123
-33
lines changed

clang-tools-extra/clang-tidy/cir-tidy/CIRASTConsumer.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include "CIRChecks.h"
1111

1212
#include "../utils/OptionsUtils.h"
13-
#include "ClangTidyCheck.h"
1413
#include "mlir/IR/BuiltinOps.h"
1514
#include "mlir/IR/MLIRContext.h"
1615
#include "mlir/Pass/Pass.h"
@@ -26,7 +25,16 @@ namespace tidy {
2625

2726
CIRASTConsumer::CIRASTConsumer(CompilerInstance &CI, StringRef inputFile,
2827
clang::tidy::ClangTidyContext &Context)
29-
: Context(Context) {
28+
: Context(Context),
29+
OptsView(ClangTidyCheck::OptionsView(cir::checks::LifetimeCheckName,
30+
Context.getOptions().CheckOptions,
31+
&Context)) {
32+
// Setup CIR codegen options via config specified information.
33+
CI.getCodeGenOpts().ClangIRBuildDeferredThreshold =
34+
OptsView.get("CodeGenBuildDeferredThreshold", 500U);
35+
CI.getCodeGenOpts().ClangIRSkipFunctionsFromSystemHeaders =
36+
OptsView.get("CodeGenSkipFunctionsFromSystemHeaders", false);
37+
3038
Gen = std::make_unique<CIRGenerator>(CI.getDiagnostics(), nullptr,
3139
CI.getCodeGenOpts());
3240
}
@@ -138,10 +146,6 @@ void CIRASTConsumer::HandleTranslationUnit(ASTContext &C) {
138146
mlir::PassManager pm(mlirCtx.get());
139147
pm.addPass(mlir::createMergeCleanupsPass());
140148

141-
clang::tidy::ClangTidyOptions Opts = Context.getOptions();
142-
ClangTidyCheck::OptionsView OptsView(cir::checks::LifetimeCheckName,
143-
Opts.CheckOptions, &Context);
144-
145149
auto remarks =
146150
utils::options::parseStringList(OptsView.get("RemarksList", ""));
147151
auto hist =

clang-tools-extra/clang-tidy/cir-tidy/CIRASTConsumer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "../ClangTidyDiagnosticConsumer.h"
2+
#include "ClangTidyCheck.h"
23
#include "clang/AST/ASTContext.h"
34
#include "clang/CIR/CIRGenerator.h"
45
#include "clang/Frontend/CompilerInstance.h"
@@ -19,6 +20,7 @@ class CIRASTConsumer : public ASTConsumer {
1920
std::unique_ptr<CIRGenerator> Gen;
2021
ASTContext *AstContext{nullptr};
2122
clang::tidy::ClangTidyContext &Context;
23+
clang::tidy::ClangTidyCheck::OptionsView OptsView;
2224
};
2325
} // namespace tidy
2426
} // namespace cir

clang-tools-extra/test/cir-tidy/lifetime-basic.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// RUN: -config='{CheckOptions: \
44
// RUN: [{key: cir-lifetime-check.RemarksList, value: "all"}, \
55
// RUN: {key: cir-lifetime-check.HistLimit, value: "1"}, \
6+
// RUN: {key: cir-lifetime-check.CodeGenBuildDeferredThreshold, value: "500"}, \
7+
// RUN: {key: cir-lifetime-check.CodeGenSkipFunctionsFromSystemHeaders, value: "false"}, \
68
// RUN: {key: cir-lifetime-check.HistoryList, value: "invalid;null"}]}' \
79
// RUN: --
810
// RUN: FileCheck -input-file=%t.yaml -check-prefix=CHECK-YAML %s

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,23 @@ class CIRGenBuilderTy : public mlir::OpBuilder {
102102
// Attribute helpers
103103
// -----------------
104104
//
105+
106+
/// Get constant address of a global variable as an MLIR attribute.
107+
/// This wrapper infers the attribute type through the global op.
108+
mlir::cir::GlobalViewAttr getGlobalViewAttr(mlir::cir::GlobalOp globalOp,
109+
mlir::ArrayAttr indices = {}) {
110+
auto type = getPointerTo(globalOp.getSymType());
111+
return getGlobalViewAttr(type, globalOp, indices);
112+
}
113+
114+
/// Get constant address of a global variable as an MLIR attribute.
115+
mlir::cir::GlobalViewAttr getGlobalViewAttr(mlir::cir::PointerType type,
116+
mlir::cir::GlobalOp globalOp,
117+
mlir::ArrayAttr indices = {}) {
118+
auto symbol = mlir::FlatSymbolRefAttr::get(globalOp.getSymNameAttr());
119+
return mlir::cir::GlobalViewAttr::get(type, symbol, indices);
120+
}
121+
105122
mlir::TypedAttr getZeroAttr(mlir::Type t) {
106123
return mlir::cir::ZeroAttr::get(getContext(), t);
107124
}

clang/lib/CIR/CodeGen/CIRGenExprConst.cpp

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "CIRGenModule.h"
1818
#include "mlir/IR/Attributes.h"
1919
#include "mlir/IR/BuiltinAttributeInterfaces.h"
20+
#include "mlir/IR/BuiltinAttributes.h"
2021
#include "clang/AST/APValue.h"
2122
#include "clang/AST/ASTContext.h"
2223
#include "clang/AST/Attr.h"
@@ -996,16 +997,16 @@ namespace {
996997
/// A struct which can be used to peephole certain kinds of finalization
997998
/// that normally happen during l-value emission.
998999
struct ConstantLValue {
999-
using SymbolTy = mlir::SymbolRefAttr;
1000-
llvm::PointerUnion<mlir::Value, SymbolTy> Value;
1000+
llvm::PointerUnion<mlir::Value, mlir::Attribute> Value;
10011001
bool HasOffsetApplied;
10021002

10031003
/*implicit*/ ConstantLValue(mlir::Value value, bool hasOffsetApplied = false)
10041004
: Value(value), HasOffsetApplied(hasOffsetApplied) {}
10051005

1006-
/*implicit*/ ConstantLValue(SymbolTy address) : Value(address) {}
1006+
/*implicit*/ ConstantLValue(mlir::SymbolRefAttr address) : Value(address) {}
10071007

10081008
ConstantLValue(std::nullptr_t) : ConstantLValue({}, false) {}
1009+
ConstantLValue(mlir::Attribute value) : Value(value) {}
10091010
};
10101011

10111012
/// A helper class for emitting constant l-values.
@@ -1050,10 +1051,13 @@ class ConstantLValueEmitter
10501051
/// Return the value offset.
10511052
mlir::Attribute getOffset() { llvm_unreachable("NYI"); }
10521053

1054+
// TODO(cir): create a proper interface to absctract CIR constant values.
1055+
10531056
/// Apply the value offset to the given constant.
1054-
mlir::Attribute applyOffset(mlir::Attribute C) {
1057+
ConstantLValue applyOffset(ConstantLValue &C) {
10551058
if (!hasNonZeroOffset())
10561059
return C;
1060+
10571061
// TODO(cir): use ptr_stride, or something...
10581062
llvm_unreachable("NYI");
10591063
}
@@ -1089,15 +1093,15 @@ mlir::Attribute ConstantLValueEmitter::tryEmit() {
10891093
return {};
10901094

10911095
// Apply the offset if necessary and not already done.
1092-
if (!result.HasOffsetApplied && !value.is<ConstantLValue::SymbolTy>()) {
1093-
assert(0 && "NYI");
1096+
if (!result.HasOffsetApplied && !value.is<mlir::Attribute>()) {
1097+
value = applyOffset(result).Value;
10941098
}
10951099

10961100
// Convert to the appropriate type; this could be an lvalue for
10971101
// an integer. FIXME: performAddrSpaceCast
10981102
if (destTy.isa<mlir::cir::PointerType>()) {
1099-
if (value.is<ConstantLValue::SymbolTy>())
1100-
return value.get<ConstantLValue::SymbolTy>();
1103+
if (value.is<mlir::Attribute>())
1104+
return value.get<mlir::Attribute>();
11011105
llvm_unreachable("NYI");
11021106
}
11031107

@@ -1121,7 +1125,30 @@ ConstantLValue
11211125
ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
11221126
// Handle values.
11231127
if (const ValueDecl *D = base.dyn_cast<const ValueDecl *>()) {
1124-
assert(0 && "NYI");
1128+
// The constant always points to the canonical declaration. We want to look
1129+
// at properties of the most recent declaration at the point of emission.
1130+
D = cast<ValueDecl>(D->getMostRecentDecl());
1131+
1132+
if (D->hasAttr<WeakRefAttr>())
1133+
llvm_unreachable("emit pointer base for weakref is NYI");
1134+
1135+
if (auto *FD = dyn_cast<FunctionDecl>(D))
1136+
llvm_unreachable("emit pointer base for fun decl is NYI");
1137+
1138+
if (auto *VD = dyn_cast<VarDecl>(D)) {
1139+
// We can never refer to a variable with local storage.
1140+
if (!VD->hasLocalStorage()) {
1141+
if (VD->isFileVarDecl() || VD->hasExternalStorage())
1142+
return CGM.getAddrOfGlobalVarAttr(VD);
1143+
1144+
if (VD->isLocalVarDecl()) {
1145+
auto linkage =
1146+
CGM.getCIRLinkageVarDefinition(VD, /*IsConstant=*/false);
1147+
return CGM.getBuilder().getGlobalViewAttr(
1148+
CGM.getOrCreateStaticVarDecl(*VD, linkage));
1149+
}
1150+
}
1151+
}
11251152
}
11261153

11271154
// Handle typeid(T).

clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,9 +1107,8 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::BuildTypeInfo(mlir::Location loc,
11071107
if (OldGV && !OldGV.isDeclaration()) {
11081108
assert(!OldGV.hasAvailableExternallyLinkage() &&
11091109
"available_externally typeinfos not yet implemented");
1110-
return mlir::cir::GlobalViewAttr::get(
1111-
CGM.getBuilder().getUInt8PtrTy(),
1112-
mlir::FlatSymbolRefAttr::get(OldGV.getSymNameAttr()));
1110+
return CGM.getBuilder().getGlobalViewAttr(CGM.getBuilder().getUInt8PtrTy(),
1111+
OldGV);
11131112
}
11141113

11151114
// Check if there is already an external RTTI descriptor for this type.
@@ -1275,10 +1274,9 @@ void CIRGenItaniumRTTIBuilder::BuildVTablePointer(mlir::Location loc,
12751274
} else {
12761275
SmallVector<mlir::Attribute, 4> offsets{
12771276
mlir::cir::IntAttr::get(PtrDiffTy, 2)};
1278-
field = mlir::cir::GlobalViewAttr::get(
1279-
builder.getUInt8PtrTy(),
1280-
mlir::FlatSymbolRefAttr::get(VTable.getSymNameAttr()),
1281-
mlir::ArrayAttr::get(builder.getContext(), offsets));
1277+
auto indices = mlir::ArrayAttr::get(builder.getContext(), offsets);
1278+
field = CGM.getBuilder().getGlobalViewAttr(CGM.getBuilder().getUInt8PtrTy(),
1279+
VTable, indices);
12821280
}
12831281

12841282
assert(field && "expected attribute");
@@ -1347,9 +1345,7 @@ CIRGenItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(mlir::Location loc,
13471345
llvm_unreachable("NYI");
13481346
}
13491347

1350-
return mlir::cir::GlobalViewAttr::get(
1351-
builder.getUInt8PtrTy(),
1352-
mlir::FlatSymbolRefAttr::get(GV.getSymNameAttr()));
1348+
return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), GV);
13531349
}
13541350

13551351
mlir::Attribute CIRGenItaniumRTTIBuilder::BuildTypeInfo(
@@ -1374,9 +1370,8 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::BuildTypeInfo(
13741370
// for global pointers. This is very ARM64-specific.
13751371
llvm_unreachable("NYI");
13761372
} else {
1377-
TypeNameField = mlir::cir::GlobalViewAttr::get(
1378-
builder.getUInt8PtrTy(),
1379-
mlir::FlatSymbolRefAttr::get(TypeName.getSymNameAttr()));
1373+
TypeNameField =
1374+
builder.getGlobalViewAttr(builder.getUInt8PtrTy(), TypeName);
13801375
}
13811376
Fields.push_back(TypeNameField);
13821377

@@ -1539,9 +1534,7 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::BuildTypeInfo(
15391534
assert(!UnimplementedFeature::setDSOLocal());
15401535
CIRGenModule::setInitializer(GV, init);
15411536

1542-
return mlir::cir::GlobalViewAttr::get(
1543-
builder.getUInt8PtrTy(),
1544-
mlir::FlatSymbolRefAttr::get(GV.getSymNameAttr()));
1537+
return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), GV);;
15451538
}
15461539

15471540
mlir::Attribute CIRGenItaniumCXXABI::getAddrOfRTTIDescriptor(mlir::Location loc,

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,18 @@ mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *D, mlir::Type Ty,
699699
ptrTy, g.getSymName());
700700
}
701701

702+
mlir::cir::GlobalViewAttr
703+
CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *D, mlir::Type Ty,
704+
ForDefinition_t IsForDefinition) {
705+
assert(D->hasGlobalStorage() && "Not a global variable");
706+
QualType ASTTy = D->getType();
707+
if (!Ty)
708+
Ty = getTypes().convertTypeForMem(ASTTy);
709+
710+
auto globalOp = buildGlobal(D, Ty, IsForDefinition);
711+
return builder.getGlobalViewAttr(builder.getPointerTo(Ty), globalOp);
712+
}
713+
702714
mlir::Operation* CIRGenModule::getWeakRefReference(const ValueDecl *VD) {
703715
const AliasAttr *AA = VD->getAttr<AliasAttr>();
704716
assert(AA && "No alias?");

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,11 @@ class CIRGenModule : public CIRGenTypeCache {
231231
getAddrOfGlobalVar(const VarDecl *D, mlir::Type Ty = {},
232232
ForDefinition_t IsForDefinition = NotForDefinition);
233233

234+
/// Return the mlir::GlobalViewAttr for the address of the given global.
235+
mlir::cir::GlobalViewAttr
236+
getAddrOfGlobalVarAttr(const VarDecl *D, mlir::Type Ty = {},
237+
ForDefinition_t IsForDefinition = NotForDefinition);
238+
234239
/// Get a reference to the target of VD.
235240
mlir::Operation* getWeakRefReference(const ValueDecl *VD);
236241

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,15 @@ class CIRGlobalOpLowering
12091209
op->getLoc(), lowerCirAttrAsValue(structAttr, op->getLoc(), rewriter,
12101210
typeConverter));
12111211
return mlir::success();
1212+
} else if (auto attr = init.value().dyn_cast<mlir::cir::GlobalViewAttr>()) {
1213+
setupRegionInitializedLLVMGlobalOp(op, rewriter);
1214+
1215+
// Return the address of the global symbol.
1216+
auto elementType = typeConverter->convertType(attr.getType());
1217+
auto addrOfOp = rewriter.create<mlir::LLVM::AddressOfOp>(
1218+
op->getLoc(), elementType, attr.getSymbol());
1219+
rewriter.create<mlir::LLVM::ReturnOp>(op->getLoc(), addrOfOp.getResult());
1220+
return mlir::success();
12121221
} else {
12131222
op.emitError() << "usupported initializer '" << init.value() << "'";
12141223
return mlir::failure();

clang/test/CIR/CodeGen/globals.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,8 @@ int testExternVar(void) { return externVar; }
115115
// CHECK: cir.global "private" external @externVar : !s32i
116116
// CHECK: cir.func @{{.+}}testExternVar
117117
// CHECK: cir.get_global @externVar : cir.ptr <!s32i>
118+
119+
// Should constant initialize global with constant address.
120+
int var = 1;
121+
int *constAddr = &var;
122+
// CHECK-DAG: cir.global external @constAddr = #cir.global_view<@var> : !cir.ptr<!s32i>

0 commit comments

Comments
 (0)