Skip to content

Commit 58b91d1

Browse files
authored
[CIR][NFC] Upstream LValueBaseInfo handling (#134928)
Previous implementations that used the cir::LValue class omitted hanling of the LValueBaseInfo class, which tracks information about the basis for the LValue's alignment. As more code was upstreamed from the incubator, we were accumulating technical debt by adding more places where this wasn't handled correctly. This change puts the interfaces in place to track this information. The information being tracked isn't used yet, so no functional change is intended. The tracking is being added now because it will become more difficult to add it as more features are implemented.
1 parent 688c3ff commit 58b91d1

File tree

8 files changed

+89
-30
lines changed

8 files changed

+89
-30
lines changed

clang/include/clang/CIR/MissingFeatures.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,11 @@ struct MissingFeatures {
108108
static bool cgFPOptionsRAII() { return false; }
109109
static bool metaDataNode() { return false; }
110110
static bool fastMathFlags() { return false; }
111-
static bool lvalueBaseInfo() { return false; }
112111
static bool alignCXXRecordDecl() { return false; }
113112
static bool setNonGC() { return false; }
114113
static bool incrementProfileCounter() { return false; }
115114
static bool insertBuiltinUnpredictable() { return false; }
115+
static bool objCGC() { return false; }
116116

117117
// Missing types
118118
static bool dataMemberType() { return false; }

clang/lib/CIR/CodeGen/CIRGenDecl.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ void CIRGenFunction::emitAutoVarInit(
146146
// its removal/optimization to the CIR lowering.
147147
if (!constant || isa<CXXTemporaryObjectExpr>(init)) {
148148
initializeWhatIsTechnicallyUninitialized(addr);
149-
LValue lv = LValue::makeAddr(addr, type);
149+
LValue lv = makeAddrLValue(addr, type, AlignmentSource::Decl);
150150
emitExprAsInit(init, &d, lv);
151151
// In case lv has uses it means we indeed initialized something
152152
// out of it while trying to build the expression, mark it as such.
@@ -165,7 +165,7 @@ void CIRGenFunction::emitAutoVarInit(
165165
assert(typedConstant && "expected typed attribute");
166166
if (!emission.IsConstantAggregate) {
167167
// For simple scalar/complex initialization, store the value directly.
168-
LValue lv = LValue::makeAddr(addr, type);
168+
LValue lv = makeAddrLValue(addr, type);
169169
assert(init && "expected initializer");
170170
mlir::Location initLoc = getLoc(init->getSourceRange());
171171
// lv.setNonGC(true);

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ using namespace cir;
2828

2929
/// Given an expression of pointer type, try to
3030
/// derive a more accurate bound on the alignment of the pointer.
31-
Address CIRGenFunction::emitPointerWithAlignment(const Expr *expr) {
31+
Address CIRGenFunction::emitPointerWithAlignment(const Expr *expr,
32+
LValueBaseInfo *baseInfo) {
3233
// We allow this with ObjC object pointers because of fragile ABIs.
3334
assert(expr->getType()->isPointerType() ||
3435
expr->getType()->isObjCObjectPointerType());
@@ -164,7 +165,8 @@ Address CIRGenFunction::emitPointerWithAlignment(const Expr *expr) {
164165

165166
// Otherwise, use the alignment of the type.
166167
return makeNaturalAddressForPointer(
167-
emitScalarExpr(expr), expr->getType()->getPointeeType(), CharUnits());
168+
emitScalarExpr(expr), expr->getType()->getPointeeType(), CharUnits(),
169+
/*forPointeeType=*/true, baseInfo);
168170
}
169171

170172
void CIRGenFunction::emitStoreThroughLValue(RValue src, LValue dst,
@@ -300,7 +302,7 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
300302
cgm.errorNYI(vd->getSourceRange(), "emitDeclRefLValue: static local");
301303
}
302304

303-
return LValue::makeAddr(addr, ty);
305+
return makeAddrLValue(addr, ty, AlignmentSource::Type);
304306
}
305307

306308
cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type");
@@ -338,9 +340,9 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) {
338340
QualType t = e->getSubExpr()->getType()->getPointeeType();
339341
assert(!t.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
340342

341-
assert(!cir::MissingFeatures::lvalueBaseInfo());
342343
assert(!cir::MissingFeatures::opTBAA());
343-
Address addr = emitPointerWithAlignment(e->getSubExpr());
344+
LValueBaseInfo baseInfo;
345+
Address addr = emitPointerWithAlignment(e->getSubExpr(), &baseInfo);
344346

345347
// Tag 'load' with deref attribute.
346348
// FIXME: This misses some derefence cases and has problematic interactions
@@ -350,7 +352,7 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) {
350352
loadOp.setIsDerefAttr(mlir::UnitAttr::get(&getMLIRContext()));
351353
}
352354

353-
LValue lv = LValue::makeAddr(addr, t);
355+
LValue lv = makeAddrLValue(addr, t, baseInfo);
354356
assert(!cir::MissingFeatures::addressSpace());
355357
assert(!cir::MissingFeatures::setNonGC());
356358
return lv;

clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
130130
}
131131

132132
const Address address = Address(element, cirElementType, elementAlign);
133-
const LValue elementLV = LValue::makeAddr(address, elementType);
133+
const LValue elementLV = cgf.makeAddrLValue(address, elementType);
134134
emitInitializationToLValue(args[i], elementLV);
135135
}
136136

@@ -157,7 +157,7 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
157157
const Address tmpAddr = cgf.createTempAlloca(
158158
cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp",
159159
/*insertIntoFnEntryBlock=*/false);
160-
LValue tmpLV = LValue::makeAddr(tmpAddr, elementPtrType);
160+
LValue tmpLV = cgf.makeAddrLValue(tmpAddr, elementPtrType);
161161
cgf.emitStoreThroughLValue(RValue::get(element), tmpLV);
162162

163163
// TODO(CIR): Replace this part later with cir::DoWhileOp
@@ -166,7 +166,7 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
166166
builder.createLoad(loc, tmpAddr.getPointer());
167167

168168
// Emit the actual filler expression.
169-
const LValue elementLV = LValue::makeAddr(
169+
const LValue elementLV = cgf.makeAddrLValue(
170170
Address(currentElement, cirElementType, elementAlign), elementType);
171171

172172
if (arrayFiller)

clang/lib/CIR/CodeGen/CIRGenFunction.h

+15-3
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,23 @@ class CIRGenFunction : public CIRGenTypeCache {
242242
/// been signed, and the returned Address will have the pointer authentication
243243
/// information needed to authenticate the signed pointer.
244244
Address makeNaturalAddressForPointer(mlir::Value ptr, QualType t,
245-
CharUnits alignment) {
245+
CharUnits alignment,
246+
bool forPointeeType = false,
247+
LValueBaseInfo *baseInfo = nullptr) {
246248
if (alignment.isZero())
247-
alignment = cgm.getNaturalTypeAlignment(t);
249+
alignment = cgm.getNaturalTypeAlignment(t, baseInfo);
248250
return Address(ptr, convertTypeForMem(t), alignment);
249251
}
250252

253+
LValue makeAddrLValue(Address addr, QualType ty,
254+
AlignmentSource source = AlignmentSource::Type) {
255+
return makeAddrLValue(addr, ty, LValueBaseInfo(source));
256+
}
257+
258+
LValue makeAddrLValue(Address addr, QualType ty, LValueBaseInfo baseInfo) {
259+
return LValue::makeAddr(addr, ty, baseInfo);
260+
}
261+
251262
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn,
252263
cir::FuncType funcType);
253264

@@ -523,7 +534,8 @@ class CIRGenFunction : public CIRGenTypeCache {
523534
/// into the address of a local variable. In such a case, it's quite
524535
/// reasonable to just ignore the returned alignment when it isn't from an
525536
/// explicit source.
526-
Address emitPointerWithAlignment(const clang::Expr *expr);
537+
Address emitPointerWithAlignment(const clang::Expr *expr,
538+
LValueBaseInfo *baseInfo);
527539

528540
mlir::LogicalResult emitReturnStmt(const clang::ReturnStmt &s);
529541

clang/lib/CIR/CodeGen/CIRGenModule.cpp

+11-7
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,20 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
7474
builder.getStringAttr(getTriple().str()));
7575
}
7676

77-
CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t) {
77+
CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t,
78+
LValueBaseInfo *baseInfo) {
7879
assert(!cir::MissingFeatures::opTBAA());
7980

80-
// FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown. But
81-
// that doesn't return the information we need to compute BaseInfo.
81+
// FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but
82+
// that doesn't return the information we need to compute baseInfo.
8283

8384
// Honor alignment typedef attributes even on incomplete types.
8485
// We also honor them straight for C++ class types, even as pointees;
8586
// there's an expressivity gap here.
8687
if (const auto *tt = t->getAs<TypedefType>()) {
8788
if (unsigned align = tt->getDecl()->getMaxAlignment()) {
88-
assert(!cir::MissingFeatures::lvalueBaseInfo());
89+
if (baseInfo)
90+
*baseInfo = LValueBaseInfo(AlignmentSource::AttributedType);
8991
return astContext.toCharUnitsFromBits(align);
9092
}
9193
}
@@ -99,13 +101,15 @@ CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t) {
99101
// ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the
100102
// type is incomplete, so it's impossible to test. We could try to reuse
101103
// getTypeAlignIfKnown, but that doesn't return the information we need
102-
// to set BaseInfo. So just ignore the possibility that the alignment is
104+
// to set baseInfo. So just ignore the possibility that the alignment is
103105
// greater than one.
104-
assert(!cir::MissingFeatures::lvalueBaseInfo());
106+
if (baseInfo)
107+
*baseInfo = LValueBaseInfo(AlignmentSource::Type);
105108
return CharUnits::One();
106109
}
107110

108-
assert(!cir::MissingFeatures::lvalueBaseInfo());
111+
if (baseInfo)
112+
*baseInfo = LValueBaseInfo(AlignmentSource::Type);
109113

110114
CharUnits alignment;
111115
if (t.getQualifiers().hasUnaligned()) {

clang/lib/CIR/CodeGen/CIRGenModule.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "CIRGenBuilder.h"
1717
#include "CIRGenTypeCache.h"
1818
#include "CIRGenTypes.h"
19+
#include "CIRGenValue.h"
1920

2021
#include "clang/AST/CharUnits.h"
2122
#include "clang/CIR/Dialect/IR/CIRDialect.h"
@@ -91,7 +92,8 @@ class CIRGenModule : public CIRGenTypeCache {
9192

9293
/// FIXME: this could likely be a common helper and not necessarily related
9394
/// with codegen.
94-
clang::CharUnits getNaturalTypeAlignment(clang::QualType t);
95+
clang::CharUnits getNaturalTypeAlignment(clang::QualType t,
96+
LValueBaseInfo *baseInfo);
9597

9698
void emitTopLevelDecl(clang::Decl *decl);
9799

clang/lib/CIR/CodeGen/CIRGenValue.h

+46-7
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,28 @@ enum class AlignmentSource {
7575
Type
7676
};
7777

78+
/// Given that the base address has the given alignment source, what's
79+
/// our confidence in the alignment of the field?
80+
static inline AlignmentSource getFieldAlignmentSource(AlignmentSource source) {
81+
// For now, we don't distinguish fields of opaque pointers from
82+
// top-level declarations, but maybe we should.
83+
return AlignmentSource::Decl;
84+
}
85+
86+
class LValueBaseInfo {
87+
AlignmentSource alignSource;
88+
89+
public:
90+
explicit LValueBaseInfo(AlignmentSource source = AlignmentSource::Type)
91+
: alignSource(source) {}
92+
AlignmentSource getAlignmentSource() const { return alignSource; }
93+
void setAlignmentSource(AlignmentSource source) { alignSource = source; }
94+
95+
void mergeForCast(const LValueBaseInfo &info) {
96+
setAlignmentSource(info.getAlignmentSource());
97+
}
98+
};
99+
78100
class LValue {
79101
enum {
80102
Simple, // This is a normal l-value, use getAddress().
@@ -87,13 +109,26 @@ class LValue {
87109
clang::QualType type;
88110
clang::Qualifiers quals;
89111

112+
// The alignment to use when accessing this lvalue. (For vector elements,
113+
// this is the alignment of the whole vector)
114+
unsigned alignment;
90115
mlir::Value v;
91116
mlir::Type elementType;
117+
LValueBaseInfo baseInfo;
92118

93-
void initialize(clang::QualType type, clang::Qualifiers quals) {
94-
assert(!cir::MissingFeatures::lvalueBaseInfo());
119+
void initialize(clang::QualType type, clang::Qualifiers quals,
120+
clang::CharUnits alignment, LValueBaseInfo baseInfo) {
121+
assert((!alignment.isZero() || type->isIncompleteType()) &&
122+
"initializing l-value with zero alignment!");
95123
this->type = type;
96124
this->quals = quals;
125+
const unsigned maxAlign = 1U << 31;
126+
this->alignment = alignment.getQuantity() <= maxAlign
127+
? alignment.getQuantity()
128+
: maxAlign;
129+
assert(this->alignment == alignment.getQuantity() &&
130+
"Alignment exceeds allowed max!");
131+
this->baseInfo = baseInfo;
97132
}
98133

99134
public:
@@ -108,23 +143,27 @@ class LValue {
108143
mlir::Value getPointer() const { return v; }
109144

110145
clang::CharUnits getAlignment() const {
111-
// TODO: Handle alignment
112-
return clang::CharUnits::One();
146+
return clang::CharUnits::fromQuantity(alignment);
113147
}
148+
void setAlignment(clang::CharUnits a) { alignment = a.getQuantity(); }
114149

115150
Address getAddress() const {
116151
return Address(getPointer(), elementType, getAlignment());
117152
}
118153

119154
const clang::Qualifiers &getQuals() const { return quals; }
120155

121-
static LValue makeAddr(Address address, clang::QualType t) {
156+
static LValue makeAddr(Address address, clang::QualType t,
157+
LValueBaseInfo baseInfo) {
158+
// Classic codegen sets the objc gc qualifier here. That requires an
159+
// ASTContext, which is passed in from CIRGenFunction::makeAddrLValue.
160+
assert(!cir::MissingFeatures::objCGC());
161+
122162
LValue r;
123163
r.lvType = Simple;
124164
r.v = address.getPointer();
125165
r.elementType = address.getElementType();
126-
r.initialize(t, t.getQualifiers());
127-
assert(!cir::MissingFeatures::lvalueBaseInfo());
166+
r.initialize(t, t.getQualifiers(), address.getAlignment(), baseInfo);
128167
return r;
129168
}
130169
};

0 commit comments

Comments
 (0)