Software Archive
Read-only legacy content
17061 Discussions

Static variable alignment

james1
Beginner
1,056 Views
I need to align a static variable on a 64k boundary. On OVMS one did this by using the PSECT ALIGN directive, however CVF does not appear to support this past 6. Any suggestions?
0 Kudos
10 Replies
Steven_L_Intel1
Employee
1,056 Views
The MS linker doesn't support this - sorry. What are you trying to accomplish? Perhaps there's another way...

Steve
0 Kudos
james1
Beginner
1,056 Views
I need to use MapViewOfFileEx with lpBaseAddress pointing to the address of a 64k aligned static data structure. There should be a way, otherwise I don't know why this Win32 routine would exist in addition to the MapViewOfFile call. Thanks.

James
0 Kudos
james1
Beginner
1,056 Views
Also I noticed from the release notes that ALIGN=PAGE should work (note that it does not solve this problem, I need ALIGN=16) but that doesn't appear to work in the 6.6 RC. From what I can tell the directive has no effect regardless of value.

James
0 Kudos
Steven_L_Intel1
Employee
1,056 Views
Hmm - I'll ask our local expert on such things to see what is going on...

Steve
0 Kudos
Steven_L_Intel1
Employee
1,056 Views
Ok, here's the scoop.

First, there's a bug in CVF, in that alignments greater than 6 are limited to 6. We'll fix that.

Second, the documentation says that for IA32, an alignment of 13, not 16, is the maximum, and that PAGE gets you 12 (4096 bytes), which is indeed the Windows page size.

Third, the PE-COFF object file format does not support alignments past 8192 bytes, so we couldn't go past that even if we wanted to.

MapViewOfFileEx does not suggest that there is a way to get 64K-aligned static data. It leaves it up to you to figure out how to get the address space. My recommendation is to create a COMMON of size 128K-1 bytes and then take the address of the last element and IAND it with Z'FFFF0000' to get your address. How you deal with that as a variable in Fortran is an exercise left for the reader.

Steve
0 Kudos
james1
Beginner
1,056 Views
First, I still contend that the alignment directive is being ignored for all values. Just an FYI, I have example code if needed.

Second, I believe the limitation in the linker, and am just trying to determine a way around it without resorting to pointers for a large body of existing code (using a large, complex structure mapped to a global section under OVMS, with direct access to the record variable from all code). I know the page size is 4k, but unfortunately that isn't sufficient alignment for this call, which requires 64k.

Regarding creating a common of size 2^17-1 this does not work, the original common remains aligned on a 2^6 boundary which doesn't help. Unless I can get a location (even if not properly aligned) at compile time, I have no way to base structures by relying upon chopping off the low order 16 bits. If I had the information at compile time then indeed I could equivalence to the appropriate location in a byte array, but doing this calculation at runtime doesn't appear to gain anything over using pointers.

James
0 Kudos
Steven_L_Intel1
Employee
1,056 Views
My tests show that the directive does work, up to a maximum alignment of 6.

As for using pointers, yes, that's essentially what I was proposing.

Steve
0 Kudos
james1
Beginner
1,056 Views
Regarding pointers, I would just use MapViewOfFile and that would be that. :-) Just trying to make this transparent to a lot of existing code...


Anyhow here is what *I* see regarding the operation of the PSECT ALIGN directive.


  
align.f90  
  
