I’m generating some LLVM IR that has to mask out the lower bits two bits of a certain pointers. I expect this should be done like so (on a 32-bit architecture)
%classPointer = …
%classPointer1 = ptrtoint i8** %classPointer to i32
%classPointer2 = and i32 -4, %classPointer1
%realClassPointer = inttoptr i32 %classPointer2 to i8**
Ideally, I’d like to generate completely architecture-independent code, which brings me to my question: Does LLVM have some sort of i<target_ptr_size> type that I can cast to to do this masking (like size_t in C), instead of generating different LLVM IR for 32- and 64- bit architectures?
Small nitpick: size_t is not guaranteed to be large enough to hold a
pointer (only an array index, which can be less; though such platforms
are pretty exotic now). [u]intptr_t are the types.
This has come up in the past, although I don't think anyone
implemented it. Use your favorite list archive frontend to search for
That and the possibility of differently sized pointers made me
hesitate to dive into implementing this. I guess nailing it down to
be the platform equivalent of size_t would be sensible here.
I looked through the “intp” thread.
I don’t really want to start that argument up again, but my immediate thought would be to create a new class of “picked-by-the-target” integer types (equivelents of size_t, intptr_t, etc…), and two new instructions, zcast and scast, which are only valid in the context of casting to / from integer types of unknown sizes. To begin with, most passes could probably ignore (or otherwise pass pass over) these instructions. The resolution of these types would only happen in the legalize phase in the SelectionDAG.
Just my two cents…
For now, I’ll settle for a little architecture dependence in my front-end.
That might be your best bet. There is more architecture dependence
that isn't trivial to get rid of:
1. The ABI varies from OS to OS on many platforms, and ABI details are
sometimes handled by llvm-gcc/clang rather than llc. There's also at
least one case where a particular named type is passed/returned
differently from other types with the same structure.
2. Unions aren't really implemented in LLVM, and any front-end
implementations require knowledge of the platform (which union member
is the largest, the integer or the pointer?)
3. va_arg is handled specially be llvm-gcc/clang, because it's not
implemented on all platforms.
You can hide a lot of this in a platform dependent .bc file that you
ship with your front-end, or have your front-end build for you.
Support/TypeBuilder.h has some macros you might find useful for
generating a Module with a platform-independent API that does the
necessary typecasting for you to call platform-dependent stuff.
TypeBuilder takes a compile-type C/C++ type and turns it into an