Why is my 32-bit pointer treated like a 64-bit pointer?

Hi all,

I’m trying to implement mixed 32/64-bit pointers in the same translation unit. But right now, clang is doing something I don’t understand why.

If I take this simple C++ code:

#include

template

using Addr32 = __attribute((address_space(32))) T;

void Debug(Addr32* p1, int* p2, int* p3, Addr32* p4);

Addr32 i1 = 1234;

Addr32* p1;

int main()

{

p1 = &i1;

static_assert(sizeof(p1) == 4);

}

And compile it, I get the following IR without optimizations:

@“\01?i1@@3HA” = addrspace(32) global i32 1234, align 4

@“\01?p1@@3PEAHEA” = global i32 addrspace(32)* null, align 4

; Function Attrs: norecurse nounwind uwtable

define i32 @main() #0

{

store i32 addrspace(32)* @“\01?i1@@3HA”, i32 addrspace(32)** @“\01?p1@@3PEAHEA”, align 4

ret i32 0

}

And with optimizations (-O3), it becomes

@“\01?i1@@3HA” = addrspace(32) global i32 1234, align 4

@“\01?p1@@3PEAHEA” = local_unnamed_addr global i32 addrspace(32)* null, align 8

; Function Attrs: norecurse nounwind uwtable

define i32 @main() local_unnamed_addr #0

{

store i32 addrspace(32)* @“\01?i1@@3HA”, i32 addrspace(32)** @“\01?p1@@3PEAHEA”, align 8, !tbaa !8

ret i32 0

}

Both of them produce the same assembly:

lea rcx, [rip + “?i1@@3HA”]

mov qword ptr [rip + “?p1@@3PEAHEA”], rcx

So even though I have a 32-bit pointer (static_assert(sizeof(p1) == 4)) and alignment 4 (in the debug version), it gets treated as a 64-bit pointer with alignment 8 in the assembly. Clang also somehow optimizes the pointer by aligning it on a 8-byte boundary when optimizing.

I’ve overridden TargetInfo::getPointerWidthV and TargetInfo::getPointerAlignV to properly return 32 bits for a pointer in address space 32. I’ve also modified the Pointers vector in the DataLayout to return 4 bytes for both size and alignment for address space 32. Is there something I’m missing? Why is clang treating the pointers as 64 bits?

Regards,

Patrik Eklöf

I’ve overridden TargetInfo::getPointerWidthV and
TargetInfo::getPointerAlignV to properly return 32 bits for a pointer in
address space 32.

Just about all that'll affect is sizeof/alignof and structure layout
algorithms. Things the C front-end handles.

I’ve also modified the Pointers vector in the DataLayout
to return 4 bytes for both size and alignment for address space 32. Is there
something I’m missing? Why is clang treating the pointers as 64 bits?

That's closer to CodeGen, but I'm afraid the x86 backend just isn't
written to deal with different address-spaces having different pointer
sizes right now. Virtually all the choices it makes are based on a
simple "isTarget64BitLP64" check.

I'd expect it to be quite a lot of work in lib/Target/X86 to get this going.

Tim.