libnexus-rv
return-stack.h
1 // SPDX-License-Identifier: Apache 2.0
2 /*
3  * return-stack.h - NexusRV return stack
4  *
5  * Copyright (C) 2025, Bo Gan <ganboing@gmail.com>
6  */
7 
8 #ifndef LIBNEXUS_RV_RETURN_STACK_H
9 #define LIBNEXUS_RV_RETURN_STACK_H
10 
11 #include <assert.h>
12 #include <stdint.h>
13 #include <stdlib.h>
14 
15 #define NEXUS_RV_RETSTACK_DEFAULT 32
16 
17 typedef struct nexusrv_return_stack {
18  uint64_t *entries;
19  unsigned size;
20  unsigned max;
21  unsigned used;
22  unsigned end;
24 
25 static inline int nexusrv_retstack_init(nexusrv_return_stack *stack,
26  unsigned max) {
27  stack->end = stack->used = 0;
28  stack->max = stack->size = max;
29  if (max > NEXUS_RV_RETSTACK_DEFAULT)
30  stack->size = NEXUS_RV_RETSTACK_DEFAULT;
31  stack->entries = NULL;
32  if (!stack->size)
33  return 0;
34  stack->entries = (uint64_t*)malloc(
35  sizeof(stack->entries[0]) * stack->size);
36  if (!stack->entries)
37  return -nexus_no_mem;
38  return 0;
39 }
40 
41 static inline void nexusrv_retstack_fini(nexusrv_return_stack *stack) {
42  free(stack->entries);
43  stack->entries = NULL;
44 }
45 
46 static inline unsigned nexusrv_retstack_used(nexusrv_return_stack *stack) {
47  return stack->used;
48 }
49 
50 static inline void nexusrv_retstack_clear(nexusrv_return_stack *stack) {
51  stack->used = 0;
52  stack->end = 0;
53 }
54 
55 static inline int nexusrv_retstack_may_enlarge(nexusrv_return_stack *stack) {
56  if (stack->size == stack->max)
57  return 0;
58  assert(stack->used == stack->end);
59  if (stack->used != stack->size)
60  return 0;
61  unsigned newsize = stack->size * 2;
62  if (newsize > stack->max)
63  newsize = stack->max;
64  void *newptr = realloc(stack->entries,
65  sizeof(stack->entries[0]) * newsize);
66  if (!newptr)
67  return -nexus_no_mem;
68  stack->size = newsize;
69  stack->entries = (uint64_t*)newptr;
70  return 0;
71 }
72 
73 static inline int nexusrv_retstack_push(nexusrv_return_stack *stack,
74  uint64_t addr) {
75  if (stack->used == stack->max)
76  return 0;
77  int rc = nexusrv_retstack_may_enlarge(stack);
78  if (rc < 0)
79  return rc;
80  if (stack->end == stack->size)
81  stack->end = 0;
82  stack->entries[stack->end++] = addr;
83  if (stack->used < stack->size)
84  ++stack->used;
85  return 0;
86 }
87 
88 static inline int nexusrv_retstack_pop(nexusrv_return_stack *stack,
89  uint64_t *addr) {
90  if (!stack->used)
91  return -nexus_trace_retstack_empty;
92  assert(stack->end);
93  *addr = stack->entries[--stack->end];
94  --stack->used;
95  if (!stack->end && stack->used)
96  stack->end = stack->size;
97  return 0;
98 }
99 
100 #undef NEXUS_RV_RETSTACK_DEFAULT
101 
102 #endif
Definition: return-stack.h:17