|
@@ -737,6 +737,22 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node,
|
|
|
lb_start_block(p, done);
|
|
|
}
|
|
|
|
|
|
+gb_internal lbValue lb_enum_values_slice(lbProcedure *p, Type *enum_type, i64 *enum_count_) {
|
|
|
+ Type *t = enum_type;
|
|
|
+ GB_ASSERT(is_type_enum(t));
|
|
|
+ t = base_type(t);
|
|
|
+ GB_ASSERT(t->kind == Type_Enum);
|
|
|
+ i64 enum_count = t->Enum.fields.count;
|
|
|
+
|
|
|
+ if (enum_count_) *enum_count_ = enum_count;
|
|
|
+
|
|
|
+ lbValue ti = lb_type_info(p, t);
|
|
|
+ lbValue variant = lb_emit_struct_ep(p, ti, 4);
|
|
|
+ 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));
|
|
|
+ return values;
|
|
|
+}
|
|
|
+
|
|
|
gb_internal 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;
|
|
|
|
|
@@ -744,15 +760,11 @@ gb_internal void lb_build_range_enum(lbProcedure *p, Type *enum_type, Type *val_
|
|
|
GB_ASSERT(is_type_enum(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);
|
|
|
+ i64 enum_count = 0;
|
|
|
|
|
|
- lbValue ti = lb_type_info(p, t);
|
|
|
- lbValue variant = lb_emit_struct_ep(p, ti, 4);
|
|
|
- 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 = lb_enum_values_slice(p, enum_type, &enum_count);
|
|
|
lbValue values_data = lb_slice_elem(p, values);
|
|
|
+ lbValue max_count = lb_const_int(m, t_int, enum_count);
|
|
|
|
|
|
lbAddr offset_ = lb_add_local_generated(p, t_int, false);
|
|
|
lb_addr_store(p, offset_, lb_const_int(m, t_int, 0));
|
|
@@ -1052,6 +1064,74 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
|
|
|
case Type_Tuple:
|
|
|
lb_build_range_tuple(p, expr, val0_type, val1_type, &val, &key, &loop, &done);
|
|
|
break;
|
|
|
+
|
|
|
+ case Type_BitSet: {
|
|
|
+ lbModule *m = p->module;
|
|
|
+
|
|
|
+ lbValue the_set = lb_build_expr(p, expr);
|
|
|
+ if (is_type_pointer(type_deref(the_set.type))) {
|
|
|
+ the_set = lb_emit_load(p, the_set);
|
|
|
+ }
|
|
|
+
|
|
|
+ Type *elem = et->BitSet.elem;
|
|
|
+ if (is_type_enum(elem)) {
|
|
|
+ i64 enum_count = 0;
|
|
|
+ lbValue values = lb_enum_values_slice(p, elem, &enum_count);
|
|
|
+ lbValue values_data = lb_slice_elem(p, values);
|
|
|
+ lbValue max_count = lb_const_int(m, t_int, enum_count);
|
|
|
+
|
|
|
+ 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.bit_set.enum.loop");
|
|
|
+ lb_emit_jump(p, loop);
|
|
|
+ lb_start_block(p, loop);
|
|
|
+
|
|
|
+ lbBlock *body_check = lb_create_block(p, "for.bit_set.enum.body-check");
|
|
|
+ lbBlock *body = lb_create_block(p, "for.bit_set.enum.body");
|
|
|
+ done = lb_create_block(p, "for.bit_set.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_check, done);
|
|
|
+ lb_start_block(p, body_check);
|
|
|
+
|
|
|
+ lbValue val_ptr = lb_emit_ptr_offset(p, values_data, offset);
|
|
|
+ lb_emit_increment(p, offset_.addr);
|
|
|
+ val = lb_emit_load(p, val_ptr);
|
|
|
+ val = lb_emit_conv(p, val, elem);
|
|
|
+
|
|
|
+ lbValue check = lb_build_binary_in(p, val, the_set, Token_in);
|
|
|
+ lb_emit_if(p, check, body, loop);
|
|
|
+ lb_start_block(p, body);
|
|
|
+ } else {
|
|
|
+ lbAddr offset_ = lb_add_local_generated(p, t_int, false);
|
|
|
+ lb_addr_store(p, offset_, lb_const_int(m, t_int, et->BitSet.lower));
|
|
|
+
|
|
|
+ lbValue max_count = lb_const_int(m, t_int, et->BitSet.upper);
|
|
|
+
|
|
|
+ loop = lb_create_block(p, "for.bit_set.range.loop");
|
|
|
+ lb_emit_jump(p, loop);
|
|
|
+ lb_start_block(p, loop);
|
|
|
+
|
|
|
+ lbBlock *body_check = lb_create_block(p, "for.bit_set.range.body-check");
|
|
|
+ lbBlock *body = lb_create_block(p, "for.bit_set.range.body");
|
|
|
+ done = lb_create_block(p, "for.bit_set.range.done");
|
|
|
+
|
|
|
+ lbValue offset = lb_addr_load(p, offset_);
|
|
|
+ lbValue cond = lb_emit_comp(p, Token_LtEq, offset, max_count);
|
|
|
+ lb_emit_if(p, cond, body_check, done);
|
|
|
+ lb_start_block(p, body_check);
|
|
|
+
|
|
|
+ val = lb_emit_conv(p, offset, elem);
|
|
|
+ lb_emit_increment(p, offset_.addr);
|
|
|
+
|
|
|
+ lbValue check = lb_build_binary_in(p, val, the_set, Token_in);
|
|
|
+ lb_emit_if(p, check, body, loop);
|
|
|
+ lb_start_block(p, body);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
default:
|
|
|
GB_PANIC("Cannot range over %s", type_to_string(expr_type));
|
|
|
break;
|