nany
sequence.hxx
1 #pragma once
2 #include "sequence.h"
3 
4 #define NANY_PRINT_sequence_OPCODES 0
5 #if NANY_PRINT_sequence_OPCODES != 0
6 #include <iostream>
7 #endif
8 
9 
10 namespace ny {
11 namespace ir {
12 
13 
14 inline void Sequence::reserve(uint32_t count) {
15  if (m_capacity < count)
16  grow(count);
17 }
18 
19 
20 inline uint32_t Sequence::opcodeCount() const {
21  return m_size;
22 }
23 
24 
25 inline uint32_t Sequence::capacity() const {
26  return m_capacity;
27 }
28 
29 
30 inline const Instruction& Sequence::at(uint32_t offset) const {
31  assert(offset < m_size);
32  return m_body[offset];
33 }
34 
35 
36 inline Instruction& Sequence::at(uint32_t offset) {
37  assert(offset < m_size);
38  return m_body[offset];
39 }
40 
41 
42 template<isa::Op O> inline isa::Operand<O>& Sequence::at(uint32_t offset) {
43  assert(offset < m_size);
44  static_assert(sizeof(Instruction) >= sizeof(isa::Operand<O>), "m_size mismatch");
45  return reinterpret_cast<isa::Operand<O>&>(m_body[offset]);
46 }
47 
48 
49 template<isa::Op O> inline const isa::Operand<O>& Sequence::at(uint32_t offset) const {
50  assert(offset < m_size);
51  static_assert(sizeof(Instruction) >= sizeof(isa::Operand<O>), "m_size mismatch");
52  return reinterpret_cast<isa::Operand<O>&>(m_body[offset]);
53 }
54 
55 
56 inline uint32_t Sequence::offsetOf(const Instruction& instr) const {
57  assert(m_size > 0 and m_capacity > 0);
58  assert(&instr >= m_body);
59  assert(&instr < m_body + m_size);
60  auto start = reinterpret_cast<std::uintptr_t>(m_body);
61  auto end = reinterpret_cast<std::uintptr_t>(&instr);
62  assert((end - start) / sizeof(Instruction) < 512 * 1024 * 1024); // arbitrary
63  uint32_t r = static_cast<uint32_t>(((end - start) / sizeof(Instruction)));
64  assert(r < m_size);
65  return r;
66 }
67 
68 
69 inline bool Sequence::isCursorValid(const Instruction& instr) const {
70  return (m_size > 0 and m_capacity > 0)
71  and (&instr >= m_body)
72  and (&instr < m_body + m_size);
73 }
74 
75 
76 template<isa::Op O>
77 inline uint32_t Sequence::offsetOf(const isa::Operand<O>& instr) const {
78  static_assert(sizeof(Instruction) >= sizeof(isa::Operand<O>), "m_size mismatch");
79  return offsetOf(ir::Instruction::fromOpcode(instr));
80 }
81 
82 
83 inline void Sequence::invalidateCursor(const Instruction*& cursor) const {
84  cursor = m_body + m_size;
85 }
86 
87 
88 inline void Sequence::invalidateCursor(Instruction*& cursor) const {
89  cursor = m_body + m_size;
90 }
91 
92 
93 inline bool Sequence::jumpToLabelForward(const Instruction*& cursor, uint32_t label) const {
94  const auto* const end = m_body + m_size;
95  const Instruction* instr = cursor;
96  while (++instr < end) {
97  if (instr->opcodes[0] == static_cast<uint32_t>(ir::isa::Op::label)) {
98  auto& operands = (*instr).to<ir::isa::Op::label>();
99  if (operands.label == label) {
100  cursor = instr;
101  return true;
102  }
103  }
104  }
105  // not found - the cursor is alreayd invalidated
106  return false;
107 }
108 
109 
110 inline bool Sequence::jumpToLabelBackward(const Instruction*& cursor, uint32_t label) const {
111  const auto* const base = m_body;
112  const Instruction* instr = cursor;
113  while (instr-- > base) {
114  if (instr->opcodes[0] == static_cast<uint32_t>(ir::isa::Op::label)) {
115  auto& operands = (*instr).to<ir::isa::Op::label>();
116  if (operands.label == label) {
117  cursor = instr;
118  return true;
119  }
120  }
121  }
122  // not found - invalidate
123  return false;
124 }
125 
126 
127 template<class T> inline void Sequence::each(T& visitor, uint32_t offset) {
128  if (likely(offset < m_size)) {
129  auto* it = m_body + offset;
130  const auto* const end = m_body + m_size;
131  visitor.cursor = &it;
132  for ( ; it < end; ++it) {
133  #if NANY_PRINT_sequence_OPCODES != 0
134  std::cout << "== opcode == at " << (it - m_body) << "|" << (void*) it << " :: ";
135  std::cout << it->opcodes[0] << ": " << ir::isa::print(*this, *it) << '\n';
136  #endif
137  LIBNANYC_IR_VISIT_SEQUENCE(ir::isa::Operand, visitor, *it);
138  }
139  }
140 }
141 
142 
143 template<class T> inline void Sequence::each(T& visitor, uint32_t offset) const {
144  if (likely(offset < m_size)) {
145  const auto* it = m_body + offset;
146  const auto* const end = m_body + m_size;
147  visitor.cursor = &it;
148  for ( ; it < end; ++it) {
149  #if NANY_PRINT_sequence_OPCODES != 0
150  std::cout << "== opcode == at " << (it - m_body) << "|" << (void*) it << " :: ";
151  std::cout << it->opcodes[0] << ": " << ir::isa::print(*this, *it) << '\n';
152  #endif
153  LIBNANYC_IR_VISIT_SEQUENCE(const ir::isa::Operand, visitor, *it);
154  }
155  }
156 }
157 
158 
159 template<isa::Op O> inline isa::Operand<O>& Sequence::emit() {
160  if (unlikely(m_capacity < m_size + 1))
161  grow(m_size + 1);
162  static_assert(sizeof(Instruction) >= sizeof(isa::Operand<O>), "m_size mismatch");
163  assert(m_size + 1 <= m_capacity);
164  auto& result = at<O>(m_size++);
165  result.opcode = static_cast<uint32_t>(O);
166  return result;
167 }
168 
169 
170 } // namespace ir
171 } // namespace ny
isa::Operand< O > & at(uint32_t offset)
Fetch an instruction at a given offset.
Definition: sequence.hxx:42
Definition: ast.cpp:6
void each(T &visitor, uint32_t offset=0)
Visit each instruction.
Definition: sequence.hxx:127
void reserve(uint32_t count)
Reserve enough memory for N instructions.
Definition: sequence.hxx:14
isa::Operand< O > & to()
Convert the instruction into an Opcode struct.
Definition: instruction.h:16
bool jumpToLabelBackward(const Instruction *&cursor, uint32_t label) const
Go to a previous label.
Definition: sequence.hxx:110
isa::Operand< O > & emit()
emit a new Instruction
Definition: sequence.hxx:159
uint32_t opcodeCount() const
Get how many instructions the sequence has.
Definition: sequence.hxx:20
Definition: instruction.h:12
bool jumpToLabelForward(const Instruction *&cursor, uint32_t label) const
Go to the next label.
Definition: sequence.hxx:93
uint32_t capacity() const
Get the capacity of the sequence (in instructions)
Definition: sequence.hxx:25
bool isCursorValid(const Instruction &instr) const
Get if a cursor is valid.
Definition: sequence.hxx:69
Definition: data.h:85
uint32_t offsetOf(const isa::Operand< O > &instr) const
Get the offset of an instruction within the sequence.
Definition: sequence.hxx:77
void invalidateCursor(const Instruction *&cusror) const
Get the upper limit.
Definition: sequence.hxx:83