program test_align  
implicit none  
integer aval  
byte base  
byte x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12  
common /cx0/ x0  
common /cx1/ x1  
common /cx2/ x2  
common /cx3/ x3  
common /cx4/ x4  
common /cx5/ x5  
common /cx6/ x6  
common /cx7/ x7  
common /cx8/ x8  
common /cx9/ x9  
common /cx10/ x10  
common /cx11/ x11  
common /cx12/ x12  
!DEC$ PSECT /cx0/ ALIGN=0  
!DEC$ PSECT /cx1/ ALIGN=1  
!DEC$ PSECT /cx2/ ALIGN=2  
!DEC$ PSECT /cx3/ ALIGN=3  
!DEC$ PSECT /cx4/ ALIGN=4  
!DEC$ PSECT /cx5/ ALIGN=5  
!DEC$ PSECT /cx6/ ALIGN=6  
!DEC$ PSECT /cx7/ ALIGN=7  
!DEC$ PSECT /cx8/ ALIGN=8  
!DEC$ PSECT /cx9/ ALIGN=9  
!DEC$ PSECT /cx10/ ALIGN=10  
!DEC$ PSECT /cx11/ ALIGN=11  
!DEC$ PSECT /cx12/ ALIGN=12  
type *  
type *, 'LOCATION REQUESTED ACTUAL'  
type 1, loc(base), -1, aval(loc(base))  
type 1, loc(x0), 0, aval(loc(x0))  
type 1, loc(x1), 1, aval(loc(x1))  
type 1, loc(x2), 2, aval(loc(x2))  
type 1, loc(x3), 3, aval(loc(x3))  
type 1, loc(x4), 4, aval(loc(x4))  
type 1, loc(x5), 5, aval(loc(x5))  
type 1, loc(x6), 6, aval(loc(x6))  
type 1, loc(x7), 7, aval(loc(x7))  
type 1, loc(x8), 8, aval(loc(x8))  
type 1, loc(x9), 9, aval(loc(x9))  
type 1, loc(x10), 10, aval(loc(x10))  
type 1, loc(x11), 11, aval(loc(x11))  
type 1, loc(x12), 12, aval(loc(x12))  
1 format(x,z8.8,6x,i2,6x,i2)  
end  
  
integer function aval (addr)  
integer addr  
integer i,j  
i = 0; j = -1  
do while (j .lt. 0 .and. i .lt. bit_size(addr)-1)  
  if (btest(addr,i)) then  
    j = i  
  else  
    i = i + 1  
  end if  
end do  
aval = j  
return  
end  
  
Result under Windows XP Pro build 2505 CVF 6.6  
  
LOCATION REQUESTED ACTUA  
00448604      -1       2  
0044C040       0       6  
0044C038       1       3  
0044C030       2       4  
0044C028       3       3  
0044C020       4       5  
0044C018       5       3  
0044C010       6       4  
0044C008       7       3  
0044C000       8      14  
0044BFF8       9       3  
0044BFF0      10       4  
0044BFE8      11       3  
0044BFE0      12       5  
  
Sanity check on OpenVMS Alpha V7.3 CF 7.3  
  
LOCATION REQUESTED ACTUAL  
00040000      -1      18  
00040010       0       4  
00040012       1       1  
00041004       2       2  
00041008       3       3  
00041010       4       4  
00041020       5       5  
00041040       6       6  
00041080       7       7  
00041100       8       8  
00041200       9       9  
00040400      10      10  
00040800      11      11  
00041000      12      12  

FWIW,


James

0 Kudos
Steven_L_Intel1
Employee
1,056 Views
James,

I have good news and bad news. The good news is that we'll fix the compiler to allow alignments up to 13 to work. The bad news is that the Microsoft object format does not recognize alignment requests on uninitialized COMMONs - there's nothing we can do about this. The workaround is to DATA initialize at least one variable in your COMMON. Note that you must do this in one program unit only, preferably a BLOCK DATA subprogram. We'll amend our documentation to state this.

Steve
0 Kudos
james1
Beginner
1,056 Views
Steve,

I came across a proposed solution in C and wondered if there was a way to do this in CVF. The following procedure (roughly) should do the job in C:

 
 
typedef structure _record_str 
{ 
  
    INT    record_number; 
    DWORD  number; 
    struct record_junk; ... 
  
}    _record_str; 
  
#pragma data_seg(".record_seg") 
extern _record_str _record_common; 
#pragma data_seg() 
 


This link with /align:0x10000. Of course this gives all program sections 64k alignment but there aren't that many. I notice that with my previous example that all commons are placed in the same program section (.data), so is there any way to identify a common with a separate program section?

James
0 Kudos
Reply