diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 13:58:24 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 14:11:53 +0300 |
commit | 11a895b7e15d1c5a1f52706396b82e3f9db953cb (patch) | |
tree | fabc6d883b0f946151f61ae7865cee9f529a1fdd /contrib/libs/clang16/lib/CodeGen/ConstantEmitter.h | |
parent | 9685917341315774aad5733b1793b1e533a88bbb (diff) | |
download | ydb-11a895b7e15d1c5a1f52706396b82e3f9db953cb.tar.gz |
Export clang-format16 via ydblib project
6e6be3a95868fde888d801b7590af4044049563f
Diffstat (limited to 'contrib/libs/clang16/lib/CodeGen/ConstantEmitter.h')
-rw-r--r-- | contrib/libs/clang16/lib/CodeGen/ConstantEmitter.h | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/contrib/libs/clang16/lib/CodeGen/ConstantEmitter.h b/contrib/libs/clang16/lib/CodeGen/ConstantEmitter.h new file mode 100644 index 0000000000..1a7a181ca7 --- /dev/null +++ b/contrib/libs/clang16/lib/CodeGen/ConstantEmitter.h @@ -0,0 +1,185 @@ +//===--- ConstantEmitter.h - IR constant emission ---------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// A helper class for emitting expressions and values as llvm::Constants +// and as initializers for global variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H +#define LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" + +namespace clang { +namespace CodeGen { + +class ConstantEmitter { +public: + CodeGenModule &CGM; + CodeGenFunction *const CGF; + +private: + bool Abstract = false; + + /// Whether non-abstract components of the emitter have been initialized. + bool InitializedNonAbstract = false; + + /// Whether the emitter has been finalized. + bool Finalized = false; + + /// Whether the constant-emission failed. + bool Failed = false; + + /// Whether we're in a constant context. + bool InConstantContext = false; + + /// The AST address space where this (non-abstract) initializer is going. + /// Used for generating appropriate placeholders. + LangAS DestAddressSpace; + + llvm::SmallVector<std::pair<llvm::Constant *, llvm::GlobalVariable*>, 4> + PlaceholderAddresses; + +public: + ConstantEmitter(CodeGenModule &CGM, CodeGenFunction *CGF = nullptr) + : CGM(CGM), CGF(CGF) {} + + /// Initialize this emission in the context of the given function. + /// Use this if the expression might contain contextual references like + /// block addresses or PredefinedExprs. + ConstantEmitter(CodeGenFunction &CGF) + : CGM(CGF.CGM), CGF(&CGF) {} + + ConstantEmitter(const ConstantEmitter &other) = delete; + ConstantEmitter &operator=(const ConstantEmitter &other) = delete; + + ~ConstantEmitter(); + + /// Is the current emission context abstract? + bool isAbstract() const { + return Abstract; + } + + bool isInConstantContext() const { return InConstantContext; } + void setInConstantContext(bool var) { InConstantContext = var; } + + /// Try to emit the initiaizer of the given declaration as an abstract + /// constant. If this succeeds, the emission must be finalized. + llvm::Constant *tryEmitForInitializer(const VarDecl &D); + llvm::Constant *tryEmitForInitializer(const Expr *E, LangAS destAddrSpace, + QualType destType); + llvm::Constant *emitForInitializer(const APValue &value, LangAS destAddrSpace, + QualType destType); + + void finalize(llvm::GlobalVariable *global); + + // All of the "abstract" emission methods below permit the emission to + // be immediately discarded without finalizing anything. Therefore, they + // must also promise not to do anything that will, in the future, require + // finalization: + // + // - using the CGF (if present) for anything other than establishing + // semantic context; for example, an expression with ignored + // side-effects must not be emitted as an abstract expression + // + // - doing anything that would not be safe to duplicate within an + // initializer or to propagate to another context; for example, + // side effects, or emitting an initialization that requires a + // reference to its current location. + + /// Try to emit the initializer of the given declaration as an abstract + /// constant. + llvm::Constant *tryEmitAbstractForInitializer(const VarDecl &D); + + /// Emit the result of the given expression as an abstract constant, + /// asserting that it succeeded. This is only safe to do when the + /// expression is known to be a constant expression with either a fairly + /// simple type or a known simple form. + llvm::Constant *emitAbstract(const Expr *E, QualType T); + llvm::Constant *emitAbstract(SourceLocation loc, const APValue &value, + QualType T); + + /// Try to emit the result of the given expression as an abstract constant. + llvm::Constant *tryEmitAbstract(const Expr *E, QualType T); + llvm::Constant *tryEmitAbstractForMemory(const Expr *E, QualType T); + + llvm::Constant *tryEmitAbstract(const APValue &value, QualType T); + llvm::Constant *tryEmitAbstractForMemory(const APValue &value, QualType T); + + llvm::Constant *tryEmitConstantExpr(const ConstantExpr *CE); + + llvm::Constant *emitNullForMemory(QualType T) { + return emitNullForMemory(CGM, T); + } + llvm::Constant *emitForMemory(llvm::Constant *C, QualType T) { + return emitForMemory(CGM, C, T); + } + + static llvm::Constant *emitNullForMemory(CodeGenModule &CGM, QualType T); + static llvm::Constant *emitForMemory(CodeGenModule &CGM, llvm::Constant *C, + QualType T); + + // These are private helper routines of the constant emitter that + // can't actually be private because things are split out into helper + // functions and classes. + + llvm::Constant *tryEmitPrivateForVarInit(const VarDecl &D); + + llvm::Constant *tryEmitPrivate(const Expr *E, QualType T); + llvm::Constant *tryEmitPrivateForMemory(const Expr *E, QualType T); + + llvm::Constant *tryEmitPrivate(const APValue &value, QualType T); + llvm::Constant *tryEmitPrivateForMemory(const APValue &value, QualType T); + + /// Get the address of the current location. This is a constant + /// that will resolve, after finalization, to the address of the + /// 'signal' value that is registered with the emitter later. + llvm::GlobalValue *getCurrentAddrPrivate(); + + /// Register a 'signal' value with the emitter to inform it where to + /// resolve a placeholder. The signal value must be unique in the + /// initializer; it might, for example, be the address of a global that + /// refers to the current-address value in its own initializer. + /// + /// Uses of the placeholder must be properly anchored before finalizing + /// the emitter, e.g. by being installed as the initializer of a global + /// variable. That is, it must be possible to replaceAllUsesWith + /// the placeholder with the proper address of the signal. + void registerCurrentAddrPrivate(llvm::Constant *signal, + llvm::GlobalValue *placeholder); + +private: + void initializeNonAbstract(LangAS destAS) { + assert(!InitializedNonAbstract); + InitializedNonAbstract = true; + DestAddressSpace = destAS; + } + llvm::Constant *markIfFailed(llvm::Constant *init) { + if (!init) + Failed = true; + return init; + } + + struct AbstractState { + bool OldValue; + size_t OldPlaceholdersSize; + }; + AbstractState pushAbstract() { + AbstractState saved = { Abstract, PlaceholderAddresses.size() }; + Abstract = true; + return saved; + } + llvm::Constant *validateAndPopAbstract(llvm::Constant *C, AbstractState save); +}; + +} +} + +#endif |