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 #ifdef __PLUMED_HAS_ASMJIT
21 #pragma GCC diagnostic push
22 #pragma GCC diagnostic ignored "-Wpedantic"
23 // [AsmJit]
24 // Complete x86/x64 JIT and Remote Assembler for C++.
25 //
26 // [License]
27 // Zlib - See LICENSE.md file in the package.
28
29 // [Export]
30 #define ASMJIT_EXPORTS
31
32 // [Dependencies]
33 #include "./moved_string.h"
34 #include "./utils.h"
35
36 // [Api-Begin]
37 #include "./asmjit_apibegin.h"
38
39 namespace PLMD {
40 namespace asmjit {
41
42 // ============================================================================
43 // [asmjit::StringBuilder - Construction / Destruction]
44 // ============================================================================
45
46 // Should be placed in read-only memory.
47 static const char StringBuilder_empty[4] = { 0 };
48
StringBuilder()49 StringBuilder::StringBuilder() noexcept
50 : _data(const_cast<char*>(StringBuilder_empty)),
51 _length(0),
52 _capacity(0),
53 _canFree(false) {}
54
~StringBuilder()55 StringBuilder::~StringBuilder() noexcept {
56 if (_canFree)
57 Internal::releaseMemory(_data);
58 }
59
60 // ============================================================================
61 // [asmjit::StringBuilder - Prepare / Reserve]
62 // ============================================================================
63
prepare(uint32_t op,size_t len)64 ASMJIT_FAVOR_SIZE char* StringBuilder::prepare(uint32_t op, size_t len) noexcept {
65 if (op == kStringOpSet) {
66 // We don't care here, but we can't return a null pointer since it indicates
67 // failure in memory allocation.
68 if (len == 0) {
69 if (_data != StringBuilder_empty)
70 _data[0] = 0;
71
72 _length = 0;
73 return _data;
74 }
75
76 if (_capacity < len) {
77 if (len >= IntTraits<size_t>::maxValue() - sizeof(intptr_t) * 2)
78 return nullptr;
79
80 size_t to = Utils::alignTo<size_t>(len, sizeof(intptr_t));
81 if (to < 256 - sizeof(intptr_t))
82 to = 256 - sizeof(intptr_t);
83
84 char* newData = static_cast<char*>(Internal::allocMemory(to + sizeof(intptr_t)));
85 if (!newData) {
86 clear();
87 return nullptr;
88 }
89
90 if (_canFree)
91 Internal::releaseMemory(_data);
92
93 _data = newData;
94 _capacity = to + sizeof(intptr_t) - 1;
95 _canFree = true;
96 }
97
98 _data[len] = 0;
99 _length = len;
100
101 ASMJIT_ASSERT(_length <= _capacity);
102 return _data;
103 }
104 else {
105 // We don't care here, but we can't return a null pointer since it indicates
106 // failure of memory allocation.
107 if (len == 0)
108 return _data + _length;
109
110 // Overflow.
111 if (IntTraits<size_t>::maxValue() - sizeof(intptr_t) * 2 - _length < len)
112 return nullptr;
113
114 size_t after = _length + len;
115 if (_capacity < after) {
116 size_t to = _capacity;
117
118 if (to < 256)
119 to = 256;
120
121 while (to < 1024 * 1024 && to < after)
122 to *= 2;
123
124 if (to < after) {
125 to = after;
126 if (to < (IntTraits<size_t>::maxValue() - 1024 * 32))
127 to = Utils::alignTo<size_t>(to, 1024 * 32);
128 }
129
130 to = Utils::alignTo<size_t>(to, sizeof(intptr_t));
131 char* newData = static_cast<char*>(Internal::allocMemory(to + sizeof(intptr_t)));
132 if (!newData) return nullptr;
133
134 ::memcpy(newData, _data, _length);
135 if (_canFree)
136 Internal::releaseMemory(_data);
137
138 _data = newData;
139 _capacity = to + sizeof(intptr_t) - 1;
140 _canFree = true;
141 }
142
143 char* ret = _data + _length;
144 _data[after] = 0;
145 _length = after;
146
147 ASMJIT_ASSERT(_length <= _capacity);
148 return ret;
149 }
150 }
151
reserve(size_t to)152 ASMJIT_FAVOR_SIZE Error StringBuilder::reserve(size_t to) noexcept {
153 if (_capacity >= to)
154 return kErrorOk;
155
156 if (to >= IntTraits<size_t>::maxValue() - sizeof(intptr_t) * 2)
157 return DebugUtils::errored(kErrorNoHeapMemory);
158
159 to = Utils::alignTo<size_t>(to, sizeof(intptr_t));
160 char* newData = static_cast<char*>(Internal::allocMemory(to + sizeof(intptr_t)));
161
162 if (!newData)
163 return DebugUtils::errored(kErrorNoHeapMemory);
164
165 ::memcpy(newData, _data, _length + 1);
166 if (_canFree)
167 Internal::releaseMemory(_data);
168
169 _data = newData;
170 _capacity = to + sizeof(intptr_t) - 1;
171 _canFree = true;
172 return kErrorOk;
173 }
174
175 // ============================================================================
176 // [asmjit::StringBuilder - Clear]
177 // ============================================================================
178
clear()179 void StringBuilder::clear() noexcept {
180 if (_data != StringBuilder_empty)
181 _data[0] = 0;
182 _length = 0;
183 }
184
185 // ============================================================================
186 // [asmjit::StringBuilder - Methods]
187 // ============================================================================
188
_opString(uint32_t op,const char * str,size_t len)189 Error StringBuilder::_opString(uint32_t op, const char* str, size_t len) noexcept {
190 if (len == Globals::kInvalidIndex)
191 len = str ? ::strlen(str) : static_cast<size_t>(0);
192
193 char* p = prepare(op, len);
194 if (!p) return DebugUtils::errored(kErrorNoHeapMemory);
195
196 ::memcpy(p, str, len);
197 return kErrorOk;
198 }
199
_opChar(uint32_t op,char c)200 Error StringBuilder::_opChar(uint32_t op, char c) noexcept {
201 char* p = prepare(op, 1);
202 if (!p) return DebugUtils::errored(kErrorNoHeapMemory);
203
204 *p = c;
205 return kErrorOk;
206 }
207
_opChars(uint32_t op,char c,size_t n)208 Error StringBuilder::_opChars(uint32_t op, char c, size_t n) noexcept {
209 char* p = prepare(op, n);
210 if (!p) return DebugUtils::errored(kErrorNoHeapMemory);
211
212 ::memset(p, c, n);
213 return kErrorOk;
214 }
215
216 static const char StringBuilder_numbers[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
217
_opNumber(uint32_t op,uint64_t i,uint32_t base,size_t width,uint32_t flags)218 Error StringBuilder::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, uint32_t flags) noexcept {
219 if (base < 2 || base > 36)
220 base = 10;
221
222 char buf[128];
223 char* p = buf + ASMJIT_ARRAY_SIZE(buf);
224
225 uint64_t orig = i;
226 char sign = '\0';
227
228 // --------------------------------------------------------------------------
229 // [Sign]
230 // --------------------------------------------------------------------------
231
232 if ((flags & kStringFormatSigned) != 0 && static_cast<int64_t>(i) < 0) {
233 i = static_cast<uint64_t>(-static_cast<int64_t>(i));
234 sign = '-';
235 }
236 else if ((flags & kStringFormatShowSign) != 0) {
237 sign = '+';
238 }
239 else if ((flags & kStringFormatShowSpace) != 0) {
240 sign = ' ';
241 }
242
243 // --------------------------------------------------------------------------
244 // [Number]
245 // --------------------------------------------------------------------------
246
247 do {
248 uint64_t d = i / base;
249 uint64_t r = i % base;
250
251 *--p = StringBuilder_numbers[r];
252 i = d;
253 } while (i);
254
255 size_t numberLength = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p);
256
257 // --------------------------------------------------------------------------
258 // [Alternate Form]
259 // --------------------------------------------------------------------------
260
261 if ((flags & kStringFormatAlternate) != 0) {
262 if (base == 8) {
263 if (orig != 0)
264 *--p = '0';
265 }
266 if (base == 16) {
267 *--p = 'x';
268 *--p = '0';
269 }
270 }
271
272 // --------------------------------------------------------------------------
273 // [Width]
274 // --------------------------------------------------------------------------
275
276 if (sign != 0)
277 *--p = sign;
278
279 if (width > 256)
280 width = 256;
281
282 if (width <= numberLength)
283 width = 0;
284 else
285 width -= numberLength;
286
287 // --------------------------------------------------------------------------
288 // Write]
289 // --------------------------------------------------------------------------
290
291 size_t prefixLength = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p) - numberLength;
292 char* data = prepare(op, prefixLength + width + numberLength);
293
294 if (!data)
295 return DebugUtils::errored(kErrorNoHeapMemory);
296
297 ::memcpy(data, p, prefixLength);
298 data += prefixLength;
299
300 ::memset(data, '0', width);
301 data += width;
302
303 ::memcpy(data, p + prefixLength, numberLength);
304 return kErrorOk;
305 }
306
_opHex(uint32_t op,const void * data,size_t len)307 Error StringBuilder::_opHex(uint32_t op, const void* data, size_t len) noexcept {
308 char* dst;
309
310 if (len >= IntTraits<size_t>::maxValue() / 2 || !(dst = prepare(op, len * 2)))
311 return DebugUtils::errored(kErrorNoHeapMemory);;
312
313 const char* src = static_cast<const char*>(data);
314 for (size_t i = 0; i < len; i++, dst += 2, src++) {
315 dst[0] = StringBuilder_numbers[(src[0] >> 4) & 0xF];
316 dst[1] = StringBuilder_numbers[(src[0] ) & 0xF];
317 }
318 return kErrorOk;
319 }
320
_opVFormat(uint32_t op,const char * fmt,va_list ap)321 Error StringBuilder::_opVFormat(uint32_t op, const char* fmt, va_list ap) noexcept {
322 char buf[1024];
323
324 vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf), fmt, ap);
325 buf[ASMJIT_ARRAY_SIZE(buf) - 1] = '\0';
326
327 return _opString(op, buf);
328 }
329
setFormat(const char * fmt,...)330 Error StringBuilder::setFormat(const char* fmt, ...) noexcept {
331 bool result;
332
333 va_list ap;
334 va_start(ap, fmt);
335 result = _opVFormat(kStringOpSet, fmt, ap);
336 va_end(ap);
337
338 return result;
339 }
340
appendFormat(const char * fmt,...)341 Error StringBuilder::appendFormat(const char* fmt, ...) noexcept {
342 bool result;
343
344 va_list ap;
345 va_start(ap, fmt);
346 result = _opVFormat(kStringOpAppend, fmt, ap);
347 va_end(ap);
348
349 return result;
350 }
351
eq(const char * str,size_t len) const352 bool StringBuilder::eq(const char* str, size_t len) const noexcept {
353 const char* aData = _data;
354 const char* bData = str;
355
356 size_t aLength = _length;
357 size_t bLength = len;
358
359 if (bLength == Globals::kInvalidIndex) {
360 size_t i;
361 for (i = 0; i < aLength; i++)
362 if (aData[i] != bData[i] || bData[i] == 0)
363 return false;
364 return bData[i] == 0;
365 }
366 else {
367 if (aLength != bLength)
368 return false;
369 return ::memcmp(aData, bData, aLength) == 0;
370 }
371 }
372
373 } // asmjit namespace
374 } // namespace PLMD
375
376 // [Api-End]
377 #include "./asmjit_apiend.h"
378 #pragma GCC diagnostic pop
379 #endif // __PLUMED_HAS_ASMJIT
380