10
votes

Currently I use i8* to represent void pointers in my generated IR, but this makes it quite difficult to differentiate void* from char*, for example. Are there any common approaches to solving this? I have searched around quite a bit with no luck.

For every other pair of types I am able to directly use the llvm::Type* to differentiate the types, so it adds a lot of complexity if I can no longer do that just for the special case of void pointers.

One idea might be to use a named struct containing i8 as the void type (for example, %void = type { i8 } ) and take pointers to that instead, but clang generated IR uses i8* when you give it a void pointer type, so I am not sure what the advantages/disadvantages of each are.

1
In general types belong in the frontend of your compiler. It's just luck that the LLVM type system might be similar to yours, and it's free to change out from under you (one example: opaque pointer types are coming). There shouldn't be a need to distinguish types at the LLVM level. - Ismail Badawi
if you start from source and have debug info enabled, you can parse them to know what a pointer really is (uint*, void*, ...). If you write (or generate) your own llvmIR, I don't see why you'd need that... - Regis Portalez
@IsmailBadawi that all makes sense. Thank you. Seems like it is time to write a more complete type system for my compiler. By the way, if you made that an answer I would accept it. - Lane

1 Answers

7
votes

In general types belong in the frontend of your compiler. It's just luck that the LLVM type system might be similar to yours, and it's free to change out from under you (one example: opaque pointer types are coming). There shouldn't be a need to distinguish types at the LLVM level -- trying to force a 1:1 correspondence between your type system and the LLVM type system is probably misguided.