[cfe-dev] Mixed 32b/64b pointers in same translation unit

Patrik Eklöf via cfe-dev cfe-dev at lists.llvm.org
Thu Feb 2 10:12:31 PST 2017


Well, it does the same thing if you type out the type too, which is why I left it as auto:

__attribute((address_space(4))) void bar() {}
constexpr __attribute__((address_space(4))) void(*HiIAmA32BitPtr)(){ &bar };

int main()
{
                static_assert(sizeof(HiIAmA32BitPtr) == 4); // Assertion fails
}

Regards,
Patrik Eklöf

From: Reid Kleckner [mailto:rnk at google.com]
Sent: 02 February 2017 13:09
To: Patrik Eklöf <patrik.eklof at energymachines.com>
Cc: cfe-dev at lists.llvm.org
Subject: Re: [cfe-dev] Mixed 32b/64b pointers in same translation unit

I wouldn't be surprised if our attribute parsing does strange things around auto. We have a lot of heuristics to try to figure out which attributes apply to which part of the type or declaration. Address spaces are primarily used by opencl and cuda, so if you can write idiomatic cuda to do it, then it'll probably work.

On Thu, Feb 2, 2017 at 10:00 AM, Patrik Eklöf <patrik.eklof at energymachines.com<mailto:patrik.eklof at energymachines.com>> wrote:
Thanks for the answer, Reid.

I tried your suggestion and it worked on simpler types where I initialize pointers to some constant value, e.g.

constexpr __attribute__((address_space(0))) int* HiIAmA64BitPtr{ nullptr };
constexpr __attribute__((address_space(4))) int* HiIAmA32BitPtr{ nullptr };

int main()
{
                static_assert(sizeof(HiIAmA32BitPtr) == 4);
                static_assert(sizeof(HiIAmA64BitPtr) == 8);
}

But when I tried something more complex, it stops working. For example:

void foo() {}
__attribute((address_space(4))) void bar() {}

constexpr __attribute__((address_space(0))) auto* HiIAmA64BitPtr{ &foo };
constexpr __attribute__((address_space(4))) auto* HiIAmA32BitPtr{ &bar };

int main()
{
                constexpr auto SizeOf32 = sizeof(HiIAmA32BitPtr);
                constexpr auto SizeOf64 = sizeof(HiIAmA64BitPtr);
                static_assert(sizeof(HiIAmA32BitPtr) == 4);
                static_assert(sizeof(HiIAmA64BitPtr) == 8);
}

From what I can gather, it tries to take the address space of the parent type (or the dereferenced type of a pointer). My guess is that in the former experiment, the attribute binds to the dereferenced type and not the pointer? In this case, it doesn’t seem to work, though. Presumably because the attribute binds to the pointer type? I’m not sure. Regardless, it doesn’t work, and I’m still not sure why.

The assert that the 32-bit pointer is 4 bytes fails.

Any ideas?

Regards,
Patrik Eklöf


From: Reid Kleckner [mailto:rnk at google.com<mailto:rnk at google.com>]
Sent: 02 February 2017 12:05
To: Patrik Eklöf <patrik.eklof at energymachines.com<mailto:patrik.eklof at energymachines.com>>
Cc: cfe-dev at lists.llvm.org<mailto:cfe-dev at lists.llvm.org>
Subject: Re: [cfe-dev] Mixed 32b/64b pointers in same translation unit

I think you're on the right track with address spaces, but you need to modify clang/lib/Basic/Targets.cpp to override TargetInfo::getPointerWidthV to give a different size.

If you go down this road, consider making __ptr32 and __ptr64 work better. MSVC accepts this code but clang rejects:

struct Foo { int *__ptr32 p; };
int *__ptr32 p;
int *__ptr64 q;
static_assert(sizeof(Foo) == 4, "Foo");
static_assert(sizeof(p) == 4, "p");
static_assert(sizeof(q) == 8, "q");

On Thu, Feb 2, 2017 at 8:05 AM, Patrik Eklöf via cfe-dev <cfe-dev at lists.llvm.org<mailto:cfe-dev at lists.llvm.org>> wrote:
Dear community,

I am looking at trying to use clang in such a way that it is possible to use both 32-bit and 64-bit pointers in the same translation unit. Is this currently supported?

I would like to enable it on a per-pointer basis, and it would be ideal if it is part of the type. I am thinking that one would do something like…

[[ptr_32]] int* p;

…or the like to tell the compiler specifically that it is a 32-bit pointer (the rest will be 64-bit). I am compiling to a 64-bit target, so all pointers should natively be 64-bit.

I’ve been looking over the source a little, and see references to address space and an attribute __address_space__ that enables one to choose the address space for variables. It seems that depending on the address space, different sizes for pointers can be used. I tried modifying the DataLayout::reset function (I realize I should probably modify the targets instead of the layout class itself) to add another entry to the Pointers vector:

setPointerAlignment(0, 8, 8, 8);
setPointerAlignment(4, 4, 4, 4);

…and using the address space extension to pick out the right size for some pointers:

__attribute__((address_space(0))) int* HiIAmA64BitPtr{ (int*)0xFFFF'FFFF'FFFF'FFFF };
__attribute__((address_space(4))) int* HiIAmA32BitPtr{ (__attribute__((address_space(4))) int*)0xFFFF'FFFF'FFFF'FFFF };

But that did not appear to work. When running the code and printing the size of the variables, I see that they are both 8 bytes:

std::cout << "Size of 64-bit ptr: " << sizeof(HiIAmA64BitPtr) << std::endl; // Prints 8
std::cout << "Size of 32-bit ptr: " << sizeof(HiIAmA32BitPtr) << std::endl; // Prints 8

Furthermore, for some strange reason, if I print the LLVM IR using clang++ -S -emit-llvm, I see that all pointers seem to be 32 bits long even without using the address space extension. Yet, a long long variable (called Test here) has a 64-bit size:

target triple = "x86_64-pc-windows-msvc19.0.0"

@"\01?HiIAmA64BitPtr@@3PEAHEA" = global i32* inttoptr (i64 -1 to i32*), align 8
@"\01?HiIAmA32BitPtr@@3PEAHEA" = global i32 addrspace(4)* inttoptr (i64 -1 to i32 addrspace(4)*), align 8
@"\01?g_Test@@3_KA" = global i64 0, align 8

This seems very odd to me. Can someone point me in the right direction on how to approach this?

My command line for compiling:

clang++ "Test.cpp" -std=c++1z -Wall -fms-compatibility-version=19 -c -o Test.o && "link.exe" -out:Test.exe -defaultlib:libcmt -nologo Test.o

(For some reason, clang is unable to invoke the linker correctly on its own.)
Regards,
Patrik Eklöf


_______________________________________________
cfe-dev mailing list
cfe-dev at lists.llvm.org<mailto:cfe-dev at lists.llvm.org>
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170202/771c0516/attachment.html>


More information about the cfe-dev mailing list