Skip to content

Commit 8eb9b94

Browse files
authored
[CIR] Emit init of local variables (#130164)
Local variable initialization was previously being ignored. This change adds support for initialization of scalar variables with constant values and introduces the constant emitter framework.
1 parent 5668c7b commit 8eb9b94

File tree

14 files changed

+924
-33
lines changed

14 files changed

+924
-33
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
2626
CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
2727
: mlir::OpBuilder(&mlirContext) {}
2828

29+
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) {
30+
return create<cir::ConstantOp>(loc, attr.getType(), attr);
31+
}
32+
2933
cir::ConstantOp getBool(bool state, mlir::Location loc) {
3034
return create<cir::ConstantOp>(loc, getBoolTy(), getCIRBoolAttr(state));
3135
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,20 @@ def CIR_BoolAttr : CIR_Attr<"Bool", "bool", [TypedAttrInterface]> {
5454
}];
5555
}
5656

57+
//===----------------------------------------------------------------------===//
58+
// ZeroAttr
59+
//===----------------------------------------------------------------------===//
60+
61+
def ZeroAttr : CIR_Attr<"Zero", "zero", [TypedAttrInterface]> {
62+
let summary = "Attribute to represent zero initialization";
63+
let description = [{
64+
The ZeroAttr is used to indicate zero initialization on structs.
65+
}];
66+
67+
let parameters = (ins AttributeSelfTypeParameter<"">:$type);
68+
let assemblyFormat = [{}];
69+
}
70+
5771
//===----------------------------------------------------------------------===//
5872
// UndefAttr
5973
//===----------------------------------------------------------------------===//

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,17 @@ struct MissingFeatures {
4141
static bool supportComdat() { return false; }
4242

4343
// Load/store attributes
44-
static bool opLoadThreadLocal() { return false; }
44+
static bool opLoadStoreThreadLocal() { return false; }
4545
static bool opLoadEmitScalarRangeCheck() { return false; }
4646
static bool opLoadBooleanRepresentation() { return false; }
4747
static bool opLoadStoreTbaa() { return false; }
4848
static bool opLoadStoreMemOrder() { return false; }
4949
static bool opLoadStoreVolatile() { return false; }
5050
static bool opLoadStoreAlignment() { return false; }
51+
static bool opLoadStoreAtomic() { return false; }
52+
static bool opLoadStoreObjC() { return false; }
5153

5254
// AllocaOp handling
53-
static bool opAllocaVarDeclContext() { return false; }
5455
static bool opAllocaStaticLocal() { return false; }
5556
static bool opAllocaNonGC() { return false; }
5657
static bool opAllocaImpreciseLifetime() { return false; }
@@ -61,6 +62,7 @@ struct MissingFeatures {
6162
static bool opAllocaReference() { return false; }
6263
static bool opAllocaAnnotations() { return false; }
6364
static bool opAllocaDynAllocSize() { return false; }
65+
static bool opAllocaCaptureByInit() { return false; }
6466

6567
// FuncOp handling
6668
static bool opFuncOpenCLKernelMetadata() { return false; }
@@ -76,6 +78,10 @@ struct MissingFeatures {
7678
static bool constructABIArgDirectExtend() { return false; }
7779
static bool opGlobalViewAttr() { return false; }
7880
static bool lowerModeOptLevel() { return false; }
81+
static bool opTBAA() { return false; }
82+
static bool objCLifetime() { return false; }
83+
static bool emitNullabilityCheck() { return false; }
84+
static bool astVarDeclInterface() { return false; }
7985
};
8086

8187
} // namespace cir
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// A helper class for emitting expressions and values as cir::ConstantOp
10+
// and as initializers for global variables.
11+
//
12+
// Note: this is based on clang's LLVM IR codegen in ConstantEmitter.h, reusing
13+
// this class interface makes it easier move forward with bringing CIR codegen
14+
// to completion.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef CLANG_LIB_CIR_CODEGEN_CIRGENCONSTANTEMITTER_H
19+
#define CLANG_LIB_CIR_CODEGEN_CIRGENCONSTANTEMITTER_H
20+
21+
#include "CIRGenFunction.h"
22+
#include "CIRGenModule.h"
23+
#include "llvm/ADT/SmallVector.h"
24+
25+
namespace clang::CIRGen {
26+
27+
class ConstantEmitter {
28+
public:
29+
CIRGenModule &cgm;
30+
const CIRGenFunction *cgf;
31+
32+
private:
33+
bool abstract = false;
34+
35+
/// Whether we're in a constant context.
36+
bool inConstantContext = false;
37+
38+
public:
39+
/// Initialize this emission in the context of the given function.
40+
/// Use this if the expression might contain contextual references like
41+
/// block addresses or PredefinedExprs.
42+
ConstantEmitter(CIRGenFunction &cgf) : cgm(cgf.cgm), cgf(&cgf) {}
43+
44+
ConstantEmitter(const ConstantEmitter &other) = delete;
45+
ConstantEmitter &operator=(const ConstantEmitter &other) = delete;
46+
47+
// All of the "abstract" emission methods below permit the emission to
48+
// be immediately discarded without finalizing anything. Therefore, they
49+
// must also promise not to do anything that will, in the future, require
50+
// finalization:
51+
//
52+
// - using the CGF (if present) for anything other than establishing
53+
// semantic context; for example, an expression with ignored
54+
// side-effects must not be emitted as an abstract expression
55+
//
56+
// - doing anything that would not be safe to duplicate within an
57+
// initializer or to propagate to another context; for example,
58+
// side effects, or emitting an initialization that requires a
59+
// reference to its current location.
60+
mlir::Attribute emitForMemory(mlir::Attribute c, QualType t);
61+
62+
/// Emit the result of the given expression as an abstract constant,
63+
/// asserting that it succeeded. This is only safe to do when the
64+
/// expression is known to be a constant expression with either a fairly
65+
/// simple type or a known simple form.
66+
mlir::Attribute emitAbstract(SourceLocation loc, const APValue &value,
67+
QualType t);
68+
69+
mlir::Attribute tryEmitConstantExpr(const ConstantExpr *CE);
70+
71+
// These are private helper routines of the constant emitter that
72+
// can't actually be private because things are split out into helper
73+
// functions and classes.
74+
75+
mlir::Attribute tryEmitPrivateForVarInit(const VarDecl &d);
76+
77+
mlir::Attribute tryEmitPrivate(const APValue &value, QualType destType);
78+
mlir::Attribute tryEmitPrivateForMemory(const APValue &value, QualType t);
79+
80+
/// Try to emit the initializer of the given declaration as an abstract
81+
/// constant.
82+
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d);
83+
84+
private:
85+
class AbstractStateRAII {
86+
ConstantEmitter &emitter;
87+
bool oldValue;
88+
89+
public:
90+
AbstractStateRAII(ConstantEmitter &emitter, bool value)
91+
: emitter(emitter), oldValue(emitter.abstract) {
92+
emitter.abstract = value;
93+
}
94+
~AbstractStateRAII() { emitter.abstract = oldValue; }
95+
};
96+
};
97+
98+
} // namespace clang::CIRGen
99+
100+
#endif // CLANG_LIB_CIR_CODEGEN_CIRGENCONSTANTEMITTER_H

0 commit comments

Comments
 (0)