|
@@ -17,8 +17,6 @@ typedef Array(irValue *) irValueArray;
|
|
|
|
|
|
typedef struct irModule {
|
|
|
CheckerInfo * info;
|
|
|
- BuildContext *build_context;
|
|
|
- BaseTypeSizes sizes;
|
|
|
gbArena arena;
|
|
|
gbArena tmp_arena;
|
|
|
gbAllocator allocator;
|
|
@@ -326,6 +324,7 @@ typedef struct irValueGlobal {
|
|
|
bool is_constant;
|
|
|
bool is_private;
|
|
|
bool is_thread_local;
|
|
|
+ bool is_foreign;
|
|
|
bool is_unnamed_addr;
|
|
|
} irValueGlobal;
|
|
|
|
|
@@ -1438,9 +1437,9 @@ irValue *ir_gen_map_header(irProcedure *proc, irValue *map_val, Type *map_type)
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, h, 1), v_true);
|
|
|
}
|
|
|
|
|
|
- i64 entry_size = type_size_of(proc->module->sizes, a, map_type->Map.entry_type);
|
|
|
- i64 entry_align = type_align_of(proc->module->sizes, a, map_type->Map.entry_type);
|
|
|
- i64 value_offset = type_offset_of(proc->module->sizes, a, map_type->Map.entry_type, 2);
|
|
|
+ i64 entry_size = type_size_of(a, map_type->Map.entry_type);
|
|
|
+ i64 entry_align = type_align_of(a, map_type->Map.entry_type);
|
|
|
+ i64 value_offset = type_offset_of(a, map_type->Map.entry_type, 2);
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, h, 2), ir_make_const_int(a, entry_size));
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, h, 3), ir_make_const_int(a, entry_align));
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, h, 4), ir_make_const_int(a, value_offset));
|
|
@@ -1460,7 +1459,7 @@ irValue *ir_gen_map_key(irProcedure *proc, irValue *key, Type *key_type) {
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, p, t_u64));
|
|
|
} else if (is_type_float(t)) {
|
|
|
irValue *bits = NULL;
|
|
|
- i64 size = type_size_of(proc->module->sizes, proc->module->allocator, t);
|
|
|
+ i64 size = type_size_of(proc->module->allocator, t);
|
|
|
switch (8*size) {
|
|
|
case 32: bits = ir_emit_bitcast(proc, key, t_u32); break;
|
|
|
case 64: bits = ir_emit_bitcast(proc, key, t_u64); break;
|
|
@@ -1660,7 +1659,7 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
|
|
|
irModule *m = proc->module;
|
|
|
Type *ptr_type = base_type(t_left);
|
|
|
GB_ASSERT(!is_type_rawptr(ptr_type));
|
|
|
- irValue *elem_size = ir_make_const_int(m->allocator, type_size_of(m->sizes, m->allocator, ptr_type->Pointer.elem));
|
|
|
+ irValue *elem_size = ir_make_const_int(m->allocator, type_size_of(m->allocator, ptr_type->Pointer.elem));
|
|
|
irValue *x = ir_emit_conv(proc, left, type);
|
|
|
irValue *y = ir_emit_conv(proc, right, type);
|
|
|
irValue *diff = ir_emit_arith(proc, op, x, y, type);
|
|
@@ -1675,7 +1674,7 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *
|
|
|
left = ir_emit_conv(proc, left, type);
|
|
|
if (!is_type_unsigned(ir_type(right))) {
|
|
|
Type *t = t_u64;
|
|
|
- if (proc->module->sizes.word_size == 32) {
|
|
|
+ if (build_context.word_size == 32) {
|
|
|
t = t_u32;
|
|
|
}
|
|
|
right = ir_emit_conv(proc, right, t);
|
|
@@ -2189,8 +2188,8 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|
|
if (is_type_integer(src) && is_type_integer(dst)) {
|
|
|
GB_ASSERT(src->kind == Type_Basic &&
|
|
|
dst->kind == Type_Basic);
|
|
|
- i64 sz = type_size_of(proc->module->sizes, proc->module->allocator, src);
|
|
|
- i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst);
|
|
|
+ i64 sz = type_size_of(proc->module->allocator, src);
|
|
|
+ i64 dz = type_size_of(proc->module->allocator, dst);
|
|
|
irConvKind kind = irConv_trunc;
|
|
|
if (sz == dz) {
|
|
|
// NOTE(bill): In LLVM, all integers are signed and rely upon 2's compliment
|
|
@@ -2216,8 +2215,8 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|
|
|
|
|
// float -> float
|
|
|
if (is_type_float(src) && is_type_float(dst)) {
|
|
|
- i64 sz = type_size_of(proc->module->sizes, proc->module->allocator, src);
|
|
|
- i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst);
|
|
|
+ i64 sz = type_size_of(proc->module->allocator, src);
|
|
|
+ i64 dz = type_size_of(proc->module->allocator, dst);
|
|
|
irConvKind kind = irConv_fptrunc;
|
|
|
if (dz >= sz) {
|
|
|
kind = irConv_fpext;
|
|
@@ -2432,8 +2431,8 @@ irValue *ir_emit_transmute(irProcedure *proc, irValue *value, Type *t) {
|
|
|
|
|
|
irModule *m = proc->module;
|
|
|
|
|
|
- i64 sz = type_size_of(m->sizes, m->allocator, src);
|
|
|
- i64 dz = type_size_of(m->sizes, m->allocator, dst);
|
|
|
+ i64 sz = type_size_of(m->allocator, src);
|
|
|
+ i64 dz = type_size_of(m->allocator, dst);
|
|
|
|
|
|
GB_ASSERT_MSG(sz == dz, "Invalid transmute conversion: `%s` to `%s`", type_to_string(src_type), type_to_string(t));
|
|
|
|
|
@@ -2457,7 +2456,7 @@ irValue *ir_emit_down_cast(irProcedure *proc, irValue *value, Type *t) {
|
|
|
Selection sel = lookup_field(proc->module->allocator, t, field_name, false);
|
|
|
irValue *bytes = ir_emit_conv(proc, value, t_u8_ptr);
|
|
|
|
|
|
- i64 offset_ = type_offset_of_from_selection(proc->module->sizes, allocator, type_deref(t), sel);
|
|
|
+ i64 offset_ = type_offset_of_from_selection(allocator, type_deref(t), sel);
|
|
|
irValue *offset = ir_make_const_int(allocator, -offset_);
|
|
|
irValue *head = ir_emit_ptr_offset(proc, bytes, offset);
|
|
|
return ir_emit_conv(proc, head, t);
|
|
@@ -3072,8 +3071,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|
|
Type *type = type_of_expr(proc->module->info, ce->args.e[0]);
|
|
|
Type *ptr_type = make_type_pointer(allocator, type);
|
|
|
|
|
|
- i64 s = type_size_of(proc->module->sizes, allocator, type);
|
|
|
- i64 a = type_align_of(proc->module->sizes, allocator, type);
|
|
|
+ i64 s = type_size_of(allocator, type);
|
|
|
+ i64 a = type_align_of(allocator, type);
|
|
|
|
|
|
irValue **args = gb_alloc_array(allocator, irValue *, 2);
|
|
|
args[0] = ir_make_const_int(allocator, s);
|
|
@@ -3092,8 +3091,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|
|
Type *ptr_type = make_type_pointer(allocator, type);
|
|
|
Type *slice_type = make_type_slice(allocator, type);
|
|
|
|
|
|
- i64 s = type_size_of(proc->module->sizes, allocator, type);
|
|
|
- i64 a = type_align_of(proc->module->sizes, allocator, type);
|
|
|
+ i64 s = type_size_of(allocator, type);
|
|
|
+ i64 a = type_align_of(allocator, type);
|
|
|
|
|
|
irValue *elem_size = ir_make_const_int(allocator, s);
|
|
|
irValue *elem_align = ir_make_const_int(allocator, a);
|
|
@@ -3207,8 +3206,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|
|
if (is_type_dynamic_array(type)) {
|
|
|
Type *elem = type->DynamicArray.elem;
|
|
|
|
|
|
- irValue *elem_size = ir_make_const_int(a, type_size_of(proc->module->sizes, a, elem));
|
|
|
- irValue *elem_align = ir_make_const_int(a, type_align_of(proc->module->sizes, a, elem));
|
|
|
+ irValue *elem_size = ir_make_const_int(a, type_size_of(a, elem));
|
|
|
+ irValue *elem_align = ir_make_const_int(a, type_align_of(a, elem));
|
|
|
|
|
|
ptr = ir_emit_conv(proc, ptr, t_rawptr);
|
|
|
|
|
@@ -3257,8 +3256,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|
|
GB_ASSERT(is_type_dynamic_array(type));
|
|
|
Type *elem_type = type->DynamicArray.elem;
|
|
|
|
|
|
- irValue *elem_size = ir_make_const_int(a, type_size_of(proc->module->sizes, a, elem_type));
|
|
|
- irValue *elem_align = ir_make_const_int(a, type_align_of(proc->module->sizes, a, elem_type));
|
|
|
+ irValue *elem_size = ir_make_const_int(a, type_size_of(a, elem_type));
|
|
|
+ irValue *elem_align = ir_make_const_int(a, type_align_of(a, elem_type));
|
|
|
|
|
|
array_ptr = ir_emit_conv(proc, array_ptr, t_rawptr);
|
|
|
|
|
@@ -3401,7 +3400,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|
|
Type *slice_type = base_type(ir_type(dst_slice));
|
|
|
GB_ASSERT(slice_type->kind == Type_Slice);
|
|
|
Type *elem_type = slice_type->Slice.elem;
|
|
|
- i64 size_of_elem = type_size_of(proc->module->sizes, proc->module->allocator, elem_type);
|
|
|
+ i64 size_of_elem = type_size_of(proc->module->allocator, elem_type);
|
|
|
|
|
|
irValue *dst = ir_emit_conv(proc, ir_slice_elem(proc, dst_slice), t_rawptr);
|
|
|
irValue *src = ir_emit_conv(proc, ir_slice_elem(proc, src_slice), t_rawptr);
|
|
@@ -3473,7 +3472,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
|
|
return ir_emit_conv(proc, s, tv->type);
|
|
|
}
|
|
|
irValue *slice = ir_add_local_generated(proc, tv->type);
|
|
|
- i64 elem_size = type_size_of(proc->module->sizes, proc->module->allocator, t->Slice.elem);
|
|
|
+ i64 elem_size = type_size_of(proc->module->allocator, t->Slice.elem);
|
|
|
|
|
|
irValue *ptr = ir_emit_conv(proc, ir_slice_elem(proc, s), t_u8_ptr);
|
|
|
irValue *count = ir_slice_count(proc, s);
|
|
@@ -4194,8 +4193,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|
|
}
|
|
|
Type *elem = bt->DynamicArray.elem;
|
|
|
gbAllocator a = proc->module->allocator;
|
|
|
- irValue *size = ir_make_const_int(a, type_size_of(proc->module->sizes, a, elem));
|
|
|
- irValue *align = ir_make_const_int(a, type_align_of(proc->module->sizes, a, elem));
|
|
|
+ irValue *size = ir_make_const_int(a, type_size_of(a, elem));
|
|
|
+ irValue *align = ir_make_const_int(a, type_align_of(a, elem));
|
|
|
{
|
|
|
irValue **args = gb_alloc_array(a, irValue *, 4);
|
|
|
args[0] = ir_emit_conv(proc, v, t_rawptr);
|
|
@@ -5670,7 +5669,7 @@ void ir_module_add_value(irModule *m, Entity *e, irValue *v) {
|
|
|
map_ir_value_set(&m->values, hash_pointer(e), v);
|
|
|
}
|
|
|
|
|
|
-void ir_init_module(irModule *m, Checker *c, BuildContext *build_context) {
|
|
|
+void ir_init_module(irModule *m, Checker *c) {
|
|
|
// TODO(bill): Determine a decent size for the arena
|
|
|
isize token_count = c->parser->total_token_count;
|
|
|
isize arena_size = 4 * token_count * gb_size_of(irValue);
|
|
@@ -5679,8 +5678,6 @@ void ir_init_module(irModule *m, Checker *c, BuildContext *build_context) {
|
|
|
m->allocator = gb_arena_allocator(&m->arena);
|
|
|
m->tmp_allocator = gb_arena_allocator(&m->tmp_arena);
|
|
|
m->info = &c->info;
|
|
|
- m->sizes = c->sizes;
|
|
|
- m->build_context = build_context;
|
|
|
|
|
|
map_ir_value_init(&m->values, heap_allocator());
|
|
|
map_ir_value_init(&m->members, heap_allocator());
|
|
@@ -5785,7 +5782,7 @@ void ir_destroy_module(irModule *m) {
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
-bool ir_gen_init(irGen *s, Checker *c, BuildContext *build_context) {
|
|
|
+bool ir_gen_init(irGen *s, Checker *c) {
|
|
|
if (global_error_collector.count != 0) {
|
|
|
return false;
|
|
|
}
|
|
@@ -5795,7 +5792,7 @@ bool ir_gen_init(irGen *s, Checker *c, BuildContext *build_context) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- ir_init_module(&s->module, c, build_context);
|
|
|
+ ir_init_module(&s->module, c);
|
|
|
s->module.generate_debug_info = false;
|
|
|
|
|
|
// TODO(bill): generate appropriate output name
|
|
@@ -5974,6 +5971,7 @@ void ir_gen_tree(irGen *s) {
|
|
|
if (!scope->is_global) {
|
|
|
if (e->kind == Entity_Procedure && (e->Procedure.tags & ProcTag_export) != 0) {
|
|
|
} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
|
|
|
+ // Handle later
|
|
|
} else if (scope->is_init && e->kind == Entity_Procedure && str_eq(name, str_lit("main"))) {
|
|
|
} else {
|
|
|
name = ir_mangle_name(s, e->token.pos.file, e);
|
|
@@ -6079,7 +6077,7 @@ void ir_gen_tree(irGen *s) {
|
|
|
}
|
|
|
|
|
|
#if defined(GB_SYSTEM_WINDOWS)
|
|
|
- if (m->build_context->is_dll && !has_dll_main) {
|
|
|
+ if (build_context.is_dll && !has_dll_main) {
|
|
|
// DllMain :: proc(inst: rawptr, reason: u32, reserved: rawptr) -> i32
|
|
|
String name = str_lit("DllMain");
|
|
|
Type *proc_params = make_type_tuple(a);
|
|
@@ -6306,7 +6304,7 @@ void ir_gen_tree(irGen *s) {
|
|
|
case Basic_uint: {
|
|
|
tag = ir_emit_conv(proc, ti_ptr, t_type_info_integer_ptr);
|
|
|
bool is_unsigned = (t->Basic.flags & BasicFlag_Unsigned) != 0;
|
|
|
- irValue *bits = ir_make_const_int(a, type_size_of(m->sizes, a, t));
|
|
|
+ irValue *bits = ir_make_const_int(a, type_size_of(a, t));
|
|
|
irValue *is_signed = ir_make_const_bool(a, !is_unsigned);
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), bits);
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), is_signed);
|
|
@@ -6318,7 +6316,7 @@ void ir_gen_tree(irGen *s) {
|
|
|
// case Basic_f128:
|
|
|
{
|
|
|
tag = ir_emit_conv(proc, ti_ptr, t_type_info_float_ptr);
|
|
|
- irValue *bits = ir_make_const_int(a, type_size_of(m->sizes, a, t));
|
|
|
+ irValue *bits = ir_make_const_int(a, type_size_of(a, t));
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), bits);
|
|
|
} break;
|
|
|
|
|
@@ -6348,7 +6346,7 @@ void ir_gen_tree(irGen *s) {
|
|
|
irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Array.elem);
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
|
|
|
|
|
- isize ez = type_size_of(m->sizes, a, t->Array.elem);
|
|
|
+ isize ez = type_size_of(a, t->Array.elem);
|
|
|
irValue *elem_size = ir_emit_struct_ep(proc, tag, 1);
|
|
|
ir_emit_store(proc, elem_size, ir_make_const_int(a, ez));
|
|
|
|
|
@@ -6362,7 +6360,7 @@ void ir_gen_tree(irGen *s) {
|
|
|
irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->DynamicArray.elem);
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
|
|
|
|
|
- isize ez = type_size_of(m->sizes, a, t->DynamicArray.elem);
|
|
|
+ isize ez = type_size_of(a, t->DynamicArray.elem);
|
|
|
irValue *elem_size = ir_emit_struct_ep(proc, tag, 1);
|
|
|
ir_emit_store(proc, elem_size, ir_make_const_int(a, ez));
|
|
|
} break;
|
|
@@ -6372,7 +6370,7 @@ void ir_gen_tree(irGen *s) {
|
|
|
irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Slice.elem);
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
|
|
|
|
|
- isize ez = type_size_of(m->sizes, a, t->Slice.elem);
|
|
|
+ isize ez = type_size_of(a, t->Slice.elem);
|
|
|
irValue *elem_size = ir_emit_struct_ep(proc, tag, 1);
|
|
|
ir_emit_store(proc, elem_size, ir_make_const_int(a, ez));
|
|
|
} break;
|
|
@@ -6382,10 +6380,10 @@ void ir_gen_tree(irGen *s) {
|
|
|
irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Vector.elem);
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep);
|
|
|
|
|
|
- isize ez = type_size_of(m->sizes, a, t->Vector.elem);
|
|
|
+ isize ez = type_size_of(a, t->Vector.elem);
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), ir_make_const_int(a, ez));
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), ir_make_const_int(a, t->Vector.count));
|
|
|
- ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), ir_make_const_int(a, type_align_of(m->sizes, a, t)));
|
|
|
+ ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), ir_make_const_int(a, type_align_of(a, t)));
|
|
|
|
|
|
} break;
|
|
|
case Type_Proc: {
|
|
@@ -6413,7 +6411,7 @@ void ir_gen_tree(irGen *s) {
|
|
|
tag = ir_emit_conv(proc, ti_ptr, t_type_info_tuple_ptr);
|
|
|
|
|
|
{
|
|
|
- irValue *align = ir_make_const_int(a, type_align_of(m->sizes, a, t));
|
|
|
+ irValue *align = ir_make_const_int(a, type_align_of(a, t));
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 4), align);
|
|
|
}
|
|
|
|
|
@@ -6444,8 +6442,8 @@ void ir_gen_tree(irGen *s) {
|
|
|
tag = ir_emit_conv(proc, ti_ptr, t_type_info_struct_ptr);
|
|
|
|
|
|
{
|
|
|
- irValue *size = ir_make_const_int(a, type_size_of(m->sizes, a, t));
|
|
|
- irValue *align = ir_make_const_int(a, type_align_of(m->sizes, a, t));
|
|
|
+ irValue *size = ir_make_const_int(a, type_size_of(a, t));
|
|
|
+ irValue *align = ir_make_const_int(a, type_align_of(a, t));
|
|
|
irValue *packed = ir_make_const_bool(a, t->Record.struct_is_packed);
|
|
|
irValue *ordered = ir_make_const_bool(a, t->Record.struct_is_ordered);
|
|
|
irValue *custom_align = ir_make_const_bool(a, t->Record.custom_align);
|
|
@@ -6460,7 +6458,7 @@ void ir_gen_tree(irGen *s) {
|
|
|
irValue *memory_names = ir_type_info_member_offset(proc, type_info_member_names, t->Record.field_count, &type_info_member_names_index);
|
|
|
irValue *memory_offsets = ir_type_info_member_offset(proc, type_info_member_offsets, t->Record.field_count, &type_info_member_offsets_index);
|
|
|
|
|
|
- type_set_offsets(m->sizes, a, t); // NOTE(bill): Just incase the offsets have not been set yet
|
|
|
+ type_set_offsets(a, t); // NOTE(bill): Just incase the offsets have not been set yet
|
|
|
for (isize source_index = 0; source_index < t->Record.field_count; source_index++) {
|
|
|
// TODO(bill): Order fields in source order not layout order
|
|
|
Entity *f = t->Record.fields_in_src_order[source_index];
|
|
@@ -6488,8 +6486,8 @@ void ir_gen_tree(irGen *s) {
|
|
|
ir_emit_comment(proc, str_lit("Type_Info_Union"));
|
|
|
tag = ir_emit_conv(proc, ti_ptr, t_type_info_union_ptr);
|
|
|
{
|
|
|
- irValue *size = ir_make_const_int(a, type_size_of(m->sizes, a, t));
|
|
|
- irValue *align = ir_make_const_int(a, type_align_of(m->sizes, a, t));
|
|
|
+ irValue *size = ir_make_const_int(a, type_size_of(a, t));
|
|
|
+ irValue *align = ir_make_const_int(a, type_align_of(a, t));
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), size);
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 4), align);
|
|
|
}
|
|
@@ -6498,8 +6496,8 @@ void ir_gen_tree(irGen *s) {
|
|
|
ir_emit_comment(proc, str_lit("Type_Info_RawUnion"));
|
|
|
tag = ir_emit_conv(proc, ti_ptr, t_type_info_raw_union_ptr);
|
|
|
{
|
|
|
- irValue *size = ir_make_const_int(a, type_size_of(m->sizes, a, t));
|
|
|
- irValue *align = ir_make_const_int(a, type_align_of(m->sizes, a, t));
|
|
|
+ irValue *size = ir_make_const_int(a, type_size_of(a, t));
|
|
|
+ irValue *align = ir_make_const_int(a, type_align_of(a, t));
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), size);
|
|
|
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 4), align);
|
|
|
}
|