Fix heap when size_t is not unsigned long long
When the width of size_t doesn't match the width of the unsigned long long type, the number of leading zeros doesn't match, making the heap_get_move() function return incorrect values. This is the case on ARMv7 with 32 bits, where size_t is 32 bits but unsigned long long is 64 bits. We check the size of size_t to select which builtin we need. The sizeof operator cannot be used at preprocessing, so we rely on the optimizations to only leave the proper assembly instruction. Fixes: https://pm.bsc.es/gitlab/rarias/ovni/-/issues/193
This commit is contained in:
		
							parent
							
								
									91e8367d35
								
							
						
					
					
						commit
						3d8c84e17c
					
				| @ -1,4 +1,4 @@ | ||||
| /* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
 | ||||
| /* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||
| 
 | ||||
| /* Author: David Alvarez
 | ||||
| @ -112,6 +112,20 @@ heap_max(heap_head_t *head) | ||||
| 	return head->root; | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| leading_zeros(size_t x) | ||||
| { | ||||
| 	/* Call and if()'s optimized by the compiler with -O2 */ | ||||
| 	if (sizeof(size_t) == sizeof(unsigned int)) | ||||
| 		return __builtin_clz(x); | ||||
| 	else if (sizeof(size_t) == sizeof(unsigned long)) | ||||
| 		return __builtin_clzl(x); | ||||
| 	else if (sizeof(size_t) == sizeof(unsigned long long)) | ||||
| 		return __builtin_clzll(x); | ||||
| 	else | ||||
| 		die("cannot find suitable size for __builtin_clz*"); | ||||
| } | ||||
| 
 | ||||
| /* Get a move to reach a leaf */ | ||||
| static inline int | ||||
| heap_get_move(size_t *node /*out*/) | ||||
| @ -119,8 +133,8 @@ heap_get_move(size_t *node /*out*/) | ||||
| 	size_t aux_node = *node; | ||||
| 
 | ||||
| 	// Round to previous po2
 | ||||
| 	size_t base = (1ULL) << (sizeof(size_t) * 8 | ||||
| 				      - __builtin_clzll(aux_node) - 1); | ||||
| 	int shift = sizeof(size_t) * 8 - leading_zeros(aux_node) - 1; | ||||
| 	size_t base = 1ULL << shift; | ||||
| 
 | ||||
| 	aux_node -= base / 2; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user