Skip to content

Commit 1ffe43b

Browse files
committed
Address review feedback
1 parent 39b2db1 commit 1ffe43b

File tree

13 files changed

+134
-93
lines changed

13 files changed

+134
-93
lines changed

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,8 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
5555

5656
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType,
5757
mlir::Type type, llvm::StringRef name,
58-
mlir::IntegerAttr alignment,
59-
mlir::Value dynAllocSize) {
60-
return create<cir::AllocaOp>(loc, addrType, type, name, alignment,
61-
dynAllocSize);
58+
mlir::IntegerAttr alignment) {
59+
return create<cir::AllocaOp>(loc, addrType, type, name, alignment);
6260
}
6361

6462
cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr,

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

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -139,25 +139,16 @@ def AllocaOp : CIR_Op<"alloca", [
139139
let description = [{
140140
The `cir.alloca` operation defines a scope-local variable.
141141

142-
The presence `init` attribute indicates that the local variable represented
143-
by this alloca was originally initialized in C/C++ source code. In such
144-
cases, the first use contains the initialization (a cir.store, a cir.call
145-
to a ctor, etc).
146-
147142
The presence of the `const` attribute indicates that the local variable is
148143
declared with C/C++ `const` keyword.
149144

150-
The `dynAllocSize` specifies the size to dynamically allocate on the stack
151-
and ignores the allocation size based on the original type. This is useful
152-
when handling VLAs and is omitted when declaring regular local variables.
153-
154145
The result type is a pointer to the input's type.
155146

156147
Example:
157148

158149
```mlir
159-
// int count = 3;
160-
%0 = cir.alloca i32, !cir.ptr<i32>, ["count", init] {alignment = 4 : i64}
150+
// int count;
151+
%0 = cir.alloca i32, !cir.ptr<i32>, ["count"] {alignment = 4 : i64}
161152

162153
// int *ptr;
163154
%1 = cir.alloca !cir.ptr<i32>, !cir.ptr<!cir.ptr<i32>>, ["ptr"] {alignment = 8 : i64}
@@ -166,7 +157,6 @@ def AllocaOp : CIR_Op<"alloca", [
166157
}];
167158

168159
let arguments = (ins
169-
Optional<PrimitiveInt>:$dynAllocSize,
170160
TypeAttr:$allocaType,
171161
StrAttr:$name,
172162
UnitAttr:$init,
@@ -180,32 +170,19 @@ def AllocaOp : CIR_Op<"alloca", [
180170

181171
let skipDefaultBuilders = 1;
182172
let builders = [
183-
OpBuilder<(ins "mlir::Type":$addr, "mlir::Type":$allocaType,
184-
"llvm::StringRef":$name,
185-
"mlir::IntegerAttr":$alignment)>,
186-
187173
OpBuilder<(ins "mlir::Type":$addr,
188174
"mlir::Type":$allocaType,
189175
"llvm::StringRef":$name,
190-
"mlir::IntegerAttr":$alignment,
191-
"mlir::Value":$dynAllocSize),
192-
[{
193-
if (dynAllocSize)
194-
$_state.addOperands(dynAllocSize);
195-
build($_builder, $_state, addr, allocaType, name, alignment);
196-
}]>
176+
"mlir::IntegerAttr":$alignment)>
197177
];
198178

199179
let extraClassDeclaration = [{
200180
// Whether the alloca input type is a pointer.
201181
bool isPointerType() { return ::mlir::isa<::cir::PointerType>(getAllocaType()); }
202-
203-
bool isDynamic() { return (bool)getDynAllocSize(); }
204182
}];
205183

206184
let assemblyFormat = [{
207185
$allocaType `,` qualified(type($addr)) `,`
208-
($dynAllocSize^ `:` type($dynAllocSize) `,`)?
209186
`[` $name
210187
(`,` `init` $init^)?
211188
(`,` `const` $constant^)?
@@ -229,13 +206,7 @@ def LoadOp : CIR_Op<"load", [
229206
let summary = "Load value from memory adddress";
230207
let description = [{
231208
`cir.load` reads a value (lvalue to rvalue conversion) given an address
232-
backed up by a `cir.ptr` type. A unit attribute `deref` can be used to
233-
mark the resulting value as used by another operation to dereference
234-
a pointer. A unit attribute `volatile` can be used to indicate a volatile
235-
loading. Load can be marked atomic by using `atomic(<mem_order>)`.
236-
237-
`align` can be used to specify an alignment that's different from the
238-
default, which is computed from `result`'s type ABI data layout.
209+
backed up by a `cir.ptr` type.
239210

240211
Example:
241212

@@ -247,8 +218,7 @@ def LoadOp : CIR_Op<"load", [
247218
}];
248219

249220
let arguments = (ins Arg<CIR_PointerType, "the address to load from",
250-
[MemRead]>:$addr
251-
);
221+
[MemRead]>:$addr);
252222
let results = (outs CIR_AnyType:$result);
253223

254224
let assemblyFormat = [{

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ struct MissingFeatures {
3030
// This isn't needed until we add support for bools.
3131
static bool convertTypeForMemory() { return false; }
3232

33+
// CIRGenFunction implementation details
34+
static bool cgfSymbolTable() { return false; }
35+
3336
// Unhandled global/linkage information.
3437
static bool opGlobalDSOLocal() { return false; }
3538
static bool opGlobalThreadLocal() { return false; }
@@ -47,13 +50,15 @@ struct MissingFeatures {
4750
static bool opAllocaStaticLocal() { return false; }
4851
static bool opAllocaNonGC() { return false; }
4952
static bool opAllocaImpreciseLifetime() { return false; }
53+
static bool opAllocaPreciseLifetime() { return false; }
5054
static bool opAllocaTLS() { return false; }
5155
static bool opAllocaOpenMPThreadPrivate() { return false; }
5256
static bool opAllocaEscapeByReference() { return false; }
5357
static bool opAllocaReference() { return false; }
5458

55-
// Options for casts
59+
// Misc
5660
static bool scalarConversionOpts() { return false; }
61+
static bool tryEmitAsConstant() { return false; }
5762
};
5863

5964
} // namespace cir

clang/lib/CIR/CodeGen/Address.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
//
1212
//===----------------------------------------------------------------------===//
1313

14-
#ifndef LLVM_CLANG_LIB_CIR_ADDRESS_H
15-
#define LLVM_CLANG_LIB_CIR_ADDRESS_H
14+
#ifndef CLANG_LIB_CIR_ADDRESS_H
15+
#define CLANG_LIB_CIR_ADDRESS_H
1616

1717
#include "mlir/IR/Value.h"
1818
#include "clang/AST/CharUnits.h"
@@ -73,4 +73,4 @@ class Address {
7373

7474
} // namespace clang::CIRGen
7575

76-
#endif // LLVM_CLANG_LIB_CIR_ADDRESS_H
76+
#endif // CLANG_LIB_CIR_ADDRESS_H

clang/lib/CIR/CodeGen/CIRGenDecl.cpp

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "CIRGenFunction.h"
14+
#include "clang/AST/Attr.h"
15+
#include "clang/AST/Decl.h"
1416
#include "clang/AST/Expr.h"
1517
#include "clang/CIR/MissingFeatures.h"
1618

1719
using namespace clang;
1820
using namespace clang::CIRGen;
1921

20-
/// Emit code and set up symbol table for a variable declaration with auto,
21-
/// register, or no storage class specifier. These turn into simple stack
22-
/// objects, globals depending on target.
23-
void CIRGenFunction::emitAutoVarDecl(const VarDecl &d) {
22+
void CIRGenFunction::emitAutoVarAlloca(const VarDecl &d) {
2423
QualType ty = d.getType();
25-
assert(ty.getAddressSpace() == LangAS::Default);
24+
if (ty.getAddressSpace() != LangAS::Default)
25+
cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: address space");
2626

2727
auto loc = getLoc(d.getSourceRange());
2828

@@ -43,18 +43,50 @@ void CIRGenFunction::emitAutoVarDecl(const VarDecl &d) {
4343
// A normal fixed sized variable becomes an alloca in the entry block,
4444
mlir::Type allocaTy = convertTypeForMem(ty);
4545
// Create the temp alloca and declare variable using it.
46-
mlir::Value addrVal;
47-
address = createTempAlloca(allocaTy, alignment, loc, d.getName(),
48-
/*ArraySize=*/nullptr);
46+
address = createTempAlloca(allocaTy, alignment, loc, d.getName());
47+
declare(address, &d, ty, getLoc(d.getSourceRange()), alignment);
48+
4949
setAddrOfLocalVar(&d, address);
50-
// TODO: emit var init and cleanup
50+
}
51+
52+
void CIRGenFunction::emitAutoVarInit(const clang::VarDecl &d) {
53+
QualType type = d.getType();
54+
55+
// If this local has an initializer, emit it now.
56+
const Expr *init = d.getInit();
57+
58+
if (init || !type.isPODType(getContext())) {
59+
cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit");
60+
}
61+
}
62+
63+
void CIRGenFunction::emitAutoVarCleanups(const clang::VarDecl &d) {
64+
// Check the type for a cleanup.
65+
if (QualType::DestructionKind dtorKind = d.needsDestruction(getContext()))
66+
cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: type cleanup");
67+
68+
assert(!cir::MissingFeatures::opAllocaPreciseLifetime());
69+
70+
// Handle the cleanup attribute.
71+
if (d.hasAttr<CleanupAttr>())
72+
cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: CleanupAttr");
73+
}
74+
75+
76+
/// Emit code and set up symbol table for a variable declaration with auto,
77+
/// register, or no storage class specifier. These turn into simple stack
78+
/// objects, globals depending on target.
79+
void CIRGenFunction::emitAutoVarDecl(const VarDecl &d) {
80+
emitAutoVarAlloca(d);
81+
emitAutoVarInit(d);
82+
emitAutoVarCleanups(d);
5183
}
5284

5385
void CIRGenFunction::emitVarDecl(const VarDecl &d) {
54-
if (d.hasExternalStorage()) {
55-
// Don't emit it now, allow it to be emitted lazily on its first use.
86+
// If the declaration has external storage, don't emit it now, allow it to be
87+
// emitted lazily on its first use.
88+
if (d.hasExternalStorage())
5689
return;
57-
}
5890

5991
if (d.getStorageDuration() != SD_Automatic)
6092
cgm.errorNYI(d.getSourceRange(), "emitVarDecl automatic storage duration");

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "Address.h"
1414
#include "CIRGenFunction.h"
1515
#include "CIRGenValue.h"
16+
#include "mlir/IR/BuiltinAttributes.h"
1617
#include "clang/AST/Attr.h"
1718
#include "clang/AST/CharUnits.h"
1819
#include "clang/AST/Decl.h"
@@ -33,11 +34,11 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(LValue lvalue,
3334
Address addr = lvalue.getAddress();
3435
mlir::Type eltTy = addr.getElementType();
3536

36-
auto ptr = addr.getPointer();
37+
mlir::Value ptr = addr.getPointer();
3738
if (mlir::isa<cir::VoidType>(eltTy))
3839
cgm.errorNYI(loc, "emitLoadOfScalar: void type");
3940

40-
auto loadOp = builder.CIRBaseBuilderTy::createLoad(getLoc(loc), ptr,
41+
mlir::Value loadOp = builder.CIRBaseBuilderTy::createLoad(getLoc(loc), ptr,
4142
false /*isVolatile*/);
4243

4344
return loadOp;
@@ -54,6 +55,7 @@ RValue CIRGenFunction::emitLoadOfLValue(LValue lv, SourceLocation loc) {
5455
return RValue::get(emitLoadOfScalar(lv, loc));
5556

5657
cgm.errorNYI(loc, "emitLoadOfLValue");
58+
return RValue::get(nullptr);
5759
}
5860

5961
LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
@@ -92,37 +94,35 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
9294
}
9395

9496
cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type");
97+
return LValue();
9598
}
9699

97100
mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
98-
mlir::Location loc, CharUnits alignment,
99-
mlir::Value arraySize) {
101+
mlir::Location loc, CharUnits alignment) {
100102
mlir::Block *entryBlock = getCurFunctionEntryBlock();
101103

102-
// CIR uses its own alloca AS rather than follow the target data layout like
103-
// original CodeGen. The data layout awareness should be done in the lowering
104-
// pass instead.
104+
// CIR uses its own alloca address space rather than follow the target data
105+
// layout like original CodeGen. The data layout awareness should be done in
106+
// the lowering pass instead.
105107
assert(!cir::MissingFeatures::addressSpace());
106-
auto localVarPtrTy = builder.getPointerTo(ty);
107-
auto alignIntAttr = cgm.getSize(alignment);
108+
cir::PointerType localVarPtrTy = builder.getPointerTo(ty);
109+
mlir::IntegerAttr alignIntAttr = cgm.getSize(alignment);
108110

109111
mlir::Value addr;
110112
{
111113
mlir::OpBuilder::InsertionGuard guard(builder);
112114
builder.restoreInsertionPoint(builder.getBestAllocaInsertPoint(entryBlock));
113115
addr = builder.createAlloca(loc, /*addr type*/ localVarPtrTy,
114-
/*var type*/ ty, name, alignIntAttr, arraySize);
116+
/*var type*/ ty, name, alignIntAttr);
115117
assert(!cir::MissingFeatures::opAllocaVarDeclContext());
116118
}
117119
return addr;
118120
}
119121

120-
/// This creates an alloca and inserts it into the entry block if \p ArraySize
121-
/// is nullptr, otherwise inserts it at the current insertion point of the
122+
/// This creates an alloca and inserts it at the current insertion point of the
122123
/// builder.
123124
Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,
124-
mlir::Location loc, const Twine &name,
125-
mlir::Value arraySize) {
126-
mlir::Value alloca = emitAlloca(name.str(), ty, loc, align, arraySize);
125+
mlir::Location loc, const Twine &name) {
126+
mlir::Value alloca = emitAlloca(name.str(), ty, loc, align);
127127
return Address(alloca, ty, align);
128128
}

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
6363

6464
// l-values
6565
mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
66-
// TODO: Handle constant emission
66+
assert(!cir::MissingFeatures::tryEmitAsConstant());
6767
return emitLoadOfLValue(e);
6868
}
6969

@@ -91,8 +91,8 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
9191
QualType dstType, SourceLocation loc) {
9292
// No sort of type conversion is implemented yet, but the path for implicit
9393
// paths goes through here even if the type isn't being changed.
94-
srcType = cgf.getContext().getCanonicalType(srcType);
95-
dstType = cgf.getContext().getCanonicalType(dstType);
94+
srcType = srcType.getCanonicalType();
95+
dstType = dstType.getCanonicalType();
9696
if (srcType == dstType)
9797
return src;
9898

@@ -120,9 +120,6 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
120120
QualType destTy = ce->getType();
121121
CastKind kind = ce->getCastKind();
122122

123-
// Since almost all cast kinds apply to scalars, this switch doesn't have a
124-
// default case, so the compiler will warn on a missing case. The cases are
125-
// in the same order as in the CastKind enum.
126123
switch (kind) {
127124
case CK_LValueToRValue:
128125
assert(cgf.getContext().hasSameUnqualifiedType(e->getType(), destTy));

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "CIRGenFunction.h"
1414

1515
#include "clang/AST/GlobalDecl.h"
16+
#include "clang/CIR/MissingFeatures.h"
1617

1718
#include <cassert>
1819

@@ -131,6 +132,21 @@ mlir::Location CIRGenFunction::getLoc(mlir::Location lhs, mlir::Location rhs) {
131132
return mlir::FusedLoc::get(locs, metadata, &getMLIRContext());
132133
}
133134

135+
mlir::LogicalResult CIRGenFunction::declare(Address addr, const Decl *var,
136+
QualType ty, mlir::Location loc,
137+
CharUnits alignment) {
138+
const auto *namedVar = dyn_cast_or_null<NamedDecl>(var);
139+
assert(namedVar && "Needs a named decl");
140+
assert(!cir::MissingFeatures::cgfSymbolTable());
141+
142+
mlir::Value addrVal = addr.getPointer();
143+
auto allocaOp = cast<cir::AllocaOp>(addrVal.getDefiningOp());
144+
if (ty->isReferenceType() || ty.isConstQualified())
145+
allocaOp.setConstantAttr(mlir::UnitAttr::get(&getMLIRContext()));
146+
147+
return mlir::success();
148+
}
149+
134150
void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType,
135151
cir::FuncOp fn, cir::FuncType funcType,
136152
SourceLocation loc,

0 commit comments

Comments
 (0)