Skip to content

Commit ce55bc0

Browse files
committed
[CIR] Add constant record ILE support
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 df9965c commit ce55bc0

File tree

11 files changed

+786
-14
lines changed

11 files changed

+786
-14
lines changed

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
@@ -134,6 +134,7 @@ struct MissingFeatures {
134134
static bool astRecordDeclAttr() { return false; }
135135
static bool cxxSupport() { return false; }
136136
static bool recordZeroInit() { return false; }
137+
static bool recordZeroInitPadding() { return false; }
137138
static bool zeroSizeRecordMembers() { return false; }
138139
static bool recordLayoutVirtualBases() { return false; }
139140

clang/lib/CIR/CodeGen/CIRGenBuilder.cpp

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

99
#include "CIRGenBuilder.h"
10+
#include "mlir/IR/BuiltinAttributes.h"
11+
#include "llvm/ADT/ArrayRef.h"
1012
#include "llvm/ADT/TypeSwitch.h"
1113

1214
using namespace clang::CIRGen;
@@ -130,6 +132,44 @@ void CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset(
130132
computeGlobalViewIndicesFromFlatOffset(offset, subType, layout, indices);
131133
}
132134

135+
static mlir::Type getAttributeType(mlir::Attribute attr) {
136+
return mlir::cast<mlir::TypedAttr>(attr).getType();
137+
}
138+
139+
cir::RecordType clang::CIRGen::CIRGenBuilderTy::getCompleteRecordType(
140+
mlir::ArrayAttr fields, bool packed, bool padded, llvm::StringRef name,
141+
const clang::RecordDecl *ast) {
142+
llvm::SmallVector<mlir::Type, 8> members;
143+
members.reserve(fields.size());
144+
llvm::transform(fields, std::back_inserter(members), getAttributeType);
145+
146+
if (name.empty())
147+
return getAnonRecordTy(members, packed, padded);
148+
149+
return getCompleteRecordTy(members, name, packed, padded);
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+
llvm::SmallVector<mlir::Type, 8> members;
159+
members.reserve(arrayAttr.size());
160+
llvm::transform(arrayAttr, std::back_inserter(members), getAttributeType);
161+
recordTy = getType<cir::RecordType>(members, packed, padded,
162+
cir::RecordType::Struct);
163+
}
164+
165+
// Return zero or anonymous constant record.
166+
const bool isZero = llvm::all_of(
167+
arrayAttr, [&](mlir::Attribute a) { return isNullValue(a); });
168+
if (isZero)
169+
return cir::ZeroAttr::get(recordTy);
170+
return cir::ConstRecordAttr::get(recordTy, arrayAttr);
171+
}
172+
133173
// This can't be defined in Address.h because that file is included by
134174
// CIRGenBuilder.h
135175
Address Address::withElementType(CIRGenBuilderTy &builder,

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 19 additions & 1 deletion
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,
@@ -150,6 +162,12 @@ 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+
const clang::RecordDecl *ast = nullptr);
170+
153171
/// Get an incomplete CIR struct type. If we have a complete record
154172
/// declaration, we may create an incomplete type and then add the
155173
/// members, so \p rd here may be complete.

clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h

Lines changed: 10 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,8 @@ 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, QualType destTy);
108117

109118
private:
110119
#ifndef NDEBUG

0 commit comments

Comments
 (0)