Quantcast

Mixed 32b/64b pointers in same translation unit

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Mixed 32b/64b pointers in same translation unit

Asiri Rathnayake via cfe-dev

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
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Mixed 32b/64b pointers in same translation unit

Asiri Rathnayake via cfe-dev
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 <[hidden email]> 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
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Mixed 32b/64b pointers in same translation unit

Asiri Rathnayake via cfe-dev

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:[hidden email]]
Sent: 02 February 2017 12:05
To: Patrik Eklöf <[hidden email]>
Cc: [hidden email]
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 <[hidden email]> 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
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

 


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Mixed 32b/64b pointers in same translation unit

Asiri Rathnayake via cfe-dev
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 <[hidden email]> 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:[hidden email]]
Sent: 02 February 2017 12:05
To: Patrik Eklöf <[hidden email]>
Cc: [hidden email]
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 <[hidden email]> 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
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

 



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Mixed 32b/64b pointers in same translation unit

Asiri Rathnayake via cfe-dev

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:[hidden email]]
Sent: 02 February 2017 13:09
To: Patrik Eklöf <[hidden email]>
Cc: [hidden email]
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 <[hidden email]> 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:[hidden email]]
Sent: 02 February 2017 12:05
To: Patrik Eklöf <[hidden email]>
Cc: [hidden email]
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 <[hidden email]> 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
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

 

 


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Mixed 32b/64b pointers in same translation unit

Asiri Rathnayake via cfe-dev
In reply to this post by Asiri Rathnayake via cfe-dev
On 2/2/2017 10:00 AM, Patrik Eklöf via cfe-dev 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?

 


clang doesn't currently support address spaces on function pointers.  You're getting a weird result because the address space is getting attached to the return type; clang should reject that, but currently doesn't.

-Eli
-- 
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Mixed 32b/64b pointers in same translation unit

Asiri Rathnayake via cfe-dev

Useful information.

 

Thanks.

 

Regards,

Patrik Eklöf

 

 

 

From: Friedman, Eli [mailto:[hidden email]]
Sent: 02 February 2017 19:18
To: Patrik Eklöf <[hidden email]>; Reid Kleckner <[hidden email]>
Cc: [hidden email]
Subject: Re: [cfe-dev] Mixed 32b/64b pointers in same translation unit

 

On 2/2/2017 10:00 AM, Patrik Eklöf via cfe-dev 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?

 


clang doesn't currently support address spaces on function pointers.  You're getting a weird result because the address space is getting attached to the return type; clang should reject that, but currently doesn't.

-Eli

-- 
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Loading...