Dear All
After 2 years of using gpc I thought I'd better update to a newer release, so I have installed gcc-2.95.3 and gpc-20010512.
It appears than an old bug has resurfaced. A global variable declared in a module is not initialised properly.
The following code does NOT print out the string 'OK':
-------main.h------------ var s: string(40); external;
procedure print_globals; external; -------------------------
-------main.p------------ program main(input,output);
#include "main.h"
begin s:='OK'; print_globals; end. -------------------------
-------lib.p------------- module lib(input,output);
#include "main.h"
var s:string(40);
procedure print_globals; begin writeln(s); end;
end. -------------------------
Compile with 'gpc -o main main.p lib.p'
If you move the declaration of string 's' from lib.p to main.p it works.
This was fixed about 2 years ago (by Peter I think) but it seems to have gotten un-fixed.
The initialisation code for the Main program, when the variable 's' is defined in the module in lib.p, is not correct. If you do:
# gpc -c lib.p # gpc -S main.p # vi main.s and add "movl $40,S" before .L6: in init_pascal_main_program, then # as -V -Qy -o main.o main.s GNU assembler version 2.10.91 (i386-redhat-linux) using BFD version 2.10.91.0.2 # gpc -o main main.o lib.o # ./main OK
you get the expected result.
Hope there is enough information to fix the problem.
Many thanks
Ian -- Ian Thurlbeck http://www.stams.strath.ac.uk/ Statistics and Modelling Science, University of Strathclyde Livingstone Tower, 26 Richmond Street, Glasgow, UK, G1 1XH Tel: +44 (0)141 548 3667 Fax: +44 (0)141 552 2079 °ïS
Ian Thurlbeck wrote:
After 2 years of using gpc I thought I'd better update to a newer release, so I have installed gcc-2.95.3 and gpc-20010512.
It appears than an old bug has resurfaced. A global variable declared in a module is not initialised properly.
The following code does NOT print out the string 'OK':
-------main.h------------ var s: string(40); external;
procedure print_globals; external;
-------main.p------------ program main(input,output);
#include "main.h"
begin s:='OK'; print_globals; end.
-------lib.p------------- module lib(input,output);
#include "main.h"
var s:string(40);
procedure print_globals; begin writeln(s); end;
end.
Compile with 'gpc -o main main.p lib.p'
If you move the declaration of string 's' from lib.p to main.p it works.
This was fixed about 2 years ago (by Peter I think) but it seems to have gotten un-fixed.
Yes, it was "un-fixed" indeed, to fix other, more important (IMHO) bugs.
The problem is that you use the module in a quite strange (C-ish) way rather than the normal EP `imports' or perhaps the BP `uses'.
GPC generates initialization code for the module which sets the string. But how should the main program know that it should call this initializer? All it sees is an external declaration of a variable -- and normally, it must not initialize external variables because they "belong" to another module (or similar).
The way it was done before is to have the initializers called via some linker hack. This had a number of problems: It didn't work at all on some systems (e.g. IRIX, and anything that does not use GNU ld, IIRC), and even where it did, the order of initializers run was "undefined" or at least not always right which caused problems if the initializer code of one module relied on that of another one already having been run. There may have been more problems ...
So we changed this so the initializers are now called normally from the program and/or the using/importing module/unit's initializers. This works well -- as long as the program/module/unit knows which initializers to call, i.e. not in your case.
I'm not sure why you do it like this -- perhaps it's just a relic from ancient times when GPC didn't know about importing interfaces. In this case, I'd suggest to get rid of it.
Otherwise, any ideas for fixing this are welcome.
Frank
I'm not sure why you do it like this -- perhaps it's just a relic from ancient times when GPC didn't know about importing interfaces. In this case, I'd suggest to get rid of it. Otherwise, any ideas for fixing this are welcome.
The only other solution I can think of:
- such modules shouldn't be allow to initialise, and have stuff that must be initialised global in the implementation part. (the part that is separately compiled)
- All initialisation for the variabeles in the INTERFACE, are done by the mainprogram.
Marco van de Voort wrote:
I'm not sure why you do it like this -- perhaps it's just a relic from ancient times when GPC didn't know about importing interfaces. In this case, I'd suggest to get rid of it. Otherwise, any ideas for fixing this are welcome.
The only other solution I can think of:
- such modules shouldn't be allow to initialise, and have stuff that must be
initialised global in the implementation part. (the part that is separately compiled)
How? When the module is compiled, the compiler doesn't know how it will be used?
- All initialisation for the variabeles in the INTERFACE, are done by the
mainprogram.
Again how? All the compiler sees (in Ian's example) are `external' declarations, and initializing all external variables would in general be wrong.
Frank
Marco van de Voort wrote:
I'm not sure why you do it like this -- perhaps it's just a relic from ancient times when GPC didn't know about importing interfaces. In this case, I'd suggest to get rid of it. Otherwise, any ideas for fixing this are welcome.
The only other solution I can think of:
- such modules shouldn't be allow to initialise, and have stuff that must be
initialised global in the implementation part. (the part that is separately compiled)
How? When the module is compiled, the compiler doesn't know how it will be used?
(Note that I don't judge whether it should be unsupported or not. I just come up with some possible ideas)
[thinking] I see that I have made some assumptions, which I'll try to explain:
It depends on how your link between the header and the module sourcefile is.
When compiling the module sourcefile, is the header then checked? Iow are the header and implementation linked together (so that the header of module a is parsed before with the compilation of the module is started).
If that isn't done (the header is no true interface but a mere EXTERNAL declaration), then it is impossible, because the vars are declared twice, in header and module.
-------------
Otherwise a module could get a special pragma to declare it old style, and then the compiler should not generate initialisation code for interface variables. (mangled) Names of variables to be initialised globally could be stored in .gpi, and initialisation/finalisation code generated when the main module is compiled.
- All initialisation for the variabeles in the INTERFACE, are done by the
mainprogram.
Again how? All the compiler sees (in Ian's example) are `external' declarations, and initializing all external variables would in general be wrong.
Everything imported via #include should be initialised by the mainprogram, and it could be communicated back via de unit (non-object code) file. (gpi with GPC IIRC)
A main program then has to check all involved GPI files. Not only the modules that the mainprogram includes, but also deeper nested stuff.
Marco van de Voort wrote:
Marco van de Voort wrote:
I'm not sure why you do it like this -- perhaps it's just a relic from ancient times when GPC didn't know about importing interfaces. In this case, I'd suggest to get rid of it. Otherwise, any ideas for fixing this are welcome.
The only other solution I can think of:
- such modules shouldn't be allow to initialise, and have stuff that must be
initialised global in the implementation part. (the part that is separately compiled)
How? When the module is compiled, the compiler doesn't know how it will be used?
(Note that I don't judge whether it should be unsupported or not. I just come up with some possible ideas)
That's ok, I just can't see them working out yet ...
[thinking] I see that I have made some assumptions, which I'll try to explain:
It depends on how your link between the header and the module sourcefile is.
When compiling the module sourcefile, is the header then checked? Iow are the header and implementation linked together (so that the header of module a is parsed before with the compilation of the module is started).
In this example, yes, because the header is also (explicitly) included in the module. For shared constants and types, that's useful (IMHO not as good as simply using/importing the module, but still better than copying the declarations). For variables and routines, it's kind of superfluous (it just might cause the compiler to warn if the actual declaration differs).
If that isn't done (the header is no true interface but a mere EXTERNAL declaration), then it is impossible, because the vars are declared twice, in header and module.
They're only once really declared (in the module), and twice external, once in the module (superfluous) and once in the program.
Otherwise a module could get a special pragma to declare it old style, and then the compiler should not generate initialisation code for interface variables. (mangled) Names of variables to be initialised globally could be stored in .gpi, and initialisation/finalisation code generated when the main module is compiled.
The problem is that the compiler run for the main program doesn't read the GPI file for the module (because it doesn't know about the module, it just sees the external declarations). If it did read the GPI file, everything would be fine, since that's how it is normally informed about the initializers to be called.
- All initialisation for the variabeles in the INTERFACE, are done by the
mainprogram.
Again how? All the compiler sees (in Ian's example) are `external' declarations, and initializing all external variables would in general be wrong.
Everything imported via #include should be initialised by the mainprogram, and it could be communicated back via de unit (non-object code) file. (gpi with GPC IIRC)
I don't think so. #include (which is basically the same as {$include} you might know from BP) just preprocesses the given source file. Someone might want to put some other kind of declarations in an include (which should not be initialized if external). So, include files should behave just as if the code was inserted in place of the include directive (that's also BP compatible, so I don't suppose you'd suggest otherwise ;-). So we can't use the include as an indication.
A main program then has to check all involved GPI files. Not only the modules that the mainprogram includes, but also deeper nested stuff.
That's actually a different issue (we've decided to solve it instead by letting each module's initializer call the initializers of modules it uses, and make sure that each initializer is called only once, using a flag -- as far as we know, this works well). The issue here is that the dependency (though direct, not even nested) is "hidden" from the compiler.
Frank
Dear Frank
The reason I use this odd style is because the program involved is part of a suite of numerical programs which were originally written using Suns Pascal compiler. It was then ported to Decs Pascal, then finally to gpc. The original code used this style of modules and global variables (actually there are only 2 if I remember correctly) and both Sun and Dec pascal support this style. gpc almost does :) or did. I can't change the program code because lots of user models have been written against this and they would stop compiling if I changed something like this.
Can anyone suggest a workaround ? Thanks again
Ian
On Friday 18 May 2001 17:06, you wrote:
Ian Thurlbeck wrote:
After 2 years of using gpc I thought I'd better update to a newer release, so I have installed gcc-2.95.3 and gpc-20010512.
It appears than an old bug has resurfaced. A global variable declared in a module is not initialised properly.
The following code does NOT print out the string 'OK':
-------main.h------------ var s: string(40); external;
procedure print_globals; external;
-------main.p------------ program main(input,output);
#include "main.h"
begin s:='OK'; print_globals; end.
-------lib.p------------- module lib(input,output);
#include "main.h"
var s:string(40);
procedure print_globals; begin writeln(s); end;
end.
Compile with 'gpc -o main main.p lib.p'
If you move the declaration of string 's' from lib.p to main.p it works.
This was fixed about 2 years ago (by Peter I think) but it seems to have gotten un-fixed.
Yes, it was "un-fixed" indeed, to fix other, more important (IMHO) bugs.
The problem is that you use the module in a quite strange (C-ish) way rather than the normal EP `imports' or perhaps the BP `uses'.
GPC generates initialization code for the module which sets the string. But how should the main program know that it should call this initializer? All it sees is an external declaration of a variable -- and normally, it must not initialize external variables because they "belong" to another module (or similar).
The way it was done before is to have the initializers called via some linker hack. This had a number of problems: It didn't work at all on some systems (e.g. IRIX, and anything that does not use GNU ld, IIRC), and even where it did, the order of initializers run was "undefined" or at least not always right which caused problems if the initializer code of one module relied on that of another one already having been run. There may have been more problems ...
So we changed this so the initializers are now called normally from the program and/or the using/importing module/unit's initializers. This works well -- as long as the program/module/unit knows which initializers to call, i.e. not in your case.
I'm not sure why you do it like this -- perhaps it's just a relic from ancient times when GPC didn't know about importing interfaces. In this case, I'd suggest to get rid of it.
Otherwise, any ideas for fixing this are welcome.
Frank
Ian Thurlbeck wrote:
The reason I use this odd style is because the program involved is part of a suite of numerical programs which were originally written using Suns Pascal compiler. It was then ported to Decs Pascal, then finally to gpc. The original code used this style of modules and global variables (actually there are only 2 if I remember correctly) and both Sun and Dec pascal support this style. gpc almost does :) or did. I can't change the program code because lots of user models have been written against this and they would stop compiling if I changed something like this.
The question remains -- how does the compiler know the module name. The only way I can think of right now is to explicitly give it on the command line (something like `--init-modules=foo,bar'). I think this would be fairly easy to implement in the compiler (though it's probably just a kludge). Would this help you?
Frank