Skip to content

Commit 1dbe65a

Browse files
authored
[CIR] Add constant record ILE support (#155663)
This patch adds basic support for constant record initializer list expressions. There's a couple of limitations: * No zero initialized padding bytes in C mode * No bitfields * No designated initializer lists * Record alignments are not calculated, yet * ILEs of derived records don't work, yet * The constant attribute is not propagated to the backend, resulting in non-constants being emitted in the LLVM IR
1 parent 5a0be9b commit 1dbe65a

File tree

14 files changed

+837
-24
lines changed

14 files changed

+837
-24
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,14 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
227227
return cir::AllocaOp::create(*this, loc, addrType, type, name, alignment);
228228
}
229229

230+
/// Get constant address of a global variable as an MLIR attribute.
231+
/// This wrapper infers the attribute type through the global op.
232+
cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp,
233+
mlir::ArrayAttr indices = {}) {
234+
cir::PointerType type = getPointerTo(globalOp.getSymType());
235+
return getGlobalViewAttr(type, globalOp, indices);
236+
}
237+
230238
/// Get constant address of a global variable as an MLIR attribute.
231239
cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type,
232240
cir::GlobalOp globalOp,

clang/include/clang/CIR/Dialect/IR/CIRDataLayout.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class CIRDataLayout {
3636
bool isBigEndian() const { return bigEndian; }
3737

3838
/// Internal helper method that returns requested alignment for type.
39-
llvm::Align getAlignment(mlir::Type ty, bool abiOrPref) const;
39+
llvm::Align getAlignment(mlir::Type ty, bool useABIAlign) const;
4040

4141
llvm::Align getABITypeAlign(mlir::Type ty) const {
4242
return getAlignment(ty, true);

clang/include/clang/CIR/Dialect/IR/CIRTypes.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,8 @@ def CIR_RecordType : CIR_Type<"Record", "record", [
643643
uint64_t getElementOffset(const mlir::DataLayout &dataLayout,
644644
unsigned idx) const;
645645

646+
bool isLayoutIdentical(const RecordType &other);
647+
646648
private:
647649
unsigned computeStructSize(const mlir::DataLayout &dataLayout) const;
648650
uint64_t computeStructAlignment(const mlir::DataLayout &dataLayout) const;

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ struct MissingFeatures {
133133
static bool skippedLayout() { return false; }
134134
static bool astRecordDeclAttr() { return false; }
135135
static bool recordZeroInit() { return false; }
136+
static bool recordZeroInitPadding() { return false; }
136137
static bool zeroSizeRecordMembers() { return false; }
137138

138139
// Various handling of deferred processing in CIRGenModule.

clang/lib/CIR/CodeGen/CIRGenBuilder.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "CIRGenBuilder.h"
10+
#include "mlir/IR/BuiltinAttributes.h"
11+
#include "clang/CIR/MissingFeatures.h"
12+
#include "llvm/ADT/ArrayRef.h"
1013
#include "llvm/ADT/TypeSwitch.h"
1114

1215
using namespace clang::CIRGen;
@@ -130,6 +133,39 @@ void CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset(
130133
computeGlobalViewIndicesFromFlatOffset(offset, subType, layout, indices);
131134
}
132135

136+
cir::RecordType clang::CIRGen::CIRGenBuilderTy::getCompleteRecordType(
137+
mlir::ArrayAttr fields, bool packed, bool padded, llvm::StringRef name) {
138+
assert(!cir::MissingFeatures::astRecordDeclAttr());
139+
llvm::SmallVector<mlir::Type> members;
140+
members.reserve(fields.size());
141+
llvm::transform(fields, std::back_inserter(members),
142+
[](mlir::Attribute attr) {
143+
return mlir::cast<mlir::TypedAttr>(attr).getType();
144+
});
145+
146+
if (name.empty())
147+
return getAnonRecordTy(members, packed, padded);
148+
149+
return getCompleteNamedRecordType(members, packed, padded, name);
150+
}
151+
152+
mlir::Attribute clang::CIRGen::CIRGenBuilderTy::getConstRecordOrZeroAttr(
153+
mlir::ArrayAttr arrayAttr, bool packed, bool padded, mlir::Type type) {
154+
auto recordTy = mlir::cast_or_null<cir::RecordType>(type);
155+
156+
// Record type not specified: create anon record type from members.
157+
if (!recordTy) {
158+
recordTy = getCompleteRecordType(arrayAttr, packed, padded);
159+
}
160+
161+
// Return zero or anonymous constant record.
162+
const bool isZero = llvm::all_of(
163+
arrayAttr, [&](mlir::Attribute a) { return isNullValue(a); });
164+
if (isZero)
165+
return cir::ZeroAttr::get(recordTy);
166+
return cir::ConstRecordAttr::get(recordTy, arrayAttr);
167+
}
168+
133169
// This can't be defined in Address.h because that file is included by
134170
// CIRGenBuilder.h
135171
Address Address::withElementType(CIRGenBuilderTy &builder,

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
#include "Address.h"
1313
#include "CIRGenRecordLayout.h"
1414
#include "CIRGenTypeCache.h"
15+
#include "mlir/IR/Attributes.h"
16+
#include "mlir/IR/BuiltinAttributes.h"
17+
#include "mlir/Support/LLVM.h"
1518
#include "clang/CIR/Dialect/IR/CIRDataLayout.h"
16-
#include "clang/CIR/Interfaces/CIRTypeInterfaces.h"
1719
#include "clang/CIR/MissingFeatures.h"
1820

1921
#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
@@ -60,6 +62,16 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
6062
trailingZerosNum);
6163
}
6264

65+
cir::ConstArrayAttr getConstArray(mlir::Attribute attrs,
66+
cir::ArrayType arrayTy) const {
67+
return cir::ConstArrayAttr::get(arrayTy, attrs);
68+
}
69+
70+
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr,
71+
bool packed = false,
72+
bool padded = false,
73+
mlir::Type type = {});
74+
6375
cir::ConstRecordAttr getAnonConstRecord(mlir::ArrayAttr arrayAttr,
6476
bool packed = false,
6577
bool padded = false,
@@ -126,9 +138,9 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
126138
///
127139
/// If a record already exists and is complete, but the client tries to fetch
128140
/// it with a different set of attributes, this method will crash.
129-
cir::RecordType getCompleteRecordTy(llvm::ArrayRef<mlir::Type> members,
130-
llvm::StringRef name, bool packed,
131-
bool padded) {
141+
cir::RecordType getCompleteNamedRecordType(llvm::ArrayRef<mlir::Type> members,
142+
bool packed, bool padded,
143+
llvm::StringRef name) {
132144
const auto nameAttr = getStringAttr(name);
133145
auto kind = cir::RecordType::RecordKind::Struct;
134146
assert(!cir::MissingFeatures::astRecordDeclAttr());
@@ -150,6 +162,11 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
150162
return type;
151163
}
152164

165+
cir::RecordType getCompleteRecordType(mlir::ArrayAttr fields,
166+
bool packed = false,
167+
bool padded = false,
168+
llvm::StringRef name = "");
169+
153170
/// Get an incomplete CIR struct type. If we have a complete record
154171
/// declaration, we may create an incomplete type and then add the
155172
/// members, so \p rd here may be complete.

clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ class ConstantEmitter {
8181
// side effects, or emitting an initialization that requires a
8282
// reference to its current location.
8383
mlir::Attribute emitForMemory(mlir::Attribute c, QualType destType);
84+
static mlir::Attribute emitForMemory(CIRGenModule &cgm, mlir::Attribute c,
85+
clang::QualType destTy);
86+
87+
mlir::Attribute emitNullForMemory(mlir::Location loc, QualType t) {
88+
return emitNullForMemory(loc, cgm, t);
89+
}
90+
static mlir::Attribute emitNullForMemory(mlir::Location loc,
91+
CIRGenModule &cgm, QualType t);
8492

8593
/// Try to emit the initializer of the given declaration as an abstract
8694
/// constant.
@@ -104,7 +112,9 @@ class ConstantEmitter {
104112

105113
mlir::TypedAttr tryEmitPrivate(const Expr *e, QualType destType);
106114
mlir::Attribute tryEmitPrivate(const APValue &value, QualType destType);
107-
mlir::Attribute tryEmitPrivateForMemory(const APValue &value, QualType t);
115+
mlir::Attribute tryEmitPrivateForMemory(const Expr *e, QualType destTy);
116+
mlir::Attribute tryEmitPrivateForMemory(const APValue &value,
117+
QualType destTy);
108118

109119
private:
110120
#ifndef NDEBUG

0 commit comments

Comments
 (0)