1//===- ConstantInitFuture.h - "Future" constant initializers ----*- 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// This class defines the ConstantInitFuture class.  This is split out
11// from ConstantInitBuilder.h in order to allow APIs to work with it
12// without having to include that entire header.  This is particularly
13// important because it is often useful to be able to default-construct
14// a future in, say, a default argument.
15//
16//===----------------------------------------------------------------------===//
17
18#ifndef LLVM_CLANG_CODEGEN_CONSTANTINITFUTURE_H
19#define LLVM_CLANG_CODEGEN_CONSTANTINITFUTURE_H
20
21#include "llvm/ADT/PointerUnion.h"
22#include "llvm/IR/Constant.h"
23
24// Forward-declare ConstantInitBuilderBase and give it a
25// PointerLikeTypeTraits specialization so that we can safely use it
26// in a PointerUnion below.
27namespace clang {
28namespace CodeGen {
29class ConstantInitBuilderBase;
30}
31}
32namespace llvm {
33template <>
34struct PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitBuilderBase*> {
35  using T = ::clang::CodeGen::ConstantInitBuilderBase*;
36
37  static inline void *getAsVoidPointer(T p) { return p; }
38  static inline T getFromVoidPointer(void *p) {return static_cast<T>(p);}
39  enum { NumLowBitsAvailable = 2 };
40};
41}
42
43namespace clang {
44namespace CodeGen {
45
46/// A "future" for a completed constant initializer, which can be passed
47/// around independently of any sub-builders (but not the original parent).
48class ConstantInitFuture {
49  using PairTy = llvm::PointerUnion<ConstantInitBuilderBase*, llvm::Constant*>;
50
51  PairTy Data;
52
53  friend class ConstantInitBuilderBase;
54  explicit ConstantInitFuture(ConstantInitBuilderBase *builder);
55
56public:
57  ConstantInitFuture() {}
58
59  /// A future can be explicitly created from a fixed initializer.
60  explicit ConstantInitFuture(llvm::Constant *initializer) : Data(initializer) {
61    assert(initializer && "creating null future");
62  }
63
64  /// Is this future non-null?
65  explicit operator bool() const { return bool(Data); }
66
67  /// Return the type of the initializer.
68  llvm::Type *getType() const;
69
70  /// Abandon this initializer.
71  void abandon();
72
73  /// Install the initializer into a global variable.  This cannot
74  /// be called multiple times.
75  void installInGlobal(llvm::GlobalVariable *global);
76
77  void *getOpaqueValue() const { return Data.getOpaqueValue(); }
78  static ConstantInitFuture getFromOpaqueValue(void *value) {
79    ConstantInitFuture result;
80    result.Data = PairTy::getFromOpaqueValue(value);
81    return result;
82  }
83  enum {
84    NumLowBitsAvailable =
85      llvm::PointerLikeTypeTraits<PairTy>::NumLowBitsAvailable
86  };
87};
88
89}  // end namespace CodeGen
90}  // end namespace clang
91
92namespace llvm {
93
94template <>
95struct PointerLikeTypeTraits< ::clang::CodeGen::ConstantInitFuture> {
96  using T = ::clang::CodeGen::ConstantInitFuture;
97
98  static inline void *getAsVoidPointer(T future) {
99    return future.getOpaqueValue();
100  }
101  static inline T getFromVoidPointer(void *p) {
102    return T::getFromOpaqueValue(p);
103  }
104  enum { NumLowBitsAvailable = T::NumLowBitsAvailable };
105};
106
107} // end namespace llvm
108
109#endif
110