"tests/TestRMSDForce.h" did not exist on "70ba177d431a7f8fa5039266c0f6035f367e530a"
codegen.h 10.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.

// [Guard]
#ifndef _ASMJIT_BASE_CODEGEN_H
#define _ASMJIT_BASE_CODEGEN_H

// [Dependencies - AsmJit]
#include "../base/error.h"
#include "../base/logger.h"
#include "../base/runtime.h"
#include "../base/zone.h"

// [Api-Begin]
#include "../apibegin.h"

namespace asmjit {

//! \addtogroup asmjit_base_general
//! \{

// ============================================================================
26
// [asmjit::CodeGenFeatures]
27
28
29
// ============================================================================

//! Features of \ref CodeGen.
30
ASMJIT_ENUM(CodeGenFeatures) {
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  //! Emit optimized code-alignment sequences (`Assembler` and `Compiler`).
  //!
  //! Default `true`.
  //!
  //! X86/X64
  //! -------
  //!
  //! Default align sequence used by X86/X64 architecture is one-byte 0x90
  //! opcode that is mostly shown by disassemblers as nop. However there are
  //! more optimized align sequences for 2-11 bytes that may execute faster.
  //! If this feature is enabled asmjit will generate specialized sequences
  //! for alignment between 1 to 11 bytes. Also when `X86Compiler` is used,
  //! it can add REX prefixes into the code to make some instructions greater
  //! so no alignment sequence is needed.
  kCodeGenOptimizedAlign = 0,

  //! Emit jump-prediction hints (`Assembler` and `Compiler`).
  //!
  //! Default `false`.
  //!
  //! X86/X64
  //! -------
  //!
  //! Jump prediction is usually based on the direction of the jump. If the
  //! jump is backward it is usually predicted as taken; and if the jump is
  //! forward it is usually predicted as not-taken. The reason is that loops
  //! generally use backward jumps and conditions usually use forward jumps.
  //! However this behavior can be overridden by using instruction prefixes.
  //! If this option is enabled these hints will be emitted.
  //!
  //! This feature is disabled by default, because the only processor that
  //! used to take into consideration prediction hints was P4. Newer processors
  //! implement heuristics for branch prediction that ignores any static hints.
  kCodeGenPredictedJumps = 1,

  //! Schedule instructions so they can be executed faster (`Compiler` only).
  //!
  //! Default `false` - has to be explicitly enabled as the scheduler needs
  //! some time to run.
  //!
  //! X86/X64
  //! -------
  //!
  //! If scheduling is enabled AsmJit will try to reorder instructions to
  //! minimize dependency chain. Scheduler always runs after the registers are
  //! allocated so it doesn't change count of register allocs/spills.
  //!
  //! This feature is highly experimental and untested.
  kCodeGenEnableScheduler = 2
};

// ============================================================================
83
// [asmjit::AlignMode]
84
85
86
// ============================================================================

//! Code aligning mode.
87
ASMJIT_ENUM(AlignMode) {
88
89
90
91
92
93
94
  //! Align by emitting a sequence that can be executed (code).
  kAlignCode = 0,
  //! Align by emitting sequence that shouldn't be executed (data).
  kAlignData = 1
};

// ============================================================================
95
// [asmjit::RelocMode]
96
97
98
// ============================================================================

//! Relocation mode.
99
ASMJIT_ENUM(RelocMode) {
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
  //! Relocate an absolute address to an absolute address.
  kRelocAbsToAbs = 0,
  //! Relocate a relative address to an absolute address.
  kRelocRelToAbs = 1,
  //! Relocate an absolute address to a relative address.
  kRelocAbsToRel = 2,
  //! Relocate an absolute address to a relative address or use trampoline.
  kRelocTrampoline = 3
};

// ============================================================================
// [asmjit::CodeGen]
// ============================================================================

//! Abstract class defining basics of \ref Assembler and \ref Compiler.
struct ASMJIT_VCLASS CodeGen {
  ASMJIT_NO_COPY(CodeGen)

  // --------------------------------------------------------------------------
  // [Construction / Destruction]
  // --------------------------------------------------------------------------

  //! Create a new `CodeGen` instance.
  ASMJIT_API CodeGen(Runtime* runtime);
  //! Destroy the `CodeGen` instance.
  ASMJIT_API virtual ~CodeGen();

  // --------------------------------------------------------------------------
  // [Runtime]
  // --------------------------------------------------------------------------

  //! Get runtime.
  ASMJIT_INLINE Runtime* getRuntime() const {
    return _runtime;
  }

  // --------------------------------------------------------------------------
  // [Logger]
  // --------------------------------------------------------------------------

#if !defined(ASMJIT_DISABLE_LOGGER)
  //! Get whether the code generator has a logger.
  ASMJIT_INLINE bool hasLogger() const {
    return _logger != NULL;
  }

  //! Get logger.
  ASMJIT_INLINE Logger* getLogger() const {
    return _logger;
  }

  //! Set logger to `logger`.
  ASMJIT_API Error setLogger(Logger* logger);
#endif // !ASMJIT_DISABLE_LOGGER

