64 bit Porting Problem !!!

Dear All,

I am trying to build my code (currently functioning on 32bit) on 64 bit SUSE machine.
I am getting following error:

warning: initializer element is not computable at load time
dau.gss.c:275: error: initializer element is not constant
dau.gss.c:275: error: (near initialization for `type_hs.utility.n')

in dau.gss.c the content is :

line no. Code

...
...
272 static DH_T_HS ca_type_hs =
273 {0, DH_B_OID, 0, 0, ASN1_OID, 0, 3, 0, 0x55, 4, 37};
274 static DH_T_HS type_hs =
275 {(UINT32)&ca_type_hs, DH_B_OID, 0, 0, ASN1_OID, 0, 3, 0, 0x55, 4, 36};
...
...

Following are some definitions related to the above mentioned code:

typedef unsigned int UINT32;
typedef unsigned char OCTET;
typedef unsigned short UINT16;

typedef struct dh_t_hs {
union {
UINT32 n;
struct dh_t_hs *p;
} utility;

OCTET        cntrl;
OCTET        flags;
UINT16        use;                    
UINT16        id2;
UINT16        use2;                    
UINT32        count;                    
UINT32        count_lmt;

union \{
    OCTET            id [4];
    OCTET            prime [4];
    UINT32            list [1];
    struct dh\_t_hs    *construct [1];
\} content;                            

} DH_T_HS, *DH_P_HS;

If I make the "n" variable unsigned long (in union "utility" within structure dh_t_hs) and if in "type_hs" variable (@ line 275 in the file dau.gss.c) I do "(unsigned long)&ca_type_hs", I dont get the above mentioned error.

But the problem is that I cant make the "n" variable unsigned long (in union "utility" within structure "dh_t_hs") as it used widely in the project as an integer only.

Could anybody please suggest some solution for the same?

Thanks in advance.

Regards.
Thanks in advance.

Regards,

You do realize that 64 bit architecture means 64-bit pointers, which means 8-byte pointers, which is the same size as an unsigned long, right?

Have you tried making it just a "long". Presumably the only reason you CANNOT use a signed long in place of a signed integer is that your code expects the integer to overflow at some point, or it purposefully shifts bits to the left and then expecting the 33rd bit to not be present.

Hi otheus,

Thanx for your reply. Carefully looking at the code gave me idea that making that variable as unsigned long is harmless. So I made it as unsigned long.

I am facing another issue for which I need your help. Could you give me any idea about some compiler flags which give 64 bit porting specific warnings for LInux? For example in Solaris if I provide "CC +w2 -xarch=v9" it gives the 64 bit porting warnings, but I couldn't find any similar things for Linux. I am using "gcc" to build the project and the above mentioned flag is not working with this.

Thank you in advance.

Regards,
Saurabh

Mostly all there is is "-march" option. I don't know about the -xarch option, but it looks specific to the SPARC hardware, not Solaris. Similarly, you want warnings specific to a 64-bit architecture, not Linux. Looking through the man pages, one will find references to Operating Systems being compiled on specific architectures. One thing you can do is use the "-mlong32" option which forces all "long" specifications and pointers to 32 bits. This might not be a problem unless you expect the program to require more than 32 bits of addressing space (IE, more than 4GB of memory).

Hi Otheus,

You are right on the point that I want to know the architecture of the CPU. Doing "isainfo" on Solaris gives the CPU architecture but the command is not working on Linux. I also did "cat /proc/cpuinfo" but its not providing the architecture type which I could use in -march switch. Even in gcc manual i could not find the appropriate value.
To check the appropriate flags to get desired warnings I wrote a sample code which is as follows:

#include <iostream>

using namespace std;

int main()
{
unsigned long ul = ~1UL;
int i = 20,j;
int *ip = &i;
i = ul;
j = (int) ip;
return 1;
}

If I build the code on 64 bit machine I should get warnings for the following two lines:
i = ul;
j = (int) ip;
But when i copiled it with "gcc -c -m64 -Wall -Wmissing-prototypes" I am getting only one warning i.e. "warnings.cpp:11: warning: cast from pointer to integer of different size". I am not getting warning for long to int assignement for the line "i = ul;".
Could you suggest me something on this.

Regards,
Saurabh

Your machine hardware is 64 bit, but is the OS? The code generated by -m64 depends on the "environment", not the actual hardware:

       -m64
           Generate code for a 32-bit or 64-bit environment.  The 32-bit envi-
           ronment sets int, long and pointer to 32 bits and generates code
           that runs on any i386 system.  The 64-bit environment sets int to
           32 bits and long and pointer to 64 bits and generates code for
           AMD's x86-64 architecture.

So type "uname -a" and "arch" to see what environment you are actually running under. If it's x86_64, then you are indeed on 64-bit. Otherwise, it's 32-bit.

Yes ofcourse the OS is 64 bit. its x86_64.

Thats why I am wondering why it is not giving warning for long to int assignment.
uname -a gave following result:

Linux msglxd03 2.6.5-7.97-smp #1 SMP Fri Jul 2 14:21:59 UTC 2004 x86_64 x86_64 x86_64 GNU/Linux

I have gcc 4.1.1 installed. Maybe you have an older version. If so, this might not apply to you.

I am not familiar with the options you mentioned, but the v9 is definitely SPARC architecture specific. Using "-m64" will produce code for the 64-bit platform, which would be the default anyway. ints will be 32 bits, and pointers and longs will be 64-bits. You could use -mabi=32 will generate 32-bit code for your 64-bit platform. This might result in an inability to link against 64-bit libraries, but if you have 32-bit libraries also installed, it should work. You can do something similar with "-mlong32", which forces all longs and pointer types to 32 bits (but still uses the 64-bit abi so it could run on a 64 bit platform). It might be possible to combine -mlong-calls with this to ensure proper behavior with the linker, but that's just a WAG (wild ass guess).

I thought there was a way to tell the compiler to treat an "int" as 64-bits, but I cannot find an option for that in the manual. You can always use the preprocessor to try to change "int" into "long", but that might not work in some instances.

I found some links that might help:
http://gcc.fyxm.net/summit/2003/Porting%20to%2064%20bit.pdf

This link specifically says you must use gcc 4 and later, and mentions a few options pertinent to your task.
64-Bit Transition Guide: Compiling 64-Bit Code Using GCC

Hi Guys...

Is there any solution for the prob I mentioned previously ?

Regards.

Which problem do you still have?

As I mentioned...I dont want long and pointers to be as 32 bit in 64 bit machine..I also dont want to generate 32 bit code by using -m32....I just want that on 64 bit machine if I am assigning long to int, it should give truncation warning which I am not getting even after using all switch option. If there is any option which make long as 32 bit but still keeps pointers as 64 bit, it could be worth noticing.

Thanks in advance.