Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h
213799 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// A helper class for emitting expressions and values as cir::ConstantOp9// and as initializers for global variables.10//11// Note: this is based on clang's LLVM IR codegen in ConstantEmitter.h, reusing12// this class interface makes it easier move forward with bringing CIR codegen13// to completion.14//15//===----------------------------------------------------------------------===//1617#ifndef CLANG_LIB_CIR_CODEGEN_CIRGENCONSTANTEMITTER_H18#define CLANG_LIB_CIR_CODEGEN_CIRGENCONSTANTEMITTER_H1920#include "CIRGenFunction.h"21#include "CIRGenModule.h"2223namespace clang::CIRGen {2425class ConstantEmitter {26public:27CIRGenModule &cgm;28const CIRGenFunction *cgf;2930private:31bool abstract = false;3233#ifndef NDEBUG34// Variables used for asserting state consistency.3536/// Whether non-abstract components of the emitter have been initialized.37bool initializedNonAbstract = false;3839/// Whether the emitter has been finalized.40bool finalized = false;4142/// Whether the constant-emission failed.43bool failed = false;44#endif // NDEBUG4546/// Whether we're in a constant context.47bool inConstantContext = false;4849public:50/// Initialize this emission in the context of the given function.51/// Use this if the expression might contain contextual references like52/// block addresses or PredefinedExprs.53ConstantEmitter(CIRGenFunction &cgf) : cgm(cgf.cgm), cgf(&cgf) {}5455ConstantEmitter(CIRGenModule &cgm, CIRGenFunction *cgf = nullptr)56: cgm(cgm), cgf(cgf) {}5758ConstantEmitter(const ConstantEmitter &other) = delete;59ConstantEmitter &operator=(const ConstantEmitter &other) = delete;6061~ConstantEmitter();6263/// Try to emit the initializer of the given declaration as an abstract64/// constant. If this succeeds, the emission must be finalized.65mlir::Attribute tryEmitForInitializer(const VarDecl &d);6667void finalize(cir::GlobalOp gv);6869// All of the "abstract" emission methods below permit the emission to70// be immediately discarded without finalizing anything. Therefore, they71// must also promise not to do anything that will, in the future, require72// finalization:73//74// - using the CGF (if present) for anything other than establishing75// semantic context; for example, an expression with ignored76// side-effects must not be emitted as an abstract expression77//78// - doing anything that would not be safe to duplicate within an79// initializer or to propagate to another context; for example,80// side effects, or emitting an initialization that requires a81// reference to its current location.82mlir::Attribute emitForMemory(mlir::Attribute c, QualType t);8384/// Try to emit the initializer of the given declaration as an abstract85/// constant.86mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d);8788/// Emit the result of the given expression as an abstract constant,89/// asserting that it succeeded. This is only safe to do when the90/// expression is known to be a constant expression with either a fairly91/// simple type or a known simple form.92mlir::Attribute emitAbstract(SourceLocation loc, const APValue &value,93QualType t);9495mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce);9697// These are private helper routines of the constant emitter that98// can't actually be private because things are split out into helper99// functions and classes.100101mlir::Attribute tryEmitPrivateForVarInit(const VarDecl &d);102103mlir::Attribute tryEmitPrivate(const APValue &value, QualType destType);104mlir::Attribute tryEmitPrivateForMemory(const APValue &value, QualType t);105106private:107#ifndef NDEBUG108void initializeNonAbstract() {109assert(!initializedNonAbstract);110initializedNonAbstract = true;111assert(!cir::MissingFeatures::addressSpace());112}113mlir::Attribute markIfFailed(mlir::Attribute init) {114if (!init)115failed = true;116return init;117}118#else119void initializeNonAbstract() {}120mlir::Attribute markIfFailed(mlir::Attribute init) { return init; }121#endif // NDEBUG122123class AbstractStateRAII {124ConstantEmitter &emitter;125bool oldValue;126127public:128AbstractStateRAII(ConstantEmitter &emitter, bool value)129: emitter(emitter), oldValue(emitter.abstract) {130emitter.abstract = value;131}132~AbstractStateRAII() { emitter.abstract = oldValue; }133};134};135136} // namespace clang::CIRGen137138#endif // CLANG_LIB_CIR_CODEGEN_CIRGENCONSTANTEMITTER_H139140141