| John McCall | de0fe07 | 2017-08-15 21:42:52 +0000 | [diff] [blame] | 1 | //===--- ConstantEmitter.h - IR constant emission ---------------*- C++ -*-===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // A helper class for emitting expressions and values as llvm::Constants | 
|  | 11 | // and as initializers for global variables. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | #ifndef LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H | 
|  | 16 | #define LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H | 
|  | 17 |  | 
|  | 18 | #include "CodeGenFunction.h" | 
|  | 19 | #include "CodeGenModule.h" | 
|  | 20 |  | 
|  | 21 | namespace clang { | 
|  | 22 | namespace CodeGen { | 
|  | 23 |  | 
|  | 24 | class ConstantEmitter { | 
|  | 25 | public: | 
|  | 26 | CodeGenModule &CGM; | 
|  | 27 | CodeGenFunction *CGF; | 
|  | 28 |  | 
|  | 29 | private: | 
|  | 30 | bool Abstract = false; | 
|  | 31 |  | 
|  | 32 | /// Whether non-abstract components of the emitter have been initialized. | 
|  | 33 | bool InitializedNonAbstract = false; | 
|  | 34 |  | 
|  | 35 | /// Whether the emitter has been finalized. | 
|  | 36 | bool Finalized = false; | 
|  | 37 |  | 
|  | 38 | /// Whether the constant-emission failed. | 
|  | 39 | bool Failed = false; | 
|  | 40 |  | 
|  | 41 | /// The AST address space where this (non-abstract) initializer is going. | 
|  | 42 | /// Used for generating appropriate placeholders. | 
| Alexander Richardson | 6d98943 | 2017-10-15 18:48:14 +0000 | [diff] [blame] | 43 | LangAS DestAddressSpace; | 
| John McCall | de0fe07 | 2017-08-15 21:42:52 +0000 | [diff] [blame] | 44 |  | 
|  | 45 | llvm::SmallVector<std::pair<llvm::Constant *, llvm::GlobalVariable*>, 4> | 
|  | 46 | PlaceholderAddresses; | 
|  | 47 |  | 
|  | 48 | public: | 
|  | 49 | ConstantEmitter(CodeGenModule &CGM, CodeGenFunction *CGF = nullptr) | 
|  | 50 | : CGM(CGM), CGF(CGF) {} | 
|  | 51 |  | 
|  | 52 | /// Initialize this emission in the context of the given function. | 
| JF Bastien | f014bdc | 2018-07-11 19:51:40 +0000 | [diff] [blame] | 53 | /// Use this if the expression might contain contextual references like | 
| John McCall | de0fe07 | 2017-08-15 21:42:52 +0000 | [diff] [blame] | 54 | /// block addresses or PredefinedExprs. | 
|  | 55 | ConstantEmitter(CodeGenFunction &CGF) | 
|  | 56 | : CGM(CGF.CGM), CGF(&CGF) {} | 
|  | 57 |  | 
|  | 58 | ConstantEmitter(const ConstantEmitter &other) = delete; | 
|  | 59 | ConstantEmitter &operator=(const ConstantEmitter &other) = delete; | 
|  | 60 |  | 
|  | 61 | ~ConstantEmitter(); | 
|  | 62 |  | 
|  | 63 | /// Is the current emission context abstract? | 
|  | 64 | bool isAbstract() const { | 
|  | 65 | return Abstract; | 
|  | 66 | } | 
|  | 67 |  | 
|  | 68 | /// Try to emit the initiaizer of the given declaration as an abstract | 
|  | 69 | /// constant.  If this succeeds, the emission must be finalized. | 
|  | 70 | llvm::Constant *tryEmitForInitializer(const VarDecl &D); | 
| Alexander Richardson | 6d98943 | 2017-10-15 18:48:14 +0000 | [diff] [blame] | 71 | llvm::Constant *tryEmitForInitializer(const Expr *E, LangAS destAddrSpace, | 
| John McCall | de0fe07 | 2017-08-15 21:42:52 +0000 | [diff] [blame] | 72 | QualType destType); | 
| Alexander Richardson | 6d98943 | 2017-10-15 18:48:14 +0000 | [diff] [blame] | 73 | llvm::Constant *emitForInitializer(const APValue &value, LangAS destAddrSpace, | 
| John McCall | de0fe07 | 2017-08-15 21:42:52 +0000 | [diff] [blame] | 74 | QualType destType); | 
|  | 75 |  | 
|  | 76 | void finalize(llvm::GlobalVariable *global); | 
|  | 77 |  | 
|  | 78 | // All of the "abstract" emission methods below permit the emission to | 
|  | 79 | // be immediately discarded without finalizing anything.  Therefore, they | 
|  | 80 | // must also promise not to do anything that will, in the future, require | 
|  | 81 | // finalization: | 
|  | 82 | // | 
|  | 83 | //   - using the CGF (if present) for anything other than establishing | 
|  | 84 | //     semantic context; for example, an expression with ignored | 
|  | 85 | //     side-effects must not be emitted as an abstract expression | 
|  | 86 | // | 
|  | 87 | //   - doing anything that would not be safe to duplicate within an | 
|  | 88 | //     initializer or to propagate to another context; for example, | 
|  | 89 | //     side effects, or emitting an initialization that requires a | 
|  | 90 | //     reference to its current location. | 
|  | 91 |  | 
|  | 92 | /// Try to emit the initializer of the given declaration as an abstract | 
|  | 93 | /// constant. | 
|  | 94 | llvm::Constant *tryEmitAbstractForInitializer(const VarDecl &D); | 
|  | 95 |  | 
|  | 96 | /// Emit the result of the given expression as an abstract constant, | 
|  | 97 | /// asserting that it succeeded.  This is only safe to do when the | 
|  | 98 | /// expression is known to be a constant expression with either a fairly | 
|  | 99 | /// simple type or a known simple form. | 
|  | 100 | llvm::Constant *emitAbstract(const Expr *E, QualType T); | 
|  | 101 | llvm::Constant *emitAbstract(SourceLocation loc, const APValue &value, | 
|  | 102 | QualType T); | 
|  | 103 |  | 
|  | 104 | /// Try to emit the result of the given expression as an abstract constant. | 
|  | 105 | llvm::Constant *tryEmitAbstract(const Expr *E, QualType T); | 
|  | 106 | llvm::Constant *tryEmitAbstractForMemory(const Expr *E, QualType T); | 
|  | 107 |  | 
|  | 108 | llvm::Constant *tryEmitAbstract(const APValue &value, QualType T); | 
|  | 109 | llvm::Constant *tryEmitAbstractForMemory(const APValue &value, QualType T); | 
|  | 110 |  | 
|  | 111 | llvm::Constant *emitNullForMemory(QualType T) { | 
|  | 112 | return emitNullForMemory(CGM, T); | 
|  | 113 | } | 
|  | 114 | llvm::Constant *emitForMemory(llvm::Constant *C, QualType T) { | 
|  | 115 | return emitForMemory(CGM, C, T); | 
|  | 116 | } | 
|  | 117 |  | 
|  | 118 | static llvm::Constant *emitNullForMemory(CodeGenModule &CGM, QualType T); | 
|  | 119 | static llvm::Constant *emitForMemory(CodeGenModule &CGM, llvm::Constant *C, | 
|  | 120 | QualType T); | 
|  | 121 |  | 
|  | 122 | // These are private helper routines of the constant emitter that | 
|  | 123 | // can't actually be private because things are split out into helper | 
|  | 124 | // functions and classes. | 
|  | 125 |  | 
|  | 126 | llvm::Constant *tryEmitPrivateForVarInit(const VarDecl &D); | 
|  | 127 |  | 
|  | 128 | llvm::Constant *tryEmitPrivate(const Expr *E, QualType T); | 
|  | 129 | llvm::Constant *tryEmitPrivateForMemory(const Expr *E, QualType T); | 
|  | 130 |  | 
|  | 131 | llvm::Constant *tryEmitPrivate(const APValue &value, QualType T); | 
|  | 132 | llvm::Constant *tryEmitPrivateForMemory(const APValue &value, QualType T); | 
|  | 133 |  | 
|  | 134 | /// Get the address of the current location.  This is a constant | 
|  | 135 | /// that will resolve, after finalization, to the address of the | 
|  | 136 | /// 'signal' value that is registered with the emitter later. | 
|  | 137 | llvm::GlobalValue *getCurrentAddrPrivate(); | 
|  | 138 |  | 
|  | 139 | /// Register a 'signal' value with the emitter to inform it where to | 
|  | 140 | /// resolve a placeholder.  The signal value must be unique in the | 
|  | 141 | /// initializer; it might, for example, be the address of a global that | 
|  | 142 | /// refers to the current-address value in its own initializer. | 
|  | 143 | /// | 
|  | 144 | /// Uses of the placeholder must be properly anchored before finalizing | 
|  | 145 | /// the emitter, e.g. by being installed as the initializer of a global | 
|  | 146 | /// variable.  That is, it must be possible to replaceAllUsesWith | 
|  | 147 | /// the placeholder with the proper address of the signal. | 
|  | 148 | void registerCurrentAddrPrivate(llvm::Constant *signal, | 
|  | 149 | llvm::GlobalValue *placeholder); | 
|  | 150 |  | 
|  | 151 | private: | 
| Alexander Richardson | 6d98943 | 2017-10-15 18:48:14 +0000 | [diff] [blame] | 152 | void initializeNonAbstract(LangAS destAS) { | 
| John McCall | de0fe07 | 2017-08-15 21:42:52 +0000 | [diff] [blame] | 153 | assert(!InitializedNonAbstract); | 
|  | 154 | InitializedNonAbstract = true; | 
|  | 155 | DestAddressSpace = destAS; | 
|  | 156 | } | 
|  | 157 | llvm::Constant *markIfFailed(llvm::Constant *init) { | 
|  | 158 | if (!init) | 
|  | 159 | Failed = true; | 
|  | 160 | return init; | 
|  | 161 | } | 
|  | 162 |  | 
|  | 163 | struct AbstractState { | 
|  | 164 | bool OldValue; | 
|  | 165 | size_t OldPlaceholdersSize; | 
|  | 166 | }; | 
|  | 167 | AbstractState pushAbstract() { | 
|  | 168 | AbstractState saved = { Abstract, PlaceholderAddresses.size() }; | 
|  | 169 | Abstract = true; | 
|  | 170 | return saved; | 
|  | 171 | } | 
|  | 172 | llvm::Constant *validateAndPopAbstract(llvm::Constant *C, AbstractState save); | 
|  | 173 | }; | 
|  | 174 |  | 
|  | 175 | } | 
|  | 176 | } | 
|  | 177 |  | 
|  | 178 | #endif |