31class FunctionWriterBase {
33 struct TargetCIEInfo {
35 std::span<const u8> instrs;
37 u8 return_addr_register;
39 u8 code_alignment_factor;
41 u8 data_alignment_factor;
45 const TargetCIEInfo &cie_info;
47 DataSection *section =
nullptr;
48 u8 *data_begin =
nullptr;
49 u8 *data_cur =
nullptr;
50 u8 *data_reserve_end =
nullptr;
81 std::span<Label> labels() {
82 return {
reinterpret_cast<Label *
>(
this + 1), size};
86 static_assert(std::is_trivially_destructible_v<JumpTable>);
89 util::BumpAllocator<> jump_table_alloc;
92 util::SmallVector<JumpTable *> jump_tables;
95 DataSection *eh_frame_section;
98 util::VectorWriter eh_writer;
102 SymRef cur_personality_func_addr;
103 u32 eh_cur_cie_off = 0u;
106 struct ExceptCallSiteInfo {
115 util::SmallVector<ExceptCallSiteInfo, 0> except_call_site_table;
118 util::SmallVector<u8, 0> except_encoded_call_sites;
120 util::SmallVector<u8, 0> except_action_table;
123 util::SmallVector<SymRef, 0> except_type_info_table;
125 util::SmallVector<u8, 0> except_spec_table;
128 FunctionWriterBase(
const TargetCIEInfo &cie_info) : cie_info(cie_info) {}
130 ~FunctionWriterBase() {
131 assert(data_cur == data_reserve_end &&
132 "must flush section writer before destructing");
141 assert(section !=
nullptr);
147 assert(data_cur == data_reserve_end &&
148 "must flush section writer before switching sections");
149 section = &new_section;
150 data_begin = section->data.data();
151 data_cur = data_begin + section->data.size();
152 data_reserve_end = data_cur;
162 size_t offset()
const {
return data_cur - data_begin; }
175 void more_space(
size_t size);
179 void reloc(SymRef sym, u32 type, u64 off, i64 addend = 0) {
180 assembler->reloc_sec(
get_sec_ref(), sym, type, off, addend);
189 if (data_cur != data_reserve_end) {
190 section->data.resize(
offset());
191 data_reserve_end = data_cur;
193 section->locked =
false;
208 bool label_is_pending(Label label)
const {
212 u32 label_offset(Label label)
const {
213 assert(!label_is_pending(label));
219 assert(
label_skew == 0 &&
"label_place called after prologue truncation");
220 assert(label_is_pending(label));
225 void label_ref(Label label, u32 off, LabelFixupKind kind) {
229 label_fixups.emplace_back(LabelFixup{label, off, kind});
238 SecRef get_jump_table_section() {
241 return assembler->get_default_section(SectionKind::ReadOnly);
248 static constexpr u32 write_eh_inst(u8 *dst, u8 opcode, u64 arg) {
249 if (opcode & dwarf::DWARF_CFI_PRIMARY_OPCODE_MASK) {
250 assert((arg & dwarf::DWARF_CFI_PRIMARY_OPCODE_MASK) == 0);
255 return 1 + util::uleb_write(dst, arg);
258 static constexpr u32 write_eh_inst(u8 *dst, u8 opcode, u64 arg1, u64 arg2) {
260 dst += write_eh_inst(dst, opcode, arg1);
261 dst += util::uleb_write(dst, arg2);
265 void eh_align_frame();
266 void eh_write_inst(u8 opcode) { this->eh_writer.write<u8>(opcode); }
267 void eh_write_inst(u8 opcode, u64 arg);
268 void eh_write_inst(u8 opcode, u64 first_arg, u64 second_arg);
275 void eh_init_cie(SymRef personality_func_addr = SymRef());
278 void eh_begin_fde(SymRef personality_func_addr = SymRef());
286 void except_encode_func();
303 void except_add_empty_spec_action(
bool first_action);
305 u32 except_type_idx_for_sym(SymRef sym);
312class FunctionWriter :
public FunctionWriterBase {
314 FunctionWriter(
const TargetCIEInfo &cie_info)
315 : FunctionWriterBase(cie_info) {}
317 Derived *derived() {
return static_cast<Derived *
>(
this); }
320 void begin_func(u32 align, u32 expected_size) {
323 derived()->align(align);
324 FunctionWriterBase::begin_func();
327 void finish_func() { derived()->handle_fixups(); }
334 assert(data_reserve_end >= data_cur);
335 if (
size_t(data_reserve_end - data_cur) < size) [[unlikely]] {
336 derived()->more_space(size);
340 template <std::
integral T>
341 void write_unchecked(T t) {
342 assert(
size_t(data_reserve_end - data_cur) >=
sizeof(T));
343 std::memcpy(data_cur, &t,
sizeof(T));
344 data_cur +=
sizeof(T);
347 template <std::
integral T>
350 write_unchecked<T>(t);
353 void align(
size_t align) {
354 assert(align > 0 && (align & (align - 1)) == 0);
357 std::memset(
cur_ptr(), 0, align);
358 data_cur = data_begin + util::align_up(
offset(), align);
359 section->align = std::max(section->align, u32(align));