brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.0 KiB · 581b05a Raw
192 lines · c
1//===--- ConstantEmitter.h - IR constant emission ---------------*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8//9// A helper class for emitting expressions and values as llvm::Constants10// and as initializers for global variables.11//12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H15#define LLVM_CLANG_LIB_CODEGEN_CONSTANTEMITTER_H16 17#include "CodeGenFunction.h"18#include "CodeGenModule.h"19 20namespace clang {21namespace CodeGen {22 23class ConstantEmitter {24public:25  CodeGenModule &CGM;26  CodeGenFunction *const CGF;27 28private:29  bool Abstract = false;30 31  /// Whether non-abstract components of the emitter have been initialized.32  bool InitializedNonAbstract = false;33 34  /// Whether the emitter has been finalized.35  bool Finalized = false;36 37  /// Whether the constant-emission failed.38  bool Failed = false;39 40  /// Whether we're in a constant context.41  bool InConstantContext = false;42 43  /// The AST address space where this (non-abstract) initializer is going.44  /// Used for generating appropriate placeholders.45  LangAS DestAddressSpace = LangAS::Default;46 47  llvm::SmallVector<std::pair<llvm::Constant *, llvm::GlobalVariable*>, 4>48    PlaceholderAddresses;49 50public:51  ConstantEmitter(CodeGenModule &CGM, CodeGenFunction *CGF = nullptr)52    : CGM(CGM), CGF(CGF) {}53 54  /// Initialize this emission in the context of the given function.55  /// Use this if the expression might contain contextual references like56  /// block addresses or PredefinedExprs.57  ConstantEmitter(CodeGenFunction &CGF)58    : CGM(CGF.CGM), CGF(&CGF) {}59 60  ConstantEmitter(const ConstantEmitter &other) = delete;61  ConstantEmitter &operator=(const ConstantEmitter &other) = delete;62 63  ~ConstantEmitter();64 65  /// Is the current emission context abstract?66  bool isAbstract() const {67    return Abstract;68  }69 70  bool isInConstantContext() const { return InConstantContext; }71  void setInConstantContext(bool var) { InConstantContext = var; }72 73  /// Try to emit the initiaizer of the given declaration as an abstract74  /// constant.  If this succeeds, the emission must be finalized.75  llvm::Constant *tryEmitForInitializer(const VarDecl &D);76  llvm::Constant *tryEmitForInitializer(const Expr *E, LangAS destAddrSpace,77                                        QualType destType);78  llvm::Constant *emitForInitializer(const APValue &value, LangAS destAddrSpace,79                                     QualType destType);80 81  void finalize(llvm::GlobalVariable *global);82 83  // All of the "abstract" emission methods below permit the emission to84  // be immediately discarded without finalizing anything.  Therefore, they85  // must also promise not to do anything that will, in the future, require86  // finalization:87  //88  //   - using the CGF (if present) for anything other than establishing89  //     semantic context; for example, an expression with ignored90  //     side-effects must not be emitted as an abstract expression91  //92  //   - doing anything that would not be safe to duplicate within an93  //     initializer or to propagate to another context; for example,94  //     side effects, or emitting an initialization that requires a95  //     reference to its current location.96 97  /// Try to emit the initializer of the given declaration as an abstract98  /// constant.99  llvm::Constant *tryEmitAbstractForInitializer(const VarDecl &D);100 101  /// Emit the result of the given expression as an abstract constant,102  /// asserting that it succeeded.  This is only safe to do when the103  /// expression is known to be a constant expression with either a fairly104  /// simple type or a known simple form.105  llvm::Constant *emitAbstract(const Expr *E, QualType T);106  llvm::Constant *107  emitAbstract(SourceLocation loc, const APValue &value, QualType T,108               bool EnablePtrAuthFunctionTypeDiscrimination = true);109 110  /// Try to emit the result of the given expression as an abstract constant.111  llvm::Constant *tryEmitAbstract(const Expr *E, QualType T);112  llvm::Constant *tryEmitAbstractForMemory(const Expr *E, QualType T);113 114  llvm::Constant *tryEmitAbstract(const APValue &value, QualType T);115  llvm::Constant *tryEmitAbstractForMemory(const APValue &value, QualType T);116 117  llvm::Constant *tryEmitConstantSignedPointer(llvm::Constant *Ptr,118                                               PointerAuthQualifier Auth);119 120  llvm::Constant *tryEmitConstantExpr(const ConstantExpr *CE);121 122  llvm::Constant *emitNullForMemory(QualType T) {123    return emitNullForMemory(CGM, T);124  }125  llvm::Constant *emitForMemory(llvm::Constant *C, QualType T) {126    return emitForMemory(CGM, C, T);127  }128 129  static llvm::Constant *emitNullForMemory(CodeGenModule &CGM, QualType T);130  static llvm::Constant *emitForMemory(CodeGenModule &CGM, llvm::Constant *C,131                                       QualType T);132 133  // These are private helper routines of the constant emitter that134  // can't actually be private because things are split out into helper135  // functions and classes.136 137  llvm::Constant *tryEmitPrivateForVarInit(const VarDecl &D);138 139  llvm::Constant *tryEmitPrivate(const Expr *E, QualType T);140  llvm::Constant *tryEmitPrivateForMemory(const Expr *E, QualType T);141 142  llvm::Constant *143  tryEmitPrivate(const APValue &value, QualType T,144                 bool EnablePtrAuthFunctionTypeDiscrimination = true);145  llvm::Constant *tryEmitPrivateForMemory(const APValue &value, QualType T);146 147  /// Get the address of the current location.  This is a constant148  /// that will resolve, after finalization, to the address of the149  /// 'signal' value that is registered with the emitter later.150  llvm::GlobalValue *getCurrentAddrPrivate();151 152  /// Register a 'signal' value with the emitter to inform it where to153  /// resolve a placeholder.  The signal value must be unique in the154  /// initializer; it might, for example, be the address of a global that155  /// refers to the current-address value in its own initializer.156  ///157  /// Uses of the placeholder must be properly anchored before finalizing158  /// the emitter, e.g. by being installed as the initializer of a global159  /// variable.  That is, it must be possible to replaceAllUsesWith160  /// the placeholder with the proper address of the signal.161  void registerCurrentAddrPrivate(llvm::Constant *signal,162                                  llvm::GlobalValue *placeholder);163 164private:165  void initializeNonAbstract(LangAS destAS) {166    assert(!InitializedNonAbstract);167    InitializedNonAbstract = true;168    DestAddressSpace = destAS;169  }170  llvm::Constant *markIfFailed(llvm::Constant *init) {171    if (!init)172      Failed = true;173    return init;174  }175 176  struct AbstractState {177    bool OldValue;178    size_t OldPlaceholdersSize;179  };180  AbstractState pushAbstract() {181    AbstractState saved = { Abstract, PlaceholderAddresses.size() };182    Abstract = true;183    return saved;184  }185  llvm::Constant *validateAndPopAbstract(llvm::Constant *C, AbstractState save);186};187 188}189}190 191#endif192