1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 Copyright (c) 2008-2017, Petr Kobalicek
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must not
13    claim that you wrote the original software. If you use this software
14    in a product, an acknowledgment in the product documentation would be
15    appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17    misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
20 #ifndef __PLUMED_asmjit_logging_h
21 #define __PLUMED_asmjit_logging_h
22 #ifdef __PLUMED_HAS_ASMJIT
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wpedantic"
25 // [AsmJit]
26 // Complete x86/x64 JIT and Remote Assembler for C++.
27 //
28 // [License]
29 // Zlib - See LICENSE.md file in the package.
30 
31 // [Guard]
32 #ifndef _ASMJIT_BASE_LOGGING_H
33 #define _ASMJIT_BASE_LOGGING_H
34 
35 // [Dependencies]
36 #include "./inst.h"
37 #include "./moved_string.h"
38 
39 // [Api-Begin]
40 #include "./asmjit_apibegin.h"
41 
42 namespace PLMD {
43 namespace asmjit {
44 
45 //! \addtogroup asmjit_base
46 //! \{
47 
48 #if !defined(ASMJIT_DISABLE_LOGGING)
49 
50 // ============================================================================
51 // [Forward Declarations]
52 // ============================================================================
53 
54 class CodeEmitter;
55 class Reg;
56 struct Operand_;
57 
58 #if !defined(ASMJIT_DISABLE_BUILDER)
59 class CodeBuilder;
60 class CBNode;
61 #endif // !ASMJIT_DISABLE_BUILDER
62 
63 // ============================================================================
64 // [asmjit::Logger]
65 // ============================================================================
66 
67 //! Abstract logging interface and helpers.
68 //!
69 //! This class can be inherited and reimplemented to fit into your logging
70 //! subsystem. When reimplementing use `Logger::_log()` method to log into
71 //! a custom stream.
72 //!
73 //! There are two \ref Logger implementations offered by AsmJit:
74 //!   - \ref FileLogger - allows to log into a `FILE*` stream.
75 //!   - \ref StringLogger - logs into a \ref StringBuilder.
76 class ASMJIT_VIRTAPI Logger {
77 public:
ASMJIT_NONCOPYABLE(Logger)78   ASMJIT_NONCOPYABLE(Logger)
79 
80   // --------------------------------------------------------------------------
81   // [Options]
82   // --------------------------------------------------------------------------
83 
84   //! Logger options.
85   ASMJIT_ENUM(Options) {
86     kOptionBinaryForm      = 0x00000001, //! Output instructions also in binary form.
87     kOptionImmExtended     = 0x00000002, //! Output a meaning of some immediates.
88     kOptionHexImmediate    = 0x00000004, //! Output constants in hexadecimal form.
89     kOptionHexDisplacement = 0x00000008  //! Output displacements in hexadecimal form.
90   };
91 
92   // --------------------------------------------------------------------------
93   // [Construction / Destruction]
94   // --------------------------------------------------------------------------
95 
96   //! Create a `Logger` instance.
97   ASMJIT_API Logger() noexcept;
98   //! Destroy the `Logger` instance.
99   ASMJIT_API virtual ~Logger() noexcept;
100 
101   // --------------------------------------------------------------------------
102   // [Logging]
103   // --------------------------------------------------------------------------
104 
105   //! Log `str` - must be reimplemented.
106   virtual Error _log(const char* str, size_t len) noexcept = 0;
107 
108   //! Log a string `str`, which is either null terminated or having `len` length.
109   ASMJIT_INLINE Error log(const char* str, size_t len = Globals::kInvalidIndex) noexcept { return _log(str, len); }
110   //! Log a content of a `StringBuilder` `str`.
log(const StringBuilder & str)111   ASMJIT_INLINE Error log(const StringBuilder& str) noexcept { return _log(str.getData(), str.getLength()); }
112 
113   //! Format the message by using `sprintf()` and then send to `log()`.
114   ASMJIT_API Error logf(const char* fmt, ...) noexcept;
115   //! Format the message by using `vsprintf()` and then send to `log()`.
116   ASMJIT_API Error logv(const char* fmt, va_list ap) noexcept;
117   //! Log binary data.
118   ASMJIT_API Error logBinary(const void* data, size_t size) noexcept;
119 
120   // --------------------------------------------------------------------------
121   // [Options]
122   // --------------------------------------------------------------------------
123 
124   //! Get all logger options as a single integer.
getOptions()125   ASMJIT_INLINE uint32_t getOptions() const noexcept { return _options; }
126   //! Get the given logger option.
hasOption(uint32_t option)127   ASMJIT_INLINE bool hasOption(uint32_t option) const noexcept { return (_options & option) != 0; }
addOptions(uint32_t options)128   ASMJIT_INLINE void addOptions(uint32_t options) noexcept { _options |= options; }
clearOptions(uint32_t options)129   ASMJIT_INLINE void clearOptions(uint32_t options) noexcept { _options &= ~options; }
130 
131   // --------------------------------------------------------------------------
132   // [Indentation]
133   // --------------------------------------------------------------------------
134 
135   //! Get indentation.
getIndentation()136   ASMJIT_INLINE const char* getIndentation() const noexcept { return _indentation; }
137   //! Set indentation.
138   ASMJIT_API void setIndentation(const char* indentation) noexcept;
139   //! Reset indentation.
resetIndentation()140   ASMJIT_INLINE void resetIndentation() noexcept { setIndentation(nullptr); }
141 
142   // --------------------------------------------------------------------------
143   // [Members]
144   // --------------------------------------------------------------------------
145 
146   //! Options, see \ref LoggerOption.
147   uint32_t _options;
148 
149   //! Indentation.
150   char _indentation[12];
151 };
152 
153 // ============================================================================
154 // [asmjit::FileLogger]
155 // ============================================================================
156 
157 //! Logger that can log to a `FILE*` stream.
158 class ASMJIT_VIRTAPI FileLogger : public Logger {
159 public:
160   ASMJIT_NONCOPYABLE(FileLogger)
161 
162   // --------------------------------------------------------------------------
163   // [Construction / Destruction]
164   // --------------------------------------------------------------------------
165 
166   //! Create a new `FileLogger` that logs to a `FILE` stream.
167   ASMJIT_API FileLogger(FILE* stream = nullptr) noexcept;
168   //! Destroy the `FileLogger`.
169   ASMJIT_API virtual ~FileLogger() noexcept;
170 
171   // --------------------------------------------------------------------------
172   // [Accessors]
173   // --------------------------------------------------------------------------
174 
175   //! Get the logging out put stream or null.
getStream()176   ASMJIT_INLINE FILE* getStream() const noexcept { return _stream; }
177 
178   //! Set the logging output stream to `stream` or null.
179   //!
180   //! NOTE: If the `stream` is null it will disable logging, but it won't
181   //! stop calling `log()` unless the logger is detached from the
182   //! \ref Assembler.
setStream(FILE * stream)183   ASMJIT_INLINE void setStream(FILE* stream) noexcept { _stream = stream; }
184 
185   // --------------------------------------------------------------------------
186   // [Logging]
187   // --------------------------------------------------------------------------
188 
189   ASMJIT_API Error _log(const char* buf, size_t len = Globals::kInvalidIndex) noexcept override;
190 
191   // --------------------------------------------------------------------------
192   // [Members]
193   // --------------------------------------------------------------------------
194 
195   //! C file stream.
196   FILE* _stream;
197 };
198 
199 // ============================================================================
200 // [asmjit::StringLogger]
201 // ============================================================================
202 
203 //! Logger that stores everything in an internal string buffer.
204 class ASMJIT_VIRTAPI StringLogger : public Logger {
205 public:
206   ASMJIT_NONCOPYABLE(StringLogger)
207 
208   // --------------------------------------------------------------------------
209   // [Construction / Destruction]
210   // --------------------------------------------------------------------------
211 
212   //! Create new `StringLogger`.
213   ASMJIT_API StringLogger() noexcept;
214   //! Destroy the `StringLogger`.
215   ASMJIT_API virtual ~StringLogger() noexcept;
216 
217   // --------------------------------------------------------------------------
218   // [Accessors]
219   // --------------------------------------------------------------------------
220 
221   //! Get `char*` pointer which represents the resulting string.
222   //!
223   //! The pointer is owned by `StringLogger`, it can't be modified or freed.
getString()224   ASMJIT_INLINE const char* getString() const noexcept { return _stringBuilder.getData(); }
225   //! Clear the resulting string.
clearString()226   ASMJIT_INLINE void clearString() noexcept { _stringBuilder.clear(); }
227 
228   //! Get the length of the string returned by `getString()`.
getLength()229   ASMJIT_INLINE size_t getLength() const noexcept { return _stringBuilder.getLength(); }
230 
231   // --------------------------------------------------------------------------
232   // [Logging]
233   // --------------------------------------------------------------------------
234 
235   ASMJIT_API Error _log(const char* buf, size_t len = Globals::kInvalidIndex) noexcept override;
236 
237   // --------------------------------------------------------------------------
238   // [Members]
239   // --------------------------------------------------------------------------
240 
241   //! Output string.
242   StringBuilder _stringBuilder;
243 };
244 
245 // ============================================================================
246 // [asmjit::Logging]
247 // ============================================================================
248 
249 struct Logging {
250   ASMJIT_API static Error formatRegister(
251     StringBuilder& sb,
252     uint32_t logOptions,
253     const CodeEmitter* emitter,
254     uint32_t archType,
255     uint32_t regType,
256     uint32_t regId) noexcept;
257 
258   ASMJIT_API static Error formatLabel(
259     StringBuilder& sb,
260     uint32_t logOptions,
261     const CodeEmitter* emitter,
262     uint32_t labelId) noexcept;
263 
264   ASMJIT_API static Error formatOperand(
265     StringBuilder& sb,
266     uint32_t logOptions,
267     const CodeEmitter* emitter,
268     uint32_t archType,
269     const Operand_& op) noexcept;
270 
271   ASMJIT_API static Error formatInstruction(
272     StringBuilder& sb,
273     uint32_t logOptions,
274     const CodeEmitter* emitter,
275     uint32_t archType,
276     const Inst::Detail& detail, const Operand_* opArray, uint32_t opCount) noexcept;
277 
278 #if !defined(ASMJIT_DISABLE_BUILDER)
279   ASMJIT_API static Error formatNode(
280     StringBuilder& sb,
281     uint32_t logOptions,
282     const CodeBuilder* cb,
283     const CBNode* node_) noexcept;
284 #endif // !ASMJIT_DISABLE_BUILDER
285 
286 // Only used by AsmJit internals, not available to users.
287 #if defined(ASMJIT_EXPORTS)
288   enum {
289     // Has to be big to be able to hold all metadata compiler can assign to a
290     // single instruction.
291     kMaxCommentLength = 512,
292     kMaxInstLength = 40,
293     kMaxBinaryLength = 26
294   };
295 
296   static Error formatLine(
297     StringBuilder& sb,
298     const uint8_t* binData, size_t binLen, size_t dispLen, size_t imLen, const char* comment) noexcept;
299 #endif // ASMJIT_EXPORTS
300 };
301 #else
302 class Logger;
303 #endif // !ASMJIT_DISABLE_LOGGING
304 
305 //! \}
306 
307 } // asmjit namespace
308 } // namespace PLMD
309 
310 // [Api-End]
311 #include "./asmjit_apiend.h"
312 
313 // [Guard]
314 #endif // _ASMJIT_BASE_LOGGER_H
315 #pragma GCC diagnostic pop
316 #endif // __PLUMED_HAS_ASMJIT
317 #endif
318