  // --------------------------------------------------------------------------
  // [Arch]
  // --------------------------------------------------------------------------

  //! Get target architecture.
  ASMJIT_INLINE uint32_t getArch() const {
    return _arch;
  }

  //! Get default register size (4 or 8 bytes).
  ASMJIT_INLINE uint32_t getRegSize() const {
    return _regSize;
  }

  // --------------------------------------------------------------------------
  // [BaseAddress]
  // --------------------------------------------------------------------------

  //! Get whether the code-generator has a base address.
  //!
  //! \sa \ref getBaseAddress()
  ASMJIT_INLINE bool hasBaseAddress() const {
    return _baseAddress != kNoBaseAddress;
  }

  //! Get the base address.
  ASMJIT_INLINE Ptr getBaseAddress() const {
    return _baseAddress;
  }

  //! Set the base address to `baseAddress`.
  ASMJIT_INLINE void setBaseAddress(Ptr baseAddress) {
    _baseAddress = baseAddress;
  }

  //! Reset the base address.
  ASMJIT_INLINE void resetBaseAddress() {
    setBaseAddress(kNoBaseAddress);
  }

  // --------------------------------------------------------------------------
  // [LastError / ErrorHandler]
  // --------------------------------------------------------------------------

  //! Get last error code.
  ASMJIT_INLINE Error getError() const {
    return _error;
  }

  //! Set last error code and propagate it through the error handler.
  ASMJIT_API Error setError(Error error, const char* message = NULL);

  //! Clear the last error code.
  ASMJIT_INLINE void resetError() {
    _error = kErrorOk;
  }

  //! Get error handler.
  ASMJIT_INLINE ErrorHandler* getErrorHandler() const {
    return _errorHandler;
  }

  //! Set error handler.
  ASMJIT_API Error setErrorHandler(ErrorHandler* handler);

  //! Clear error handler.
  ASMJIT_INLINE Error resetErrorHandler() {
    return setErrorHandler(NULL);
  }

  // --------------------------------------------------------------------------
  // [Code-Generation Features]
  // --------------------------------------------------------------------------

  //! Get code-generator `feature`.
  ASMJIT_INLINE bool hasFeature(uint32_t feature) const {
    ASMJIT_ASSERT(feature < 32);

    return (_features & (1 << feature)) != 0;
  }

  //! Set code-generator `feature` to `value`.
  ASMJIT_INLINE void setFeature(uint32_t feature, bool value) {
    ASMJIT_ASSERT(feature < 32);

    feature = static_cast<uint32_t>(value) << feature;
    _features = (_features & ~feature) | feature;
  }

  //! Get code-generator features.
  ASMJIT_INLINE uint32_t getFeatures() const {
    return _features;
  }

  //! Set code-generator features.
  ASMJIT_INLINE void setFeatures(uint32_t features) {
    _features = features;
  }

  // --------------------------------------------------------------------------
  // [Instruction Options]
  // --------------------------------------------------------------------------

  //! Get options of the next instruction.
  ASMJIT_INLINE uint32_t getInstOptions() const {
    return _instOptions;
  }

  //! Get options of the next instruction and reset them.
  ASMJIT_INLINE uint32_t getInstOptionsAndReset() {
    uint32_t instOptions = _instOptions;
    _instOptions = 0;
    return instOptions;
  };

  //! Set options of the next instruction.
  ASMJIT_INLINE void setInstOptions(uint32_t instOptions) {
    _instOptions = instOptions;
  }

  // --------------------------------------------------------------------------
  // [Make]
  // --------------------------------------------------------------------------

  //! Make is a convenience method to make and relocate the current code and
  //! add it to the associated `Runtime`.
  //!
  //! What is needed is only to cast the returned pointer to your function type
  //! and then use it. If there was an error during `make()` `NULL` is returned
  //! and the last error code can be obtained by calling `getError()`.
  virtual void* make() = 0;

  // --------------------------------------------------------------------------
  // [Members]
  // --------------------------------------------------------------------------

  //! Target runtime.
  Runtime* _runtime;

#if !defined(ASMJIT_DISABLE_LOGGER)
  //! Logger.
  Logger* _logger;
#else
  //! \internal
  //!
  //! Makes libraries built with or without logging support binary compatible.
  void* _logger;
#endif // ASMJIT_DISABLE_LOGGER

  //! Error handler, called by \ref setError().
  ErrorHandler* _errorHandler;

  //! Base address (-1 if unknown/not used).
  Ptr _baseAddress;

  //! Target architecture ID.
  uint8_t _arch;
  //! Target architecture GP register size in bytes (4 or 8).
  uint8_t _regSize;
  //! \internal
  uint16_t _reserved;

  //! Code-Generation features, used by \ref hasFeature() and \ref setFeature().
  uint32_t _features;
  //! Options affecting the next instruction.
  uint32_t _instOptions;

  //! Last error code.
  uint32_t _error;

  //! Base zone.
  Zone _baseZone;
};

//! \}

} // asmjit namespace

// [Api-End]
#include "../apiend.h"

// [Guard]
#endif // _ASMJIT_BASE_CODEGEN_H