Skip to content

Commit 703443a

Browse files
Bug fixes.
1 parent 3d3b42e commit 703443a

File tree

1 file changed

+16
-13
lines changed

1 file changed

+16
-13
lines changed

_collections/_portal_posts/2025-09-12-adventures-in-address-space-inference.md

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ For anyone interested, however, Victor Lomüller has done a talk about it, avail
7777
The main limitation with this system was that it required each pointer had to have precisely one address space
7878
which was deduced as part of its initialization. For example:
7979

80-
```c++
80+
```cpp
8181
int* a = some_func(); // the address space of a will be dependant on the return type of some_func
8282

8383
int* b; // default address space is private
@@ -126,7 +126,7 @@ consider that LLVM instructions can generally be treated as function calls.
126126

127127
Here is some nonsensical example code to use as an example:
128128

129-
```c
129+
```cpp
130130
local int *local_input = 0x1000;
131131
unknown int *unknown_input = 0x3000;
132132
global int *global_input = 0x2000;
@@ -168,7 +168,8 @@ With these tools, we can loop through each statement in the module and do the fo
168168
3. Any other functions do nothing special.
169169

170170
Applying this on the previous example, we get the following:
171-
```c
171+
172+
```cpp
172173
local int *local_input = 0x1000;
173174
__a int *unknown_input = 0x3000;
174175
global int *global_input = 0x2000;
@@ -207,7 +208,7 @@ With our example, `__b`, `__a` and `__c` both share a bag with `local`, so get r
207208
bag with `global` and so gets replaced with `global` itself. This results in the final value of our module being the
208209
following:
209210

210-
```c
211+
```cpp
211212
local int *local_input = 0x1000;
212213
local int *unknown_input = 0x3000;
213214
global int *global_input = 0x2000;
@@ -239,7 +240,7 @@ language. This language is very restrictive though, so we need to expand both th
239240
In our rules for `eq` we define the function as having two input bags that are combined into one single bag. Let's steal
240241
some syntax from C++ to represent this, and define a few more functions:
241242

242-
```c
243+
```cpp
243244
bool eq<A>(A int *, A int *);
244245
B int *memcpy<A, B>(A int *, B int *, int);
245246
A int *get_ptr_offset<A>(A int *, int);
@@ -262,7 +263,7 @@ from the previous section with the following:
262263

263264
As an example, consider:
264265

265-
```c
266+
```cpp
266267
A int *do_something_strange<A>(A int *, private int *);
267268

268269
global int *first = 0x1000;
@@ -282,7 +283,7 @@ know that the second argument has the `private` address space, so we add it to `
282283

283284
Then the result of applying these solutions are as follows:
284285

285-
```c
286+
```cpp
286287
global int *do_something_strange<global>(global int *, private int *);
287288

288289
global int *first = 0x1000;
@@ -305,7 +306,8 @@ We will expand our toy language to include the following:
305306
* A `return` expression that returns a given value from the function.
306307

307308
Then, we will work on another example program:
308-
```c
309+
310+
```cpp
309311
int *my_func(unknown int *a, unknown int *b, global int *iftrue, unknown int *iffalse) {
310312
bool check = eq(a, b);
311313
goto truebranch if check else falsebranch;
@@ -321,7 +323,7 @@ int *my_func(unknown int *a, unknown int *b, global int *iftrue, unknown int *if
321323
Generating a templated declaration is relatively simple: We give the return value and arguments bags like any other
322324
value and solve them in the same way. For `my_func`, this would result in this:
323325
324-
```c
326+
```cpp
325327
global int *my_func(__a int *a, __a int *b, global int *iftrue, global int *iffalse) {
326328
// Constrains a and b to the same address space
327329
bool check = eq(a, b);
@@ -340,7 +342,7 @@ global int *my_func(__a int *a, __a int *b, global int *iftrue, global int *iffa
340342
Looking at this function, we see that we can substitute `__a` with any address space we like and still have a valid
341343
function. For stylistic reasons, we use upper case unsolved names, resulting in `my_func` having a declaration of:
342344

343-
```c
345+
```cpp
344346
global int *my_func<A>(A int *, A int *, global int *, global int *);
345347
```
346348

@@ -369,7 +371,7 @@ functions (I told you the name would make sense later):
369371

370372
With that, we are now able to fully handle arbitrary user provided functions. For example, we can go from this:
371373

372-
```c
374+
```cpp
373375
int *my_func(unknown int *a, unknown int *b, global int *iftrue, unknown int *iffalse) {
374376
bool check = eq(a, b);
375377
goto truebranch if check else falsebranch;
@@ -394,7 +396,8 @@ void main() {
394396
```
395397
396398
To this:
397-
```c
399+
400+
```cpp
398401
global int *my_func__private(private int *a, private int *b, global int *iftrue, global int *iffalse) {
399402
bool check = eq(a, b);
400403
goto truebranch if check else falsebranch;
@@ -430,7 +433,7 @@ void main() {
430433
Until now we've only been looking at types that only have a single address. Real world code tends to be more complex,
431434
with multiple levels of pointers, structs and arrays. Take this example, with unsolved address spaces:
432435

433-
```c++
436+
```cpp
434437
struct Element {
435438
__a int * __b *Active;
436439
__c int *Stuff[5];

0 commit comments

Comments
 (0)