[Orc] Take another shot at working around the GCC 4.7 ICE in
[oota-llvm.git] / include / llvm / ExecutionEngine / Orc / OrcArchitectureSupport.h
1 //===-- OrcArchitectureSupport.h - Architecture support code  ---*- 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 // Architecture specific code for Orc, e.g. callback assembly.
11 //
12 // Architecture classes should be part of the JIT *target* process, not the host
13 // process (except where you're doing hosted JITing and the two are one and the
14 // same).
15 //
16 //===----------------------------------------------------------------------===//
17
18 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCARCHITECTURESUPPORT_H
19 #define LLVM_EXECUTIONENGINE_ORC_ORCARCHITECTURESUPPORT_H
20
21 #include "IndirectionUtils.h"
22 #include "llvm/Support/Memory.h"
23 #include "llvm/Support/Process.h"
24
25 namespace llvm {
26 namespace orc {
27
28 /// Generic ORC Architecture support.
29 ///
30 /// This class can be substituted as the target architecure support class for
31 /// ORC templates that require one (e.g. IndirectStubsManagers). It does not
32 /// support lazy JITing however, and any attempt to use that functionality
33 /// will result in execution of an llvm_unreachable.
34 class OrcGenericArchitecture {
35 public:
36   static const unsigned PointerSize = sizeof(uintptr_t);
37   static const unsigned TrampolineSize = 1;
38   static const unsigned ResolverCodeSize = 1;
39
40   typedef TargetAddress (*JITReentryFn)(void *CallbackMgr, void *TrampolineId);
41
42   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
43                                 void *CallbackMgr) {
44     llvm_unreachable("writeResolverCode is not supported by the generic host "
45                      "support class");
46   }
47
48   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
49                                unsigned NumTrampolines) {
50     llvm_unreachable("writeTrampolines is not supported by the generic host "
51                      "support class");
52   }
53
54   class IndirectStubsInfo {
55   public:
56     const static unsigned StubSize = 1;
57     unsigned getNumStubs() const { llvm_unreachable("Not supported"); }
58     void *getStub(unsigned Idx) const { llvm_unreachable("Not supported"); }
59     void **getPtr(unsigned Idx) const { llvm_unreachable("Not supported"); }
60   };
61
62   static std::error_code emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
63                                                 unsigned MinStubs,
64                                                 void *InitialPtrVal) {
65     llvm_unreachable("emitIndirectStubsBlock is not supported by the generic "
66                      "host support class");
67   }
68 };
69
70 /// @brief X86_64 support.
71 ///
72 /// X86_64 supports lazy JITing.
73 class OrcX86_64 {
74 public:
75   static const unsigned PointerSize = 8;
76   static const unsigned TrampolineSize = 8;
77   static const unsigned ResolverCodeSize = 0x78;
78
79   typedef TargetAddress (*JITReentryFn)(void *CallbackMgr, void *TrampolineId);
80
81   /// @brief Write the resolver code into the given memory. The user is be
82   ///        responsible for allocating the memory and setting permissions.
83   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
84                                 void *CallbackMgr);
85
86   /// @brief Write the requsted number of trampolines into the given memory,
87   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
88   ///        trampolines.
89   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
90                                unsigned NumTrampolines);
91
92   /// @brief Provide information about stub blocks generated by the
93   ///        makeIndirectStubsBlock function.
94   class IndirectStubsInfo {
95     friend class OrcX86_64;
96
97   public:
98     const static unsigned StubSize = 8;
99
100     IndirectStubsInfo() : NumStubs(0) {}
101     IndirectStubsInfo(IndirectStubsInfo &&Other)
102         : NumStubs(Other.NumStubs), StubsMem(std::move(Other.StubsMem)) {
103       Other.NumStubs = 0;
104     }
105     IndirectStubsInfo &operator=(IndirectStubsInfo &&Other) {
106       NumStubs = Other.NumStubs;
107       Other.NumStubs = 0;
108       StubsMem = std::move(Other.StubsMem);
109       return *this;
110     }
111
112     /// @brief Number of stubs in this block.
113     unsigned getNumStubs() const { return NumStubs; }
114
115     /// @brief Get a pointer to the stub at the given index, which must be in
116     ///        the range 0 .. getNumStubs() - 1.
117     void *getStub(unsigned Idx) const {
118       return static_cast<uint64_t *>(StubsMem.base()) + Idx;
119     }
120
121     /// @brief Get a pointer to the implementation-pointer at the given index,
122     ///        which must be in the range 0 .. getNumStubs() - 1.
123     void **getPtr(unsigned Idx) const {
124       char *PtrsBase =
125           static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
126       return reinterpret_cast<void **>(PtrsBase) + Idx;
127     }
128
129   private:
130     unsigned NumStubs;
131     sys::OwningMemoryBlock StubsMem;
132   };
133
134   /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
135   ///        the nearest page size.
136   ///
137   ///   E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
138   /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
139   /// will return a block of 1024 (2-pages worth).
140   static std::error_code emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
141                                                 unsigned MinStubs,
142                                                 void *InitialPtrVal);
143 };
144
145 } // End namespace orc.
146 } // End namespace llvm.
147
148 #endif // LLVM_EXECUTIONENGINE_ORC_ORCARCHITECTURESUPPORT_H