1//
2// m3_code.c
3//
4// Created by Steven Massey on 4/19/19.
5// Copyright © 2019 Steven Massey. All rights reserved.
6//
7
8#include "m3_code.h"
9#include "m3_env.h"
10
11//---------------------------------------------------------------------------------------------------------------------------------
12
13
14IM3CodePage NewCodePage (IM3Runtime i_runtime, u32 i_minNumLines)
15{
16 IM3CodePage page;
17
18 u32 pageSize = sizeof (M3CodePageHeader) + sizeof (code_t) * i_minNumLines;
19
20 pageSize = (pageSize + (d_m3CodePageAlignSize-1)) & ~(d_m3CodePageAlignSize-1); // align
21 page = (IM3CodePage)m3_Malloc ("M3CodePage", pageSize);
22
23 if (page)
24 {
25 page->info.sequence = ++i_runtime->newCodePageSequence;
26 page->info.numLines = (pageSize - sizeof (M3CodePageHeader)) / sizeof (code_t);
27
28#if d_m3RecordBacktraces
29 u32 pageSizeBt = sizeof (M3CodeMappingPage) + sizeof (M3CodeMapEntry) * page->info.numLines;
30 page->info.mapping = (M3CodeMappingPage *)m3_Malloc ("M3CodeMappingPage", pageSizeBt);
31
32 if (page->info.mapping)
33 {
34 page->info.mapping->size = 0;
35 page->info.mapping->capacity = page->info.numLines;
36 }
37 else
38 {
39 m3_Free (page);
40 return NULL;
41 }
42 page->info.mapping->basePC = GetPageStartPC(page);
43#endif // d_m3RecordBacktraces
44
45 m3log (runtime, "new page: %p; seq: %d; bytes: %d; lines: %d", GetPagePC (page), page->info.sequence, pageSize, page->info.numLines);
46 }
47
48 return page;
49}
50
51
52void FreeCodePages (IM3CodePage * io_list)
53{
54 IM3CodePage page = * io_list;
55
56 while (page)
57 {
58 m3log (code, "free page: %d; %p; util: %3.1f%%", page->info.sequence, page, 100. * page->info.lineIndex / page->info.numLines);
59
60 IM3CodePage next = page->info.next;
61#if d_m3RecordBacktraces
62 m3_Free (page->info.mapping);
63#endif // d_m3RecordBacktraces
64 m3_Free (page);
65 page = next;
66 }
67
68 * io_list = NULL;
69}
70
71
72u32 NumFreeLines (IM3CodePage i_page)
73{
74 d_m3Assert (i_page->info.lineIndex <= i_page->info.numLines);
75
76 return i_page->info.numLines - i_page->info.lineIndex;
77}
78
79
80void EmitWord_impl (IM3CodePage i_page, void * i_word)
81{ d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines);
82 i_page->code [i_page->info.lineIndex++] = i_word;
83}
84
85void EmitWord32 (IM3CodePage i_page, const u32 i_word)
86{ d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines);
87 * ((u32 *) & i_page->code [i_page->info.lineIndex++]) = i_word;
88}
89
90void EmitWord64 (IM3CodePage i_page, const u64 i_word)
91{
92#if M3_SIZEOF_PTR == 4
93 d_m3Assert (i_page->info.lineIndex+2 <= i_page->info.numLines);
94 * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word;
95 i_page->info.lineIndex += 2;
96#else
97 d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines);
98 * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word;
99 i_page->info.lineIndex += 1;
100#endif
101}
102
103
104#if d_m3RecordBacktraces
105void EmitMappingEntry (IM3CodePage i_page, u32 i_moduleOffset)
106{
107 M3CodeMappingPage * page = i_page->info.mapping;
108 d_m3Assert (page->size < page->capacity);
109
110 M3CodeMapEntry * entry = & page->entries[page->size++];
111 pc_t pc = GetPagePC (i_page);
112
113 entry->pcOffset = pc - page->basePC;
114 entry->moduleOffset = i_moduleOffset;
115}
116#endif // d_m3RecordBacktraces
117
118pc_t GetPageStartPC (IM3CodePage i_page)
119{
120 return & i_page->code [0];
121}
122
123
124pc_t GetPagePC (IM3CodePage i_page)
125{
126 if (i_page)
127 return & i_page->code [i_page->info.lineIndex];
128 else
129 return NULL;
130}
131
132
133void PushCodePage (IM3CodePage * i_list, IM3CodePage i_codePage)
134{
135 IM3CodePage next = * i_list;
136 i_codePage->info.next = next;
137 * i_list = i_codePage;
138}
139
140
141IM3CodePage PopCodePage (IM3CodePage * i_list)
142{
143 IM3CodePage page = * i_list;
144 * i_list = page->info.next;
145 page->info.next = NULL;
146
147 return page;
148}
149
150
151
152u32 FindCodePageEnd (IM3CodePage i_list, IM3CodePage * o_end)
153{
154 u32 numPages = 0;
155 * o_end = NULL;
156
157 while (i_list)
158 {
159 * o_end = i_list;
160 ++numPages;
161 i_list = i_list->info.next;
162 }
163
164 return numPages;
165}
166
167
168u32 CountCodePages (IM3CodePage i_list)
169{
170 IM3CodePage unused;
171 return FindCodePageEnd (i_list, & unused);
172}
173
174
175IM3CodePage GetEndCodePage (IM3CodePage i_list)
176{
177 IM3CodePage end;
178 FindCodePageEnd (i_list, & end);
179
180 return end;
181}
182
183#if d_m3RecordBacktraces
184bool ContainsPC (IM3CodePage i_page, pc_t i_pc)
185{
186 return GetPageStartPC (i_page) <= i_pc && i_pc < GetPagePC (i_page);
187}
188
189
190bool MapPCToOffset (IM3CodePage i_page, pc_t i_pc, u32 * o_moduleOffset)
191{
192 M3CodeMappingPage * mapping = i_page->info.mapping;
193
194 u32 pcOffset = i_pc - mapping->basePC;
195
196 u32 left = 0;
197 u32 right = mapping->size;
198
199 while (left < right)
200 {
201 u32 mid = left + (right - left) / 2;
202
203 if (mapping->entries[mid].pcOffset < pcOffset)
204 {
205 left = mid + 1;
206 }
207 else if (mapping->entries[mid].pcOffset > pcOffset)
208 {
209 right = mid;
210 }
211 else
212 {
213 *o_moduleOffset = mapping->entries[mid].moduleOffset;
214 return true;
215 }
216 }
217
218 // Getting here means left is now one more than the element we want.
219 if (left > 0)
220 {
221 left--;
222 *o_moduleOffset = mapping->entries[left].moduleOffset;
223 return true;
224 }
225 else return false;
226}
227#endif // d_m3RecordBacktraces
228
229//---------------------------------------------------------------------------------------------------------------------------------
230
231
232