Kaynağa Gözat

Merge branch 'master' into windows-llvm-13.0.0

gingerBill 2 yıl önce
ebeveyn
işleme
cb47c78af6

+ 75 - 110
core/strings/strings.odin

@@ -3,9 +3,7 @@ package strings
 
 import "core:io"
 import "core:mem"
-import "core:slice"
 import "core:unicode"
-import "core:runtime"
 import "core:unicode/utf8"
 
 // returns a clone of the string `s` allocated using the `allocator`
@@ -996,6 +994,36 @@ last_index_any :: proc(s, chars: string) -> int {
 	return -1
 }
 
+index_multi :: proc(s: string, substrs: []string) -> (idx: int, width: int) {
+	idx = -1
+	if s == "" || len(substrs) <= 0 {
+		return
+	}
+	// disallow "" substr
+	for substr in substrs {
+		if len(substr) == 0 {
+			return
+		}
+	}
+
+	lowest_index := len(s)
+	found := false
+	for substr in substrs {
+		if i := index(s, substr); i >= 0 {
+			if i < lowest_index {
+				lowest_index = i
+				width = len(substr)
+				found = true
+			}
+		}
+	}
+
+	if found {
+		idx = lowest_index
+	}
+	return
+}
+
 /*
 	returns the count of the string `substr` found in the string `s`
 	returns the rune_count + 1 of the string `s` on empty `substr`
@@ -1412,142 +1440,79 @@ trim_suffix :: proc(s, suffix: string) -> string {
 	res := strings.split_multi("testing,this.out_nice---done~~~last", splits[:])
 	fmt.eprintln(res) // -> [testing, this, out, nice, done, last]
 */
-split_multi :: proc(s: string, substrs: []string, allocator := context.allocator) -> (buf: []string) #no_bounds_check {
+split_multi :: proc(s: string, substrs: []string, allocator := context.allocator) -> []string #no_bounds_check {
 	if s == "" || len(substrs) <= 0 {
-		return
+		return nil
 	}
 
 	// disallow "" substr
 	for substr in substrs {
 		if len(substr) == 0 {
-			return
+			return nil
 		}
 	}
 
-	// TODO maybe remove duplicate substrs
-	// sort substrings by string size, largest to smallest
-	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
-	temp_substrs := slice.clone(substrs, context.temp_allocator)
-
-	slice.sort_by(temp_substrs, proc(a, b: string) -> bool {
-		return len(a) > len(b)	
-	})
-
-	substrings_found: int
-	temp := s
-
-	// count substr results found in string
-	first_pass: for len(temp) > 0 {
-		for substr in temp_substrs {
-			size := len(substr)
-
-			// check range and compare string to substr
-			if size <= len(temp) && temp[:size] == substr {
-				substrings_found += 1
-				temp = temp[size:]
-				continue first_pass
-			}
+	// calculate the needed len of `results`
+	n := 1
+	for it := s; len(it) > 0; {
+		i, w := index_multi(it, substrs)
+		if i < 0 {
+			break
 		}
-
-		// step through string
-		_, skip := utf8.decode_rune_in_string(temp[:])
-		temp = temp[skip:]
-	}
-
-	// skip when no results
-	if substrings_found < 1 {
-		return
+		n += 1
+		it = it[i+w:]
 	}
 
-	buf = make([]string, substrings_found + 1, allocator)
-	buf_index: int
-	temp = s
-	temp_old := temp
-
-	// gather results in the same fashion
-	second_pass: for len(temp) > 0 {
-		for substr in temp_substrs {
-			size := len(substr)
-
-			// check range and compare string to substr
-			if size <= len(temp) && temp[:size] == substr {
-				buf[buf_index] = temp_old[:len(temp_old) - len(temp)]
-				buf_index += 1
-				temp = temp[size:]
-				temp_old = temp
-				continue second_pass
+	results := make([dynamic]string, 0, n, allocator)
+	{
+		it := s
+		for len(it) > 0 {
+			i, w := index_multi(it, substrs)
+			if i < 0 {
+				break
 			}
+			part := it[:i]
+			append(&results, part)
+			it = it[i+w:]
 		}
-
-		// step through string
-		_, skip := utf8.decode_rune_in_string(temp[:])
-		temp = temp[skip:]
-	}
-
-	buf[buf_index] = temp_old[:]
-
-	return buf
-}
-
-// state for the split multi iterator
-Split_Multi :: struct {
-	temp: string,
-	temp_old: string,
-	substrs: []string,
-}
-
-// returns split multi state with sorted `substrs`
-split_multi_init :: proc(s: string, substrs: []string) -> Split_Multi {
-	// sort substrings, largest to smallest
-	temp_substrs := slice.clone(substrs, context.temp_allocator)
-	slice.sort_by(temp_substrs, proc(a, b: string) -> bool {
-		return len(a) > len(b)	
-	})	
-
-	return {
-		temp = s,
-		temp_old = s,
-		substrs = temp_substrs,
+		append(&results, it)
 	}
+	assert(len(results) == n)
+	return results[:]
 }
 
 /*
 	splits the input string `s` by all possible `substrs` []string in an iterator fashion
 	returns the split string every iteration, the full string on no match
-
 	splits := [?]string { "---", "~~~", ".", "_", "," }
-	state := strings.split_multi_init("testing,this.out_nice---done~~~last", splits[:])
-	for str in strings.split_multi_iterate(&state) {
+	it := "testing,this.out_nice---done~~~last"
+	for str in strings.split_multi_iterate(&it, splits[:]) {
 		fmt.eprintln(str) // every iteration -> [testing, this, out, nice, done, last]
 	}
 */
-split_multi_iterate :: proc(using sm: ^Split_Multi) -> (res: string, ok: bool) #no_bounds_check {
-	pass: for len(temp) > 0 {
-		for substr in substrs {
-			size := len(substr)
-
-			// check range and compare string to substr
-			if size <= len(temp) && temp[:size] == substr {
-				res = temp_old[:len(temp_old) - len(temp)]
-				temp = temp[size:]
-				temp_old = temp
-				ok = true
-				return 	
-			}
-		}
-
-		// step through string
-		_, skip := utf8.decode_rune_in_string(temp[:])
-		temp = temp[skip:]
+split_multi_iterate :: proc(it: ^string, substrs: []string) -> (res: string, ok: bool) #no_bounds_check {
+	if it == nil || len(it) == 0 || len(substrs) <= 0 {
+		return
 	}
 
-	// allow last iteration
-	if temp_old != "" {
-		res = temp_old[:]	
-		ok = true
-		temp_old = ""
+	// disallow "" substr
+	for substr in substrs {
+		if len(substr) == 0 {
+			return
+		}
 	}
 
+	// calculate the needed len of `results`
+	i, w := index_multi(it^, substrs)
+	if i >= 0 {
+		res = it[:i]
+		it^ = it[i+w:]
+	} else {
+		// last value
+		res = it^
+		it^ = it[len(it):]
+	}
+	ok = true
 	return
 }
 

+ 0 - 2
src/llvm_backend.hpp

@@ -337,8 +337,6 @@ struct lbProcedure {
 
 	LLVMMetadataRef debug_info;
 
-	lbAddr current_elision_hint;
-
 	PtrMap<Ast *, lbValue> selector_values;
 	PtrMap<Ast *, lbAddr>  selector_addr;
 	PtrMap<LLVMValueRef, lbTupleFix> tuple_fix_map;

+ 1 - 7
src/llvm_backend_const.cpp

@@ -485,13 +485,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo
 					LLVMValueRef ptr = LLVMBuildInBoundsGEP2(p->builder, llvm_type, array_data, indices, 2, "");
 					LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true);
 
-					lbAddr slice = {};
-					if (p->current_elision_hint.addr.value && are_types_identical(lb_addr_type(p->current_elision_hint), type)) {
-						slice = p->current_elision_hint;
-						p->current_elision_hint = {};
-					} else {
-						slice = lb_add_local_generated(p, type, false);
-					}
+					lbAddr slice = lb_add_local_generated(p, type, false);
 					map_set(&m->exact_value_compound_literal_addr_map, value.value_compound, slice);
 
 					lb_fill_slice(p, slice, {ptr, alloc_type_pointer(elem)}, {len, t_int});

+ 33 - 31
src/llvm_backend_stmt.cpp

@@ -2269,54 +2269,56 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
 			return;
 		}
 
-		auto lvals = array_make<lbAddr>(permanent_allocator(), 0, vd->names.count);
-
-		for (Ast *name : vd->names) {
-			lbAddr lval = {};
-			if (!is_blank_ident(name)) {
-				Entity *e = entity_of_node(name);
-				// bool zero_init = true; // Always do it
-				bool zero_init = vd->values.count == 0;
-				lval = lb_add_local(p, e->type, e, zero_init);
-			}
-			array_add(&lvals, lval);
-		}
+		TEMPORARY_ALLOCATOR_GUARD();
 
 		auto const &values = vd->values;
-		if (values.count > 0) {
-			auto inits = array_make<lbValue>(permanent_allocator(), 0, lvals.count);
+		if (values.count == 0) {
+			auto lvals = slice_make<lbAddr>(temporary_allocator(), vd->names.count);
+			for_array(i, vd->names) {
+				Ast *name = vd->names[i];
+				if (!is_blank_ident(name)) {
+					Entity *e = entity_of_node(name);
+					// bool zero_init = true; // Always do it
+					bool zero_init = values.count == 0;
+					lvals[i] = lb_add_local(p, e->type, e, zero_init);
+				}
+			}
+		} else {
+			auto lvals_preused = slice_make<bool>(temporary_allocator(), vd->names.count);
+			auto lvals = slice_make<lbAddr>(temporary_allocator(), vd->names.count);
+			auto inits = array_make<lbValue>(temporary_allocator(), 0, lvals.count);
 
 			isize lval_index = 0;
 			for (Ast *rhs : values) {
-				p->current_elision_hint = lvals[lval_index];
-
 				rhs = unparen_expr(rhs);
 				lbValue init = lb_build_expr(p, rhs);
-			#if 1
-				if (p->current_elision_hint.addr.value != lvals[lval_index].addr.value) {
-					lvals[lval_index] = {}; // do nothing so that nothing will assign to it
-				} else {
+
+				if (rhs->kind == Ast_CompoundLit) {
 					// NOTE(bill, 2023-02-17): lb_const_value might produce a stack local variable for the
 					// compound literal, so reusing that variable should minimize the stack wastage
-					if (rhs->kind == Ast_CompoundLit) {
-						lbAddr *comp_lit_addr = map_get(&p->module->exact_value_compound_literal_addr_map, rhs);
-						if (comp_lit_addr) {
-							Entity *e = entity_of_node(vd->names[lval_index]);
-							if (e) {
-								GB_ASSERT(p->current_elision_hint.addr.value == nullptr);
-								GB_ASSERT(p->current_elision_hint.addr.value != lvals[lval_index].addr.value);
-								lvals[lval_index] = {}; // do nothing so that nothing will assign to it
-							}
+					lbAddr *comp_lit_addr = map_get(&p->module->exact_value_compound_literal_addr_map, rhs);
+					if (comp_lit_addr) {
+						if (Entity *e = entity_of_node(vd->names[lval_index])) {
+							lbValue val = comp_lit_addr->addr;
+							lb_add_entity(p->module, e, val);
+							lb_add_debug_local_variable(p, val.value, e->type, e->token);
+							lvals_preused[lval_index] = true;
 						}
 					}
 				}
-			#endif
 
 				lval_index += lb_append_tuple_values(p, &inits, init);
 			}
 			GB_ASSERT(lval_index == lvals.count);
 
-			p->current_elision_hint = {};
+			for_array(i, vd->names) {
+				Ast *name = vd->names[i];
+				if (!is_blank_ident(name) && !lvals_preused[i]) {
+					Entity *e = entity_of_node(name);
+					bool zero_init = values.count == 0;
+					lvals[i] = lb_add_local(p, e->type, e, zero_init);
+				}
+			}
 
 			GB_ASSERT(lvals.count == inits.count);
 			for_array(i, inits) {