brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · ccded3d Raw
152 lines · c
1//===----------------------------------------------------------------------===//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 cir::ConstantOp10// and as initializers for global variables.11//12// Note: this is based on clang's LLVM IR codegen in ConstantEmitter.h, reusing13// this class interface makes it easier move forward with bringing CIR codegen14// to completion.15//16//===----------------------------------------------------------------------===//17 18#ifndef CLANG_LIB_CIR_CODEGEN_CIRGENCONSTANTEMITTER_H19#define CLANG_LIB_CIR_CODEGEN_CIRGENCONSTANTEMITTER_H20 21#include "CIRGenFunction.h"22#include "CIRGenModule.h"23 24namespace clang::CIRGen {25 26class ConstantEmitter {27public:28  CIRGenModule &cgm;29  const CIRGenFunction *cgf;30 31private:32  bool abstract = false;33 34#ifndef NDEBUG35  // Variables used for asserting state consistency.36 37  /// Whether non-abstract components of the emitter have been initialized.38  bool initializedNonAbstract = false;39 40  /// Whether the emitter has been finalized.41  bool finalized = false;42 43  /// Whether the constant-emission failed.44  bool failed = false;45#endif // NDEBUG46 47  /// Whether we're in a constant context.48  bool inConstantContext = false;49 50public:51  /// Initialize this emission in the context of the given function.52  /// Use this if the expression might contain contextual references like53  /// block addresses or PredefinedExprs.54  ConstantEmitter(CIRGenFunction &cgf) : cgm(cgf.cgm), cgf(&cgf) {}55 56  ConstantEmitter(CIRGenModule &cgm, CIRGenFunction *cgf = nullptr)57      : cgm(cgm), cgf(cgf) {}58 59  ConstantEmitter(const ConstantEmitter &other) = delete;60  ConstantEmitter &operator=(const ConstantEmitter &other) = delete;61 62  ~ConstantEmitter();63 64  /// Try to emit the initializer of the given declaration as an abstract65  /// constant.  If this succeeds, the emission must be finalized.66  mlir::Attribute tryEmitForInitializer(const VarDecl &d);67 68  void finalize(cir::GlobalOp gv);69 70  // All of the "abstract" emission methods below permit the emission to71  // be immediately discarded without finalizing anything.  Therefore, they72  // must also promise not to do anything that will, in the future, require73  // finalization:74  //75  //   - using the CGF (if present) for anything other than establishing76  //     semantic context; for example, an expression with ignored77  //     side-effects must not be emitted as an abstract expression78  //79  //   - doing anything that would not be safe to duplicate within an80  //     initializer or to propagate to another context; for example,81  //     side effects, or emitting an initialization that requires a82  //     reference to its current location.83  mlir::Attribute emitForMemory(mlir::Attribute c, QualType destType);84  static mlir::Attribute emitForMemory(CIRGenModule &cgm, mlir::Attribute c,85                                       clang::QualType destTy);86 87  mlir::Attribute emitNullForMemory(mlir::Location loc, QualType t) {88    return emitNullForMemory(loc, cgm, t);89  }90  static mlir::Attribute emitNullForMemory(mlir::Location loc,91                                           CIRGenModule &cgm, QualType t);92 93  /// Try to emit the initializer of the given declaration as an abstract94  /// constant.95  mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d);96 97  /// Emit the result of the given expression as an abstract constant,98  /// asserting that it succeeded.  This is only safe to do when the99  /// expression is known to be a constant expression with either a fairly100  /// simple type or a known simple form.101  mlir::Attribute emitAbstract(const Expr *e, QualType destType);102  mlir::Attribute emitAbstract(SourceLocation loc, const APValue &value,103                               QualType destType);104 105  mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce);106 107  // These are private helper routines of the constant emitter that108  // can't actually be private because things are split out into helper109  // functions and classes.110 111  mlir::Attribute tryEmitPrivateForVarInit(const VarDecl &d);112 113  mlir::TypedAttr tryEmitPrivate(const Expr *e, QualType destType);114  mlir::Attribute tryEmitPrivate(const APValue &value, QualType destType);115  mlir::Attribute tryEmitPrivateForMemory(const Expr *e, QualType destTy);116  mlir::Attribute tryEmitPrivateForMemory(const APValue &value,117                                          QualType destTy);118 119private:120#ifndef NDEBUG121  void initializeNonAbstract() {122    assert(!initializedNonAbstract);123    initializedNonAbstract = true;124    assert(!cir::MissingFeatures::addressSpace());125  }126  mlir::Attribute markIfFailed(mlir::Attribute init) {127    if (!init)128      failed = true;129    return init;130  }131#else132  void initializeNonAbstract() {}133  mlir::Attribute markIfFailed(mlir::Attribute init) { return init; }134#endif // NDEBUG135 136  class AbstractStateRAII {137    ConstantEmitter &emitter;138    bool oldValue;139 140  public:141    AbstractStateRAII(ConstantEmitter &emitter, bool value)142        : emitter(emitter), oldValue(emitter.abstract) {143      emitter.abstract = value;144    }145    ~AbstractStateRAII() { emitter.abstract = oldValue; }146  };147};148 149} // namespace clang::CIRGen150 151#endif // CLANG_LIB_CIR_CODEGEN_CIRGENCONSTANTEMITTER_H152