Skip to content

Commit acbc2bb

Browse files
sitio-coutolanza
authored andcommitted
[CIR][CIRGen] Static initialize global addresses
Global addresses are constant, so we can initialize them at compile time using CIR's global_view attribute. This patch adds codegen support for the initialization of variables with constant global addresses. Since a builder method was added for global_view, the patch also updates the codegen of global variables to use it wherever possible. ghstack-source-id: 513365c Pull Request resolved: #204
1 parent 1808952 commit acbc2bb

File tree

7 files changed

+91
-25
lines changed

7 files changed

+91
-25
lines changed

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"
@@ -999,16 +1000,16 @@ namespace {
9991000
/// A struct which can be used to peephole certain kinds of finalization
10001001
/// that normally happen during l-value emission.
10011002
struct ConstantLValue {
1002-
using SymbolTy = mlir::SymbolRefAttr;
1003-
llvm::PointerUnion<mlir::Value, SymbolTy> Value;
1003+
llvm::PointerUnion<mlir::Value, mlir::Attribute> Value;
10041004
bool HasOffsetApplied;
10051005

10061006
/*implicit*/ ConstantLValue(mlir::Value value, bool hasOffsetApplied = false)
10071007
: Value(value), HasOffsetApplied(hasOffsetApplied) {}
10081008

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

10111011
ConstantLValue(std::nullptr_t) : ConstantLValue({}, false) {}
1012+
ConstantLValue(mlir::Attribute value) : Value(value) {}
10121013
};
10131014

10141015
/// A helper class for emitting constant l-values.
@@ -1053,10 +1054,13 @@ class ConstantLValueEmitter
10531054
/// Return the value offset.
10541055
mlir::Attribute getOffset() { llvm_unreachable("NYI"); }
10551056

1057+
// TODO(cir): create a proper interface to absctract CIR constant values.
1058+
10561059
/// Apply the value offset to the given constant.
1057-
mlir::Attribute applyOffset(mlir::Attribute C) {
1060+
ConstantLValue applyOffset(ConstantLValue &C) {
10581061
if (!hasNonZeroOffset())
10591062
return C;
1063+
10601064
// TODO(cir): use ptr_stride, or something...
10611065
llvm_unreachable("NYI");
10621066
}
@@ -1092,15 +1096,15 @@ mlir::Attribute ConstantLValueEmitter::tryEmit() {
10921096
return {};
10931097

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

10991103
// Convert to the appropriate type; this could be an lvalue for
11001104
// an integer. FIXME: performAddrSpaceCast
11011105
if (destTy.isa<mlir::cir::PointerType>()) {
1102-
if (value.is<ConstantLValue::SymbolTy>())
1103-
return value.get<ConstantLValue::SymbolTy>();
1106+
if (value.is<mlir::Attribute>())
1107+
return value.get<mlir::Attribute>();
11041108
llvm_unreachable("NYI");
11051109
}
11061110

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

11301157
// Handle typeid(T).

clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,9 +1109,8 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::BuildTypeInfo(mlir::Location loc,
11091109
if (OldGV && !OldGV.isDeclaration()) {
11101110
assert(!OldGV.hasAvailableExternallyLinkage() &&
11111111
"available_externally typeinfos not yet implemented");
1112-
return mlir::cir::GlobalViewAttr::get(
1113-
CGM.getBuilder().getUInt8PtrTy(),
1114-
mlir::FlatSymbolRefAttr::get(OldGV.getSymNameAttr()));
1112+
return CGM.getBuilder().getGlobalViewAttr(CGM.getBuilder().getUInt8PtrTy(),
1113+
OldGV);
11151114
}
11161115

11171116
// Check if there is already an external RTTI descriptor for this type.
@@ -1279,10 +1278,9 @@ void CIRGenItaniumRTTIBuilder::BuildVTablePointer(mlir::Location loc,
12791278
} else {
12801279
SmallVector<mlir::Attribute, 4> offsets{
12811280
mlir::cir::IntAttr::get(PtrDiffTy, 2)};
1282-
field = mlir::cir::GlobalViewAttr::get(
1283-
builder.getUInt8PtrTy(),
1284-
mlir::FlatSymbolRefAttr::get(VTable.getSymNameAttr()),
1285-
mlir::ArrayAttr::get(builder.getContext(), offsets));
1281+
auto indices = mlir::ArrayAttr::get(builder.getContext(), offsets);
1282+
field = CGM.getBuilder().getGlobalViewAttr(CGM.getBuilder().getUInt8PtrTy(),
1283+
VTable, indices);
12861284
}
12871285

12881286
assert(field && "expected attribute");
@@ -1351,9 +1349,7 @@ CIRGenItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(mlir::Location loc,
13511349
llvm_unreachable("NYI");
13521350
}
13531351

1354-
return mlir::cir::GlobalViewAttr::get(
1355-
builder.getUInt8PtrTy(),
1356-
mlir::FlatSymbolRefAttr::get(GV.getSymNameAttr()));
1352+
return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), GV);
13571353
}
13581354

13591355
mlir::Attribute CIRGenItaniumRTTIBuilder::BuildTypeInfo(
@@ -1378,9 +1374,8 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::BuildTypeInfo(
13781374
// for global pointers. This is very ARM64-specific.
13791375
llvm_unreachable("NYI");
13801376
} else {
1381-
TypeNameField = mlir::cir::GlobalViewAttr::get(
1382-
builder.getUInt8PtrTy(),
1383-
mlir::FlatSymbolRefAttr::get(TypeName.getSymNameAttr()));
1377+
TypeNameField =
1378+
builder.getGlobalViewAttr(builder.getUInt8PtrTy(), TypeName);
13841379
}
13851380
Fields.push_back(TypeNameField);
13861381

@@ -1545,9 +1540,7 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::BuildTypeInfo(
15451540
assert(!UnimplementedFeature::setDSOLocal());
15461541
CIRGenModule::setInitializer(GV, init);
15471542

1548-
return mlir::cir::GlobalViewAttr::get(
1549-
builder.getUInt8PtrTy(),
1550-
mlir::FlatSymbolRefAttr::get(GV.getSymNameAttr()));
1543+
return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), GV);;
15511544
}
15521545

15531546
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
@@ -700,6 +700,18 @@ mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *D, mlir::Type Ty,
700700
ptrTy, g.getSymName());
701701
}
702702

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

clang/test/CIR/CodeGen/static-vars.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,10 @@ void func2(void) {
3535
static float j;
3636
// CHECK-DAG: cir.global "private" internal @func2.j = 0.000000e+00 : f32
3737
}
38+
39+
// Should const initialize static vars with constant addresses.
40+
void func3(void) {
41+
static int var;
42+
static int *constAddr = &var;
43+
// CHECK-DAG: cir.global "private" internal @func3.constAddr = #cir.global_view<@func3.var> : !cir.ptr<!s32i>
44+
}

0 commit comments

Comments
 (0)