clang 23.0.0git
CIRGenConstantEmitter.h
Go to the documentation of this file.
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
24namespace clang::CIRGen {
25
27public:
30
31private:
32 bool abstract = false;
33
34#ifndef NDEBUG
35 // Variables used for asserting state consistency.
36
37 /// Whether non-abstract components of the emitter have been initialized.
38 bool initializedNonAbstract = false;
39
40 /// Whether the emitter has been finalized.
41 bool finalized = false;
42
43 /// Whether the constant-emission failed.
44 bool failed = false;
45#endif // NDEBUG
46
47 /// Whether we're in a constant context.
48 bool inConstantContext = false;
49
50public:
51 /// Initialize this emission in the context of the given function.
52 /// Use this if the expression might contain contextual references like
53 /// block addresses or PredefinedExprs.
55
58
59 ConstantEmitter(const ConstantEmitter &other) = delete;
60 ConstantEmitter &operator=(const ConstantEmitter &other) = delete;
61
63
64 bool isInConstantContext() const { return inConstantContext; }
65 void setInConstantContext(bool value) { inConstantContext = value; }
66
67 /// Try to emit the initializer of the given declaration as an abstract
68 /// constant. If this succeeds, the emission must be finalized.
69 mlir::Attribute tryEmitForInitializer(const VarDecl &d);
70 mlir::Attribute tryEmitForInitializer(const Expr *e, QualType destType);
71
72 mlir::Attribute emitForInitializer(const APValue &value, QualType destType);
73
74 void finalize(cir::GlobalOp gv);
75
76 // All of the "abstract" emission methods below permit the emission to
77 // be immediately discarded without finalizing anything. Therefore, they
78 // must also promise not to do anything that will, in the future, require
79 // finalization:
80 //
81 // - using the CGF (if present) for anything other than establishing
82 // semantic context; for example, an expression with ignored
83 // side-effects must not be emitted as an abstract expression
84 //
85 // - doing anything that would not be safe to duplicate within an
86 // initializer or to propagate to another context; for example,
87 // side effects, or emitting an initialization that requires a
88 // reference to its current location.
89 mlir::Attribute emitForMemory(mlir::Attribute c, QualType destType);
90 static mlir::Attribute emitForMemory(CIRGenModule &cgm, mlir::Attribute c,
91 clang::QualType destTy);
92
93 mlir::Attribute emitNullForMemory(mlir::Location loc, QualType t) {
94 return emitNullForMemory(loc, cgm, t);
95 }
96 static mlir::Attribute emitNullForMemory(mlir::Location loc,
98
99 /// Try to emit the initializer of the given declaration as an abstract
100 /// constant.
101 mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d);
102
103 /// Emit the result of the given expression as an abstract constant,
104 /// asserting that it succeeded. This is only safe to do when the
105 /// expression is known to be a constant expression with either a fairly
106 /// simple type or a known simple form.
107 mlir::Attribute emitAbstract(const Expr *e, QualType destType);
108 mlir::Attribute emitAbstract(SourceLocation loc, const APValue &value,
109 QualType destType);
110
111 mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce);
112
113 // These are private helper routines of the constant emitter that
114 // can't actually be private because things are split out into helper
115 // functions and classes.
116
117 mlir::Attribute tryEmitPrivateForVarInit(const VarDecl &d);
118
119 mlir::TypedAttr tryEmitPrivate(const Expr *e, QualType destType);
120 mlir::Attribute tryEmitPrivate(const APValue &value, QualType destType);
121 mlir::Attribute tryEmitPrivateForMemory(const Expr *e, QualType destTy);
122 mlir::Attribute tryEmitPrivateForMemory(const APValue &value,
123 QualType destTy);
124
125 mlir::Attribute tryEmitAbstract(const Expr *e, QualType destType);
126
127private:
128#ifndef NDEBUG
129 void initializeNonAbstract() {
130 assert(!initializedNonAbstract);
131 initializedNonAbstract = true;
133 }
134 mlir::Attribute markIfFailed(mlir::Attribute init) {
135 if (!init)
136 failed = true;
137 return init;
138 }
139#else
140 void initializeNonAbstract() {}
141 mlir::Attribute markIfFailed(mlir::Attribute init) { return init; }
142#endif // NDEBUG
143
144 class AbstractStateRAII {
145 ConstantEmitter &emitter;
146 bool oldValue;
147
148 public:
149 AbstractStateRAII(ConstantEmitter &emitter, bool value)
150 : emitter(emitter), oldValue(emitter.abstract) {
151 emitter.abstract = value;
152 }
153 ~AbstractStateRAII() { emitter.abstract = oldValue; }
154 };
155};
156
157} // namespace clang::CIRGen
158
159#endif // CLANG_LIB_CIR_CODEGEN_CIRGENCONSTANTEMITTER_H
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
This class organizes the cross-function state that is used while generating CIR code.
mlir::Attribute emitForMemory(mlir::Attribute c, QualType destType)
mlir::Attribute emitNullForMemory(mlir::Location loc, QualType t)
ConstantEmitter(const ConstantEmitter &other)=delete
ConstantEmitter & operator=(const ConstantEmitter &other)=delete
mlir::TypedAttr tryEmitPrivate(const Expr *e, QualType destType)
mlir::Attribute tryEmitPrivateForVarInit(const VarDecl &d)
mlir::Attribute tryEmitPrivateForMemory(const Expr *e, QualType destTy)
mlir::Attribute emitAbstract(const Expr *e, QualType destType)
Emit the result of the given expression as an abstract constant, asserting that it succeeded.
mlir::Attribute tryEmitAbstract(const Expr *e, QualType destType)
ConstantEmitter(CIRGenModule &cgm, const CIRGenFunction *cgf=nullptr)
mlir::Attribute tryEmitForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
ConstantEmitter(CIRGenFunction &cgf)
Initialize this emission in the context of the given function.
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d)
Try to emit the initializer of the given declaration as an abstract constant.
mlir::Attribute emitForInitializer(const APValue &value, QualType destType)
mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce)
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
Definition Expr.h:1085
This represents one expression.
Definition Expr.h:112
A (possibly-)qualified type.
Definition TypeBase.h:937
Encodes a location in the source.
Represents a variable declaration or definition.
Definition Decl.h:924
static bool addressSpace()