diff options
| author | gingerBill <bill@gingerbill.org> | 2020-02-29 14:29:47 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2020-02-29 14:29:47 +0000 |
| commit | 56240240f6c040df5ecdd10f8050ce03040f8c87 (patch) | |
| tree | 0b2629ec12c3fa37c28e5562adeae9354ede0a81 /src/llvm_backend.cpp | |
| parent | f83e1b8b0a2acb5cf0f4bec36665211af0cc9a01 (diff) | |
Range Statement support
Diffstat (limited to 'src/llvm_backend.cpp')
| -rw-r--r-- | src/llvm_backend.cpp | 643 |
1 files changed, 636 insertions, 7 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index a56991a9a..60f02e611 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -820,6 +820,13 @@ void lb_add_procedure_value(lbModule *m, lbProcedure *p) { +lbValue lb_emit_string(lbProcedure *p, lbValue str_elem, lbValue str_len) { + lbAddr res = lb_add_local_generated(p, t_string, false); + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 0), str_elem); + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 1), str_len); + return lb_addr_load(p, res); +} + LLVMAttributeRef lb_create_enum_attribute(LLVMContextRef ctx, char const *name, u64 value) { unsigned kind = LLVMGetEnumAttributeKindForName(name, gb_strlen(name)); return LLVMCreateEnumAttribute(ctx, kind, value); @@ -836,6 +843,7 @@ void lb_add_proc_attribute_at_index(lbProcedure *p, isize index, char const *nam + lbProcedure *lb_create_procedure(lbModule *m, Entity *entity) { GB_ASSERT(entity != nullptr); @@ -1738,6 +1746,627 @@ void lb_build_when_stmt(lbProcedure *p, AstWhenStmt *ws) { } } + + +void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValue count_ptr, + lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_) { + lbModule *m = p->module; + + lbValue count = {}; + Type *expr_type = base_type(type_deref(expr.type)); + switch (expr_type->kind) { + case Type_Array: + count = lb_const_int(m, t_int, expr_type->Array.count); + break; + } + + lbValue val = {}; + lbValue idx = {}; + lbBlock *loop = nullptr; + lbBlock *done = nullptr; + lbBlock *body = nullptr; + + + lbAddr index = lb_add_local_generated(p, t_int, false); + lb_addr_store(p, index, lb_const_int(m, t_int, cast(u64)-1)); + + loop = lb_create_block(p, "for.index.loop"); + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + lbValue incr = lb_emit_arith(p, Token_Add, lb_addr_load(p, index), lb_const_int(m, t_int, 1), t_int); + lb_addr_store(p, index, incr); + + body = lb_create_block(p, "for.index.body"); + done = lb_create_block(p, "for.index.done"); + if (count.value == nullptr) { + GB_ASSERT(count_ptr.value != nullptr); + count = lb_emit_load(p, count_ptr); + } + lbValue cond = lb_emit_comp(p, Token_Lt, incr, count); + lb_emit_if(p, cond, body, done); + lb_start_block(p, body); + + idx = lb_addr_load(p, index); + switch (expr_type->kind) { + case Type_Array: { + if (val_type != nullptr) { + val = lb_emit_load(p, lb_emit_array_ep(p, expr, idx)); + } + break; + } + case Type_EnumeratedArray: { + if (val_type != nullptr) { + val = lb_emit_load(p, lb_emit_array_ep(p, expr, idx)); + // NOTE(bill): Override the idx value for the enumeration + Type *index_type = expr_type->EnumeratedArray.index; + if (compare_exact_values(Token_NotEq, expr_type->EnumeratedArray.min_value, exact_value_u64(0))) { + idx = lb_emit_arith(p, Token_Add, idx, lb_const_value(m, index_type, expr_type->EnumeratedArray.min_value), index_type); + } + } + break; + } + case Type_Slice: { + if (val_type != nullptr) { + lbValue elem = lb_slice_elem(p, expr); + val = lb_emit_load(p, lb_emit_ptr_offset(p, elem, idx)); + } + break; + } + case Type_DynamicArray: { + if (val_type != nullptr) { + lbValue elem = lb_emit_struct_ep(p, expr, 0); + elem = lb_emit_load(p, elem); + val = lb_emit_load(p, lb_emit_ptr_offset(p, elem, idx)); + } + break; + } + case Type_Map: { + lbAddr key = lb_add_local_generated(p, expr_type->Map.key, true); + + lbValue entries = lb_map_entries_ptr(p, expr); + lbValue elem = lb_emit_struct_ep(p, entries, 0); + elem = lb_emit_load(p, elem); + + lbValue entry = lb_emit_ptr_offset(p, elem, idx); + val = lb_emit_load(p, lb_emit_struct_ep(p, entry, 2)); + + lbValue hash = lb_emit_struct_ep(p, entry, 0); + if (is_type_string(expr_type->Map.key)) { + lbValue str = lb_emit_struct_ep(p, hash, 1); + lb_addr_store(p, key, lb_emit_load(p, str)); + } else { + lbValue hash_ptr = lb_emit_struct_ep(p, hash, 0); + hash_ptr = lb_emit_conv(p, hash_ptr, lb_addr_type(key)); + lb_addr_store(p, key, lb_emit_load(p, hash_ptr)); + } + + idx = lb_addr_load(p, key); + + break; + } + default: + GB_PANIC("Cannot do range_indexed of %s", type_to_string(expr_type)); + break; + } + + if (val_) *val_ = val; + if (idx_) *idx_ = idx; + if (loop_) *loop_ = loop; + if (done_) *done_ = done; +} + + +void lb_build_range_string(lbProcedure *p, lbValue expr, Type *val_type, + lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_) { + lbModule *m = p->module; + lbValue count = lb_const_int(m, t_int, 0); + Type *expr_type = base_type(expr.type); + switch (expr_type->kind) { + case Type_Basic: + count = lb_string_len(p, expr); + break; + default: + GB_PANIC("Cannot do range_string of %s", type_to_string(expr_type)); + break; + } + + lbValue val = {}; + lbValue idx = {}; + lbBlock *loop = nullptr; + lbBlock *done = nullptr; + lbBlock *body = nullptr; + + + lbAddr offset_ = lb_add_local_generated(p, t_int, false); + lb_addr_store(p, offset_, lb_const_int(m, t_int, 0)); + + loop = lb_create_block(p, "for.string.loop"); + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + + + body = lb_create_block(p, "for.string.body"); + done = lb_create_block(p, "for.string.done"); + + lbValue offset = lb_addr_load(p, offset_); + lbValue cond = lb_emit_comp(p, Token_Lt, offset, count); + lb_emit_if(p, cond, body, done); + lb_start_block(p, body); + + + lbValue str_elem = lb_emit_ptr_offset(p, lb_string_elem(p, expr), offset); + lbValue str_len = lb_emit_arith(p, Token_Sub, count, offset, t_int); + auto args = array_make<lbValue >(heap_allocator(), 1); + args[0] = lb_emit_string(p, str_elem, str_len); + lbValue rune_and_len = lb_emit_runtime_call(p, "string_decode_rune", args); + lbValue len = lb_emit_struct_ev(p, rune_and_len, 1); + lb_addr_store(p, offset_, lb_emit_arith(p, Token_Add, offset, len, t_int)); + + + idx = offset; + if (val_type != nullptr) { + val = lb_emit_struct_ev(p, rune_and_len, 0); + } + + if (val_) *val_ = val; + if (idx_) *idx_ = idx; + if (loop_) *loop_ = loop; + if (done_) *done_ = done; +} + + +void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node, Type *val_type, + lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_) { + lbModule *m = p->module; + + // TODO(bill): How should the behaviour work for lower and upper bounds checking for iteration? + // If 'lower' is changed, should 'val' do so or is that not typical behaviour? + + lbValue lower = lb_build_expr(p, node->left); + lbValue upper = {}; + + lbValue val = {}; + lbValue idx = {}; + lbBlock *loop = nullptr; + lbBlock *done = nullptr; + lbBlock *body = nullptr; + + if (val_type == nullptr) { + val_type = lower.type; + } + lbAddr value = lb_add_local_generated(p, val_type, false); + lb_addr_store(p, value, lower); + + lbAddr index = lb_add_local_generated(p, t_int, false); + lb_addr_store(p, index, lb_const_int(m, t_int, 0)); + + loop = lb_create_block(p, "for.interval.loop"); + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + body = lb_create_block(p, "for.interval.body"); + done = lb_create_block(p, "for.interval.done"); + + + TokenKind op = Token_Lt; + switch (node->op.kind) { + case Token_Ellipsis: op = Token_LtEq; break; + case Token_RangeHalf: op = Token_Lt; break; + default: GB_PANIC("Invalid interval operator"); break; + } + + upper = lb_build_expr(p, node->right); + + lbValue curr_value = lb_addr_load(p, value); + lbValue cond = lb_emit_comp(p, op, curr_value, upper); + lb_emit_if(p, cond, body, done); + lb_start_block(p, body); + + val = lb_addr_load(p, value); + idx = lb_addr_load(p, index); + + lb_emit_increment(p, value.addr); + lb_emit_increment(p, index.addr); + + if (val_) *val_ = val; + if (idx_) *idx_ = idx; + if (loop_) *loop_ = loop; + if (done_) *done_ = done; +} + +void lb_build_range_enum(lbProcedure *p, Type *enum_type, Type *val_type, lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_) { + lbModule *m = p->module; + + Type *t = enum_type; + GB_ASSERT(is_type_enum(t)); + Type *enum_ptr = alloc_type_pointer(t); + t = base_type(t); + Type *core_elem = core_type(t); + GB_ASSERT(t->kind == Type_Enum); + i64 enum_count = t->Enum.fields.count; + lbValue max_count = lb_const_int(m, t_int, enum_count); + + lbValue ti = lb_type_info(m, t); + lbValue variant = lb_emit_struct_ep(p, ti, 3); + lbValue eti_ptr = lb_emit_conv(p, variant, t_type_info_enum_ptr); + lbValue values = lb_emit_load(p, lb_emit_struct_ep(p, eti_ptr, 2)); + lbValue values_data = lb_slice_elem(p, values); + + lbAddr offset_ = lb_add_local_generated(p, t_int, false); + lb_addr_store(p, offset_, lb_const_int(m, t_int, 0)); + + lbBlock *loop = lb_create_block(p, "for.enum.loop"); + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + lbBlock *body = lb_create_block(p, "for.enum.body"); + lbBlock *done = lb_create_block(p, "for.enum.done"); + + lbValue offset = lb_addr_load(p, offset_); + lbValue cond = lb_emit_comp(p, Token_Lt, offset, max_count); + lb_emit_if(p, cond, body, done); + lb_start_block(p, body); + + lbValue val_ptr = lb_emit_ptr_offset(p, values_data, offset); + lb_emit_increment(p, offset_.addr); + + lbValue val = {}; + if (val_type != nullptr) { + GB_ASSERT(are_types_identical(enum_type, val_type)); + + if (is_type_integer(core_elem)) { + lbValue i = lb_emit_load(p, lb_emit_conv(p, val_ptr, t_i64_ptr)); + val = lb_emit_conv(p, i, t); + } else { + GB_PANIC("TODO(bill): enum core type %s", type_to_string(core_elem)); + } + } + + if (val_) *val_ = val; + if (idx_) *idx_ = offset; + if (loop_) *loop_ = loop; + if (done_) *done_ = done; +} + +void lb_build_range_tuple(lbProcedure *p, Ast *expr, Type *val0_type, Type *val1_type, + lbValue *val0_, lbValue *val1_, lbBlock **loop_, lbBlock **done_) { + lbBlock *loop = lb_create_block(p, "for.tuple.loop"); + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + lbBlock *body = lb_create_block(p, "for.tuple.body"); + lbBlock *done = lb_create_block(p, "for.tuple.done"); + + lbValue tuple_value = lb_build_expr(p, expr); + Type *tuple = tuple_value.type; + GB_ASSERT(tuple->kind == Type_Tuple); + i32 tuple_count = cast(i32)tuple->Tuple.variables.count; + i32 cond_index = tuple_count-1; + + lbValue cond = lb_emit_struct_ev(p, tuple_value, cond_index); + lb_emit_if(p, cond, body, done); + lb_start_block(p, body); + + + if (val0_) *val0_ = lb_emit_struct_ev(p, tuple_value, 0); + if (val1_) *val1_ = lb_emit_struct_ev(p, tuple_value, 1); + if (loop_) *loop_ = loop; + if (done_) *done_ = done; +} + +void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs) { + lb_open_scope(p); + + Type *val0_type = nullptr; + Type *val1_type = nullptr; + if (rs->val0 != nullptr && !is_blank_ident(rs->val0)) { + val0_type = type_of_expr(rs->val0); + } + if (rs->val1 != nullptr && !is_blank_ident(rs->val1)) { + val1_type = type_of_expr(rs->val1); + } + + if (val0_type != nullptr) { + Entity *e = entity_of_ident(rs->val0); + lb_add_local(p, e->type, e, true); + } + if (val1_type != nullptr) { + Entity *e = entity_of_ident(rs->val1); + lb_add_local(p, e->type, e, true); + } + + lbValue val = {}; + lbValue key = {}; + lbBlock *loop = nullptr; + lbBlock *done = nullptr; + Ast *expr = unparen_expr(rs->expr); + bool is_map = false; + + TypeAndValue tav = type_and_value_of_expr(expr); + + if (is_ast_range(expr)) { + lb_build_range_interval(p, &expr->BinaryExpr, val0_type, &val, &key, &loop, &done); + } else if (tav.mode == Addressing_Type) { + lb_build_range_enum(p, type_deref(tav.type), val0_type, &val, &key, &loop, &done); + } else { + Type *expr_type = type_of_expr(expr); + Type *et = base_type(type_deref(expr_type)); + switch (et->kind) { + case Type_Map: { + is_map = true; + gbAllocator a = heap_allocator(); + lbAddr addr = lb_build_addr(p, expr); + lbValue map = lb_addr_get_ptr(p, addr); + if (is_type_pointer(type_deref(lb_addr_type(addr)))) { + map = lb_addr_load(p, addr); + } + lbValue entries_ptr = lb_map_entries_ptr(p, map); + lbValue count_ptr = lb_emit_struct_ep(p, entries_ptr, 1); + lb_build_range_indexed(p, map, val1_type, count_ptr, &val, &key, &loop, &done); + break; + } + case Type_Array: { + lbValue array = lb_build_addr_ptr(p, expr); + if (is_type_pointer(type_deref(array.type))) { + array = lb_emit_load(p, array); + } + lbAddr count_ptr = lb_add_local_generated(p, t_int, false); + lb_addr_store(p, count_ptr, lb_const_int(p->module, t_int, et->Array.count)); + lb_build_range_indexed(p, array, val0_type, count_ptr.addr, &val, &key, &loop, &done); + break; + } + case Type_EnumeratedArray: { + lbValue array = lb_build_addr_ptr(p, expr); + if (is_type_pointer(type_deref(array.type))) { + array = lb_emit_load(p, array); + } + lbAddr count_ptr = lb_add_local_generated(p, t_int, false); + lb_addr_store(p, count_ptr, lb_const_int(p->module, t_int, et->EnumeratedArray.count)); + lb_build_range_indexed(p, array, val0_type, count_ptr.addr, &val, &key, &loop, &done); + break; + } + case Type_DynamicArray: { + lbValue count_ptr = {}; + lbValue array = lb_build_addr_ptr(p, expr); + if (is_type_pointer(type_deref(array.type))) { + array = lb_emit_load(p, array); + } + count_ptr = lb_emit_struct_ep(p, array, 1); + lb_build_range_indexed(p, array, val0_type, count_ptr, &val, &key, &loop, &done); + break; + } + case Type_Slice: { + lbValue count_ptr = {}; + lbValue slice = lb_build_expr(p, expr); + if (is_type_pointer(slice.type)) { + count_ptr = lb_emit_struct_ep(p, slice, 1); + slice = lb_emit_load(p, slice); + } else { + count_ptr = lb_add_local_generated(p, t_int, false).addr; + lb_emit_store(p, count_ptr, lb_slice_len(p, slice)); + } + lb_build_range_indexed(p, slice, val0_type, count_ptr, &val, &key, &loop, &done); + break; + } + case Type_Basic: { + lbValue string = lb_build_expr(p, expr); + if (is_type_pointer(string.type)) { + string = lb_emit_load(p, string); + } + if (is_type_untyped(expr_type)) { + lbAddr s = lb_add_local_generated(p, default_type(string.type), false); + lb_addr_store(p, s, string); + string = lb_addr_load(p, s); + } + Type *t = base_type(string.type); + GB_ASSERT(!is_type_cstring(t)); + lb_build_range_string(p, string, val0_type, &val, &key, &loop, &done); + break; + } + case Type_Tuple: + lb_build_range_tuple(p, expr, val0_type, val1_type, &val, &key, &loop, &done); + break; + default: + GB_PANIC("Cannot range over %s", type_to_string(expr_type)); + break; + } + } + + + lbAddr val0_addr = {}; + lbAddr val1_addr = {}; + if (val0_type) val0_addr = lb_build_addr(p, rs->val0); + if (val1_type) val1_addr = lb_build_addr(p, rs->val1); + + if (is_map) { + if (val0_type) lb_addr_store(p, val0_addr, key); + if (val1_type) lb_addr_store(p, val1_addr, val); + } else { + if (val0_type) lb_addr_store(p, val0_addr, val); + if (val1_type) lb_addr_store(p, val1_addr, key); + } + + lb_push_target_list(p, rs->label, done, loop, nullptr); + + lb_build_stmt(p, rs->body); + + lb_close_scope(p, lbDeferExit_Default, nullptr); + lb_pop_target_list(p); + lb_emit_jump(p, loop); + lb_start_block(p, done); +} + +void lb_build_inline_range_stmt(lbProcedure *p, AstInlineRangeStmt *rs) { + lbModule *m = p->module; + + lb_open_scope(p); // Open scope here + + Type *val0_type = nullptr; + Type *val1_type = nullptr; + if (rs->val0 != nullptr && !is_blank_ident(rs->val0)) { + val0_type = type_of_expr(rs->val0); + } + if (rs->val1 != nullptr && !is_blank_ident(rs->val1)) { + val1_type = type_of_expr(rs->val1); + } + + if (val0_type != nullptr) { + Entity *e = entity_of_ident(rs->val0); + lb_add_local(p, e->type, e, true); + } + if (val1_type != nullptr) { + Entity *e = entity_of_ident(rs->val1); + lb_add_local(p, e->type, e, true); + } + + lbValue val = {}; + lbValue key = {}; + lbBlock *loop = nullptr; + lbBlock *done = nullptr; + Ast *expr = unparen_expr(rs->expr); + + TypeAndValue tav = type_and_value_of_expr(expr); + + if (is_ast_range(expr)) { + + lbAddr val0_addr = {}; + lbAddr val1_addr = {}; + if (val0_type) val0_addr = lb_build_addr(p, rs->val0); + if (val1_type) val1_addr = lb_build_addr(p, rs->val1); + + TokenKind op = expr->BinaryExpr.op.kind; + Ast *start_expr = expr->BinaryExpr.left; + Ast *end_expr = expr->BinaryExpr.right; + GB_ASSERT(start_expr->tav.mode == Addressing_Constant); + GB_ASSERT(end_expr->tav.mode == Addressing_Constant); + + ExactValue start = start_expr->tav.value; + ExactValue end = end_expr->tav.value; + if (op == Token_Ellipsis) { // .. [start, end] + ExactValue index = exact_value_i64(0); + for (ExactValue val = start; + compare_exact_values(Token_LtEq, val, end); + val = exact_value_increment_one(val), index = exact_value_increment_one(index)) { + + if (val0_type) lb_addr_store(p, val0_addr, lb_const_value(m, val0_type, val)); + if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, index)); + + lb_build_stmt(p, rs->body); + } + } else if (op == Token_RangeHalf) { // ..< [start, end) + ExactValue index = exact_value_i64(0); + for (ExactValue val = start; + compare_exact_values(Token_Lt, val, end); + val = exact_value_increment_one(val), index = exact_value_increment_one(index)) { + + if (val0_type) lb_addr_store(p, val0_addr, lb_const_value(m, val0_type, val)); + if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, index)); + + lb_build_stmt(p, rs->body); + } + } + + + } else if (tav.mode == Addressing_Type) { + GB_ASSERT(is_type_enum(type_deref(tav.type))); + Type *et = type_deref(tav.type); + Type *bet = base_type(et); + + lbAddr val0_addr = {}; + lbAddr val1_addr = {}; + if (val0_type) val0_addr = lb_build_addr(p, rs->val0); + if (val1_type) val1_addr = lb_build_addr(p, rs->val1); + + for_array(i, bet->Enum.fields) { + Entity *field = bet->Enum.fields[i]; + GB_ASSERT(field->kind == Entity_Constant); + if (val0_type) lb_addr_store(p, val0_addr, lb_const_value(m, val0_type, field->Constant.value)); + if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(i))); + + lb_build_stmt(p, rs->body); + } + } else { + lbAddr val0_addr = {}; + lbAddr val1_addr = {}; + if (val0_type) val0_addr = lb_build_addr(p, rs->val0); + if (val1_type) val1_addr = lb_build_addr(p, rs->val1); + + GB_ASSERT(expr->tav.mode == Addressing_Constant); + + Type *t = base_type(expr->tav.type); + + + switch (t->kind) { + case Type_Basic: + GB_ASSERT(is_type_string(t)); + { + ExactValue value = expr->tav.value; + GB_ASSERT(value.kind == ExactValue_String); + String str = value.value_string; + Rune codepoint = 0; + isize offset = 0; + do { + isize width = gb_utf8_decode(str.text+offset, str.len-offset, &codepoint); + if (val0_type) lb_addr_store(p, val0_addr, lb_const_value(m, val0_type, exact_value_i64(codepoint))); + if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(offset))); + lb_build_stmt(p, rs->body); + + offset += width; + } while (offset < str.len); + } + break; + case Type_Array: + if (t->Array.count > 0) { + lbValue val = lb_build_expr(p, expr); + lbValue val_addr = lb_address_from_load_or_generate_local(p, val); + + for (i64 i = 0; i < t->Array.count; i++) { + if (val0_type) { + // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32 + lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i); + lb_addr_store(p, val0_addr, lb_emit_load(p, elem)); + } + if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(i))); + + lb_build_stmt(p, rs->body); + } + + } + break; + case Type_EnumeratedArray: + if (t->EnumeratedArray.count > 0) { + lbValue val = lb_build_expr(p, expr); + lbValue val_addr = lb_address_from_load_or_generate_local(p, val); + + for (i64 i = 0; i < t->EnumeratedArray.count; i++) { + if (val0_type) { + // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32 + lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i); + lb_addr_store(p, val0_addr, lb_emit_load(p, elem)); + } + if (val1_type) { + ExactValue idx = exact_value_add(exact_value_i64(i), t->EnumeratedArray.min_value); + lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, idx)); + } + + lb_build_stmt(p, rs->body); + } + + } + break; + default: + GB_PANIC("Invalid inline for type"); + break; + } + } + + + lb_close_scope(p, lbDeferExit_Default, nullptr); +} + + void lb_build_stmt(lbProcedure *p, Ast *node) { switch (node->kind) { case_ast_node(bs, EmptyStmt, node); @@ -2166,11 +2795,11 @@ void lb_build_stmt(lbProcedure *p, Ast *node) { case_end; case_ast_node(rs, RangeStmt, node); - // TODO(bill): RangeStmt + lb_build_range_stmt(p, rs); case_end; case_ast_node(rs, InlineRangeStmt, node); - // TODO(bill): InlineRangeStmt + lb_build_inline_range_stmt(p, rs); case_end; case_ast_node(ss, SwitchStmt, node); @@ -2339,9 +2968,9 @@ lbValue lb_const_undef(lbModule *m, Type *type) { } -lbValue lb_const_int(lbModule *m, Type *type, unsigned long long value) { +lbValue lb_const_int(lbModule *m, Type *type, u64 value) { lbValue res = {}; - res.value = LLVMConstInt(lb_type(m, type), value, !is_type_unsigned(type)); + res.value = LLVMConstInt(lb_type(m, type), cast(unsigned long long)value, !is_type_unsigned(type)); res.type = type; return res; } @@ -3441,8 +4070,8 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { // ev = exact_value_to_integer(ev); // } else if (is_type_pointer(dst)) { // // IMPORTANT NOTE(bill): LLVM doesn't support pointer constants expect 'null' - // lbValue i = ir_add_module_constant(p->module, t_uintptr, ev); - // return ir_emit(p, ir_instr_conv(p, irConv_inttoptr, i, t_uintptr, dst)); + // lbValue i = lb_add_module_constant(p->module, t_uintptr, ev); + // return lb_emit(p, lb_instr_conv(p, irConv_inttoptr, i, t_uintptr, dst)); // } // return lb_const_value(p->module, t, ev); } @@ -5141,7 +5770,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, case BuiltinProc_atomic_store_unordered: { lbValue dst = lb_build_expr(p, ce->args[0]); lbValue val = lb_build_expr(p, ce->args[1]); - val = lb_emit_conv(p, val, type_deref(ir_type(dst))); + val = lb_emit_conv(p, val, type_deref(lb_type(dst))); return lb_emit(p, lb_instr_atomic_store(p, dst, val, id)); } |