diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h | 178 | 
1 files changed, 178 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h b/contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h new file mode 100644 index 000000000000..b4d1b65743c7 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/CodeGen/ConstantEmitter.h @@ -0,0 +1,178 @@ +//===--- ConstantEmitter.h - IR constant emission ---------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// 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 *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; + +  /// 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; +  } + +  /// 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 *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  | 
