ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
Instruction.h
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// This file is part of ETISS. It is licensed under the BSD 3-Clause License; you may not use this file except in
4// compliance with the License. You should have received a copy of the license along with this project. If not, see the
5// LICENSE file.
21#ifndef ETISS_INCLUDE_INSTRUCTION_H_
22#define ETISS_INCLUDE_INSTRUCTION_H_
23
24#include "etiss/Misc.h"
25
26#include <climits>
27#include <cstring>
28#include <iomanip>
29#include <sstream>
30#include <stdexcept>
31#include <string>
32#include <boost/dynamic_bitset.hpp>
33
34namespace etiss
35{
36
37namespace instr
38{
39
40typedef uint32_t I;
41
45class Buffer
46{
47 public:
48 I *d_;
49 unsigned intcount_;
50
51 public:
52 Buffer() : d_(nullptr), intcount_(0) {}
53 Buffer(const Buffer &o) : d_(new I[o.intcount_]), intcount_(o.intcount_) { *this = o; }
54 Buffer(Buffer &&o) : d_(o.d_), intcount_(o.intcount_) { o.d_ = nullptr; }
55 Buffer(unsigned intcount) : d_(new I[intcount]), intcount_(intcount)
56 {
57 for (unsigned i = 0; i < intcount_; i++)
58 d_[i] = 0;
59 }
60 Buffer(unsigned intcount, I val) : Buffer(intcount) { *d_ = val; }
61 ~Buffer() { clear(); }
62
64 {
65 if (o.intcount_ != intcount_)
66 throw std::runtime_error("operator= called with incompatible bit array");
67 for (unsigned i = 0; i < intcount_; i++)
68 d_[i] = o.d_[i];
69 return *this;
70 }
71
73 {
74 clear();
75 intcount_ = o.intcount_;
76 d_ = o.d_;
77 o.d_ = nullptr;
78 return *this;
79 }
80
81 void clear()
82 {
83 if (d_)
84 delete[] d_;
85 }
91 char *internalBuffer();
95 unsigned internalBufferSize();
96
97 I data() { return *d_; }
102 void recoverFromEndianness(unsigned alignment, endian_t endianness);
103};
104
108typedef std::set<Instruction *> Node;
109
113class BitArray : public boost::dynamic_bitset<>
114{
115 private:
116 typedef boost::dynamic_bitset<> super;
117
118 public:
119 using super::dynamic_bitset;
120 BitArray(const super &a) : super(a) {} // hack for parent's explicit constructors
121
125 unsigned byteCount() const;
129 unsigned intCount() const;
133 void set_value(size_type width, unsigned long value);
134 void set_value(unsigned long value);
138 BitArray get_range(size_type end, size_type start) const;
142 void set_range(unsigned long val, size_type end, size_type start);
149 static std::vector<BitArray> permutate(const BitArray &input, std::vector<size_type> indexes);
153 std::string to_string() const;
154};
155
162{
163 public:
164 etiss_del_como(BitArrayRange) private : BitArray::size_type startpos;
165 BitArray::size_type endpos;
166
167 public:
172 BitArrayRange(unsigned endindex_included, unsigned startindex_included);
173
178 I read(const BitArray &ba);
182 void write(BitArray &ba, I val);
186 BitArray::size_type start();
191 BitArray::size_type end();
192};
193
225{
226 public:
229 template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type>
236 OPCode(unsigned width, const T code, const T mask) : code_(width, code & mask), mask_(width, mask)
237 {
238#if DEBUG
239 if ((code & mask) != code)
240 {
241 etiss::log(etiss::WARNING, "etiss::instr::OPCode constructed with mismatched code and mask");
242 }
243 if (width != 16 && width != 32 && width != 64 && width != 128 && width != 256)
244 {
245 etiss::log(etiss::VERBOSE, std::string("OPCode with unusual width: ") + toString(width) +
246 "[width must be given in bits and is usually 16,32,64,128,256 bits long]");
247 }
248#endif
249 }
250
254 OPCode(const BitArray &code, const BitArray &mask);
255
259 OPCode(const OPCode &cpy);
260
265 bool operator<(const OPCode &o) const;
266 inline bool operator==(const OPCode &o) const { return !((*this < o) || (o < *this)); }
267 inline bool operator!=(const OPCode &o) const { return !((*this) == o); }
268};
269
273struct less
274{
275 bool operator()(const OPCode *const &o1, const OPCode *const &o2) const;
276};
277
290{
291
292 public:
294
295 inline InstructionContext()
296 {
297 }
298
301 unsigned instr_width_;
308 unsigned &ufield(std::string name);
309 template <typename T>
315 uint64_t &ufield(const T &plugin, std::string name)
316 {
317 return lufields_[&plugin][name];
318 }
321
322 public:
324 // common fields
326
327 private:
328 std::map<std::string, unsigned> ufields_;
330 std::map<void *, std::map<std::string, uint64_t>>
332};
333
346{
347 private:
348 std::list<std::tuple<std::function<bool(BitArray &, etiss::CodeSet &, InstructionContext &)>, uint32_t,
349 std::set<uint32_t>>>
352 std::set<uint32_t> groups_;
353 std::function<std::string(BitArray &, Instruction &)> printer_;
354
355 public:
357
358 enum class BUILTINGROUP : uint32_t {
359 CPUTIMEUPDATE = 1 << 0
361 };
362
363 const BitArray::size_type width;
365 const std::string name_;
366
367 static std::string printASMSimple(BitArray &ba, Instruction &instr);
368
369 Instruction(const OPCode &opc, const std::string &name);
370 template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type>
371 Instruction(unsigned width, const T code, const T mask, const std::string &name)
372 : builtinGroups_(0), printer_(printASMSimple), width(width), opc_(OPCode(width, code, mask)), name_(name)
373 {
374 }
375 virtual std::string print(std::string indent, I pos, unsigned pfillwidth, bool printunused = false);
376 bool addCallback(std::function<bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback,
377 uint32_t builtinGroups, const std::set<uint32_t> &groups = std::set<uint32_t>());
378 bool translate(BitArray &, CodeSet &cs, InstructionContext &context);
380 std::set<uint32_t> &presentGroups();
381 std::string printASM(BitArray &);
382 void setASMPrinter(std::function<std::string(BitArray &, Instruction &)> printer);
383 inline std::string toString() const { return name_; }
384};
385
397{
398 public:
400
401 VariableInstructionSet &parent_;
402 const std::string name_;
403 const unsigned width_;
404 const unsigned chunk_size;
405 InstructionSet(VariableInstructionSet &parent, unsigned width, const std::string &name, unsigned c_size = 4);
407
408 Instruction *get(const OPCode &key);
409 Instruction &open(const OPCode &key, const std::string &name);
410 Instruction *create(const OPCode &key, const std::string &name);
411
412 template <typename T>
413 Instruction &open(T code, T val, const std::string &name)
414 {
415 return open(OPCode(width_, code, val), name);
416 }
417
418 bool compile();
419 bool compile(Node *node, BitArray code, Instruction *instr);
420
423
424 std::string print(std::string prefix, bool printunused = false);
425
427
428 void foreach (std::function<void(Instruction &)> func);
429
430 size_t size();
431
432 inline std::string toString() const { return name_; }
433
434 private:
435 std::map<const OPCode *, Instruction *, etiss::instr::less> instrmap_;
436
437 Node **root_; // holds the entry of the bucket tree in decoding and compilition algorithm
438
440};
441
455{
456 private:
457 std::map<unsigned, InstructionSet *> ismap_;
458
459 public:
461 unsigned width_;
462 const std::string archname_;
464
465 public:
467
470 bool compile();
471
472 InstructionSet *get(unsigned width);
473 InstructionSet *create(unsigned width, const std::string &name = std::string());
474 InstructionSet &open(unsigned width, const std::string &name = std::string());
475 inline InstructionSet *getMain() { return get(width_); }
476 inline InstructionSet *createMain(const std::string &name = std::string()) { return create(width_); }
477 inline InstructionSet &openMain(const std::string &name = std::string()) { return open(width_); }
478
479 template <typename T>
480 Instruction &open(unsigned bits, T code, T mask, const char *name)
481 {
482#if DEBUG
483 unsigned bytes = bits >> 3;
484 if (bytes * 8 != bits)
485 {
486 etiss_log(ERROR, "Invalid bit count");
487 throw std::runtime_error();
488 }
489#endif
490 return open(bits).open<T>(bits, code, mask, std::string(name));
491 }
492
493 void foreach (std::function<void(InstructionSet &)> func);
494
495 std::string print(std::string prefix = std::string());
496};
497
517{
518 private:
519 std::map<uint32_t, std::string> modetostring_;
520 std::map<std::string, uint32_t> stringtomode_;
521 std::map<uint32_t, VariableInstructionSet *> vismap_;
522 std::map<VariableInstructionSet *, uint32_t> invvismap_;
523
524 public:
525 const std::string archname_;
526
527 public:
529
530 ModedInstructionSet(const std::string &name);
532
534 VariableInstructionSet *create(uint32_t mode, unsigned width, const std::string &name = std::string());
538 VariableInstructionSet &open(uint32_t mode, unsigned width, const std::string &name = std::string());
539
540 template <typename T>
541 Instruction &open(uint32_t mode, unsigned width, unsigned bits, T code, T mask, const char *instrname)
542 {
543 return open(mode, width).open<T>(bits, code, mask, instrname);
544 }
545
547 inline uint32_t getMode(VariableInstructionSet &vis) { return getMode(&vis); }
548
549 void foreach (std::function<void(VariableInstructionSet &)> call);
550
551 bool compile();
552
553 std::string print(std::string prefix = std::string());
554};
555
560{
561 private:
562 std::set<InstructionClass *> classes_;
563 template <typename... T>
564 void add(InstructionClass &klass, T &...args)
565 {
566 classes_.insert(&klass);
567 add(args...);
568 }
569 inline void add() {}
570
571 public:
573
574 const std::string name_; // e.g. ARMv6-M
575 template <typename... T>
576 inline InstructionCollection(const std::string &name, InstructionClass &class1, T &...otherclasses) : name_(name)
577 {
578 add(class1, otherclasses...);
579 }
580 inline void foreach (std::function<void(InstructionClass &)> call)
581 {
582 for (auto iter = classes_.begin(); iter != classes_.end(); iter++)
583 {
584 call(**iter);
585 }
586 }
587 void addTo(ModedInstructionSet &set, bool &ok);
588};
593{
594 private:
595 std::set<InstructionGroup *> groups_;
596 template <typename... T>
597 void add(InstructionGroup &group, T &...args)
598 {
599 groups_.insert(&group);
600 add(args...);
601 }
602 inline void add() {}
603
604 public:
605 const unsigned mode_; // e.g. 0 for ARM 1 for thumb
606 const std::string name_; // e.g. ARM
607 const unsigned width_; // most common read width (fastest)
608 public:
610
611 template <typename... T>
612 InstructionClass(unsigned mode, const std::string &name, unsigned width, InstructionGroup &group1,
615 {
617 }
618 inline void foreach (std::function<void(InstructionGroup &)> call)
619 {
620 for (auto iter = groups_.begin(); iter != groups_.end(); iter++)
621 {
622 call(**iter);
623 }
624 }
625 void addTo(VariableInstructionSet &set, bool &ok);
626};
627
632{
634
635 private:
636 std::set<InstructionDefinition *> defs_;
637
638 public:
639 const std::string name_; // e.g. thumb / thumb-2
640 const unsigned width_; // e.g. 16/32 bits
641 public:
643
644 inline InstructionGroup(const std::string &name, unsigned width)
645 : name_(name), width_(width)
646 {
647 }
648 inline void foreach (std::function<void(InstructionDefinition &)> call)
649 {
650 for (auto iter = defs_.begin(); iter != defs_.end(); iter++)
651 {
652 call(**iter);
653 }
654 }
655 void addTo(InstructionSet &set, bool &ok);
656 inline std::string toString() const { return name_; }
657};
658
663{
664 public:
666 const std::string name_;
669 const std::function<std::string(BitArray &, Instruction &)> ASMprinter_;
671
672 public:
674
675 template <typename T>
676 InstructionDefinition(InstructionGroup &ig, const std::string &name, T code, T mask,
678 uint32_t builtinGroups, std::function<std::string(BitArray &, Instruction &)> ASMprinter)
679 : group_(ig)
681 , opc_(ig.width_, code, mask)
685 {
686 if (!callback)
687 {
688 etiss_log(FATALERROR, (std::string("Instruction defined without a function callback: ") + name));
689 return;
690 }
691 group_.defs_.insert(this);
692 }
694 {
695 // group_.defs_.erase(this); // removed since InstructionDefinition should not be deleted during execution
696 }
697 void addTo(Instruction &set, bool &ok);
698 inline std::string toString() const { return group_.name_ + ":" + name_; }
699};
700
701#if __cplusplus >= 201103L
702uint32_t operator"" _i32(const char *s);
703#endif
704
705uint32_t parse_i32(const char *s);
706
707template <typename T_>
742typename std::enable_if<std::is_integral<T_>::value, typename std::make_unsigned<T_>::type>::type parse_i(
743 const char *s, bool *good = 0)
744{
745 if (good)
746 *good = true;
747 typedef typename std::make_unsigned<T_>::type U;
748 unsigned shifted = 0;
749 unsigned pos = 0;
750 int mode = 0;
751 U tmp = 0;
752 U ret = 0;
753 U mask = 0;
754 do
755 {
756 switch (mode)
757 {
758 case 0:
759 if (s[pos] >= '0' && s[pos] <= '9')
760 {
761 tmp = tmp * 10 + s[pos] - '0';
762 }
763 else if (s[pos] == 'x' || s[pos] == 'x')
764 {
765 mask = 0;
766 ret = ret << tmp;
767 shifted += tmp;
768 for (unsigned i = 0; i < tmp; i++)
769 mask = (mask << 1) | 1;
770 tmp = 0;
771 mode = 1;
772 }
773 else if (s[pos] == ' ' || s[pos] == '\t')
774 {
775 // ignore spaces
776 // TODO only ignore leading spaces
777 }
778 else
779 {
780 if (good)
781 *good = false;
782 etiss::log(etiss::ERROR, std::string("Failed to parse literal ") + s);
783 return (U)(T_)-1;
784 }
785 break;
786 case 1:
787 if (s[pos] >= '0' && s[pos] <= '9')
788 {
789 tmp = tmp * 16 + s[pos] - '0';
790 }
791 else if (s[pos] >= 'a' && s[pos] <= 'f')
792 {
793 tmp = tmp * 16 + s[pos] + 10 - 'a';
794 }
795 else if (s[pos] >= 'A' && s[pos] <= 'F')
796 {
797 tmp = tmp * 16 + s[pos] + 10 - 'A';
798 }
799 else if (s[pos] == ' ' || s[pos] == '\t' || s[pos] == 0)
800 {
801 // complain if hex is shorter than bit length?
802 ret = ret | (tmp & mask);
803 tmp = 0;
804 mode = 0;
805 }
806 else
807 {
808 if (good)
809 *good = false;
810 etiss::log(etiss::ERROR, std::string("Failed to parse literal ") + s);
811 return (U)(T_)-1;
812 }
813 }
814 } while (s[pos++] != 0);
815
816 if (shifted != 32)
817 {
818 if (good)
819 *good = false;
820 etiss::log(etiss::ERROR, std::string("Failed to parse literal due to invalid length: ") + s);
821 // return (U)(T_)-1; return the parsed value anyway
822 }
823
824 return ret;
825}
826
827} // namespace instr
828
829} // namespace etiss
830#endif
general configuration and logging
#define etiss_del_como(CLASS)
Definition Misc.h:52
#define etiss_log(LEVEL, MSG)
Definition Misc.h:41
__device__ __2f16 float bool s
static __inline__ uint32_t
Definition arm_cde.h:25
static __inline__ uint64_t
Definition arm_cde.h:31
A set of CodeParts.
Definition CodePart.h:399
Marker interface for toString() support.
Definition Misc.h:95
Reading through it will only return bits within the range.
BitArray::size_type end()
lowest bit of the range (included).
BitArray::size_type start()
highest bit of the range (included)
etiss_del_como(BitArrayRange) private BitArray::size_type endpos
void write(BitArray &ba, I val)
write the bit from the passed value starting at the lsb to the range.
I read(const BitArray &ba)
reads bits from the range to the return value starting at the lsb.
stores a bit vector
static std::vector< BitArray > permutate(const BitArray &input, std::vector< size_type > indexes)
permutates the given input at the specified indexes.
void set_value(size_type width, unsigned long value)
change the value the object is holding
BitArray get_range(size_type end, size_type start) const
get the interval [end, start]
BitArray(const super &a)
unsigned byteCount() const
std::string to_string() const
string representation of the BitArray
unsigned intCount() const
boost::dynamic_bitset super
void set_range(unsigned long val, size_type end, size_type start)
set the value to the interval [end, start]
Buffer for reading data from memory while instructions are being fetched.
Definition Instruction.h:46
Buffer(unsigned intcount)
Definition Instruction.h:55
Buffer(const Buffer &o)
Definition Instruction.h:53
unsigned internalBufferSize()
Buffer(unsigned intcount, I val)
Definition Instruction.h:60
char * internalBuffer()
get the internal buffer
Buffer & operator=(Buffer &&o)
Definition Instruction.h:72
void recoverFromEndianness(unsigned alignment, endian_t endianness)
changes byte positions as needed to resove endiannes incompabilities after using the internal buffer ...
Buffer & operator=(const Buffer &o)
Definition Instruction.h:63
maps to VariableInstructionSet
void addTo(VariableInstructionSet &set, bool &ok)
const std::string unsigned InstructionGroup T & othergroups
void add(InstructionGroup &group, T &...args)
etiss_del_como(InstructionClass) template< typename... T > InstructionClass(unsigned mode
std::set< InstructionGroup * > groups_
const std::string unsigned width
const std::string unsigned InstructionGroup & group1
maps to ModedInstructionSet
etiss_del_como(InstructionCollection) const std InstructionCollection(const std::string &name, InstructionClass &class1, T &...otherclasses)
void add(InstructionClass &klass, T &...args)
void addTo(ModedInstructionSet &set, bool &ok)
std::set< InstructionClass * > classes_
this class contains parameters that persist in between instruction lookpus/translation within a trans...
std::map< std::string, unsigned > ufields_
additional fields that can be used by any plugin/architecture.
uint64_t current_local_address_
address within the current block
bool is_not_default_width_
if true the this instruction is not as long as the width of the variable instruction set
bool force_block_end_
if true then the block ends after the current instruction.
unsigned & ufield(std::string name)
std::map< void *, std::map< std::string, uint64_t > > lufields_
additonal fields that are local (private) to a plugin/architecture.
bool instr_width_fully_evaluated_
if true the length_updater_ function will be called again after instr_width_ bits are available
uint64_t & ufield(const T &plugin, std::string name)
returns a persistent field
uint64_t current_address_
start address of current instruction
etiss_del_como(InstructionContext) inline InstructionContext()
instruction context is initialized by etiss::Translation class
bool force_append_next_instr_
if true then the block will continue with the next instruction and cannot be terminated
const std::string T T std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> uint32_t builtinGroups
void addTo(Instruction &set, bool &ok)
const std::string T T std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback
const std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback_
const std::string T T std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> uint32_t std::function< std::string(BitArray &, Instruction &)> ASMprinter
const std::function< std::string(BitArray &, Instruction &)> ASMprinter_
etiss_del_como(InstructionDefinition) template< typename T > InstructionDefinition(InstructionGroup &ig
maps to InstructionSet
std::string toString() const
etiss_del_como(InstructionGroup) inline InstructionGroup(const std
void addTo(InstructionSet &set, bool &ok)
std::set< InstructionDefinition * > defs_
holds etiss::instr::Instruction instances and handles automatic instruction tree creation.
etiss_del_como(InstructionSet) VariableInstructionSet &parent_
std::map< const OPCode *, Instruction *, etiss::instr::less > instrmap_
Instruction * get(const OPCode &key)
std::string print(std::string prefix, bool printunused=false)
Instruction * resolve(BitArray &instr)
Instruction * resolve(Node *node, BitArray &instr)
bool compile(Node *node, BitArray code, Instruction *instr)
std::string toString() const
Instruction * create(const OPCode &key, const std::string &name)
Instruction & open(const OPCode &key, const std::string &name)
Instruction & open(T code, T val, const std::string &name)
holds information and translation callbacks for an instruction.
bool addCallback(std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback, uint32_t builtinGroups, const std::set< uint32_t > &groups=std::set< uint32_t >())
std::set< uint32_t > & presentGroups()
bool translate(BitArray &, CodeSet &cs, InstructionContext &context)
uint32_t & presentBuiltinGroups()
void setASMPrinter(std::function< std::string(BitArray &, Instruction &)> printer)
Instruction(unsigned width, const T code, const T mask, const std::string &name)
const std::string name_
std::function< std::string(BitArray &, Instruction &)> printer_
static std::string printASMSimple(BitArray &ba, Instruction &instr)
virtual std::string print(std::string indent, I pos, unsigned pfillwidth, bool printunused=false)
std::string printASM(BitArray &)
std::set< uint32_t > groups_
std::list< std::tuple< std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)>, uint32_t, std::set< uint32_t > > > callbacks_
etiss_del_como(Instruction) enum class BUILTINGROUP const BitArray::size_type width
std::string toString() const
holds etiss::instr::VariableInstructionSet instances for different modes.
std::string print(std::string prefix=std::string())
uint32_t getMode(VariableInstructionSet &vis)
etiss_del_como(ModedInstructionSet) ModedInstructionSet(const std ~ModedInstructionSet()
std::map< uint32_t, std::string > modetostring_
VariableInstructionSet * create(uint32_t mode, unsigned width, const std::string &name=std::string())
std::map< VariableInstructionSet *, uint32_t > invvismap_
VariableInstructionSet & open(uint32_t mode, unsigned width, const std::string &name=std::string())
Instruction & open(uint32_t mode, unsigned width, unsigned bits, T code, T mask, const char *instrname)
uint32_t getMode(VariableInstructionSet *vis)
std::map< std::string, uint32_t > stringtomode_
VariableInstructionSet * get(uint32_t mode)
std::map< uint32_t, VariableInstructionSet * > vismap_
defines the relevant bits and their value to identify an instruction.
bool operator!=(const OPCode &o) const
OPCode(unsigned width, const T code, const T mask)
ctor that uses integral values for mask and code
const BitArray code_
bool operator==(const OPCode &o) const
bool operator<(const OPCode &o) const
comparison operator for map/sets.
const BitArray mask_
holds etiss::instr::InstructionSet instances with different bit widths.
InstructionSet & open(unsigned width, const std::string &name=std::string())
std::string print(std::string prefix=std::string())
InstructionSet * get(unsigned width)
InstructionSet & openMain(const std::string &name=std::string())
std::map< unsigned, InstructionSet * > ismap_
Instruction & open(unsigned bits, T code, T mask, const char *name)
unsigned const std::string & archname
InstructionSet * create(unsigned width, const std::string &name=std::string())
etiss_del_como(VariableInstructionSet) VariableInstructionSet(ModedInstructionSet &
std::function< void(VariableInstructionSet &, InstructionContext &, BitArray &)> length_updater_
InstructionSet * createMain(const std::string &name=std::string())
std::enable_if< std::is_integral< T_ >::value, typenamestd::make_unsigned< T_ >::type >::type parse_i(const char *s, bool *good=0)
this parser basically allows to write as a string hexadecimal values which will be appended as if it ...
BitArray::size_type size_type
uint32_t I
Definition Instruction.h:40
std::set< Instruction * > Node
Holding unique instruction sets code chunks after permutation.
uint32_t parse_i32(const char *s)
forwards: include/jit/*
Definition Benchmark.h:17
std::string toString(const T &val)
conversion of type T to std::string.
Definition Misc.h:133
endian_t
Enumeration type for the endianness.
Definition Misc.h:488
@ VERBOSE
Definition Misc.h:88
@ WARNING
Definition Misc.h:86
@ ERROR
Definition Misc.h:85
@ FATALERROR
Definition Misc.h:84
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:94
STL namespace.
#define bool
Definition stdbool.h:15
calls operator< of the objects.
bool operator()(const OPCode *const &o1, const OPCode *const &o2) const