From e3e225d21b613d789ebad0273b198b5509800bf0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 8 Nov 2022 11:04:37 +0000 Subject: [PATCH] Support `for in` loops for `map` --- src/llvm_backend_stmt.cpp | 30 +++++++++++++++++++++++------- src/llvm_backend_utility.cpp | 8 +++++++- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 55b0c4d90..3e4846f02 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -402,6 +402,22 @@ void lb_map_kvh_data_static(lbProcedure *p, lbValue map_value, lbValue *ks_, lbV if (hs_) *hs_ = hs; } +lbValue lb_map_hash_is_valid(lbProcedure *p, lbValue hash) { + // N :: size_of(uintptr)*8 - 1 + // (hash != 0) & (hash>>N == 0) + + u64 top_bit_index = cast(u64)(type_size_of(t_uintptr)*8 - 1); + lbValue shift_amount = lb_const_int(p->module, t_uintptr, top_bit_index); + lbValue zero = lb_const_int(p->module, t_uintptr, 0); + + lbValue not_empty = lb_emit_comp(p, Token_NotEq, hash, zero); + + lbValue not_deleted = lb_emit_arith(p, Token_Shr, hash, shift_amount, t_uintptr); + not_deleted = lb_emit_comp(p, Token_CmpEq, not_deleted, zero); + + return lb_emit_arith(p, Token_And, not_deleted, not_empty, t_uintptr); +} + void lb_build_range_map(lbProcedure *p, lbValue expr, Type *val_type, lbValue *val_, lbValue *key_, lbBlock **loop_, lbBlock **done_) { lbModule *m = p->module; @@ -442,19 +458,19 @@ void lb_build_range_map(lbProcedure *p, lbValue expr, Type *val_type, lbValue vs = lb_map_cell_index_static(p, type->Map.key, ks, capacity); lbValue hs = lb_map_cell_index_static(p, type->Map.value, vs, capacity); + // NOTE(bill): no need to use lb_map_cell_index_static for that hashes + // since it will always be packed without padding into the cells lbValue hash = lb_emit_load(p, lb_emit_ptr_offset(p, hs, idx)); - lbValue hash_cond = lb_emit_comp(p, Token_CmpEq, hash, lb_const_int(m, t_uintptr, 0)); + lbValue hash_cond = lb_map_hash_is_valid(p, hash); lb_emit_if(p, hash_cond, body, loop); lb_start_block(p, body); - // 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); - lbValue key = lb_const_nil(m, type->Map.key); - lbValue val = lb_const_nil(m, type->Map.value); + lbValue key_ptr = lb_map_cell_index_static(p, type->Map.key, ks, idx); + lbValue val_ptr = lb_map_cell_index_static(p, type->Map.value, vs, idx); + lbValue key = lb_emit_load(p, key_ptr); + lbValue val = lb_emit_load(p, val_ptr); if (val_) *val_ = val; if (key_) *key_ = key; diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index dce74126e..cbe690155 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1464,7 +1464,13 @@ lbValue lb_map_cap(lbProcedure *p, lbValue value) { lbValue lb_map_data_uintptr(lbProcedure *p, lbValue value) { GB_ASSERT(is_type_map(value.type)); lbValue data = lb_emit_struct_ev(p, value, 0); - lbValue mask = lb_const_int(p->module, t_uintptr, MAP_CACHE_LINE_SIZE-1); + u64 mask_value = 0; + if (build_context.word_size == 4) { + mask_value = 0xfffffffful & ~(MAP_CACHE_LINE_SIZE-1); + } else { + mask_value = 0xffffffffffffffffull & ~(MAP_CACHE_LINE_SIZE-1); + } + lbValue mask = lb_const_int(p->module, t_uintptr, mask_value); return lb_emit_arith(p, Token_And, data, mask, t_uintptr); }