davidgiven / ack

The Amsterdam Compiler Kit
http://tack.sf.net
Other
414 stars 60 forks source link

libc, libsys have name conflict with Pascal #43

Open kernigh opened 7 years ago

kernigh commented 7 years ago

The following Pascal program causes a linker error, because its procedure malloc conflicts with malloc in libc:

program callmalloc(output);

var p : ^integer;

procedure malloc;
begin
   writeln('pass');
end;

begin
   new(p);
   malloc;
end.
$ ack -mlinuxppc -o callmalloc callmalloc.p 
led: /home/kernigh/park/ack-build/staging/share/ack/linuxppc/libc.a(malloc.o): _malloc: multiply defined (error)

This only happens because Pascal's new uses libc's malloc (since c084f9f). If I delete the new(p); line and the p variable, then the program prints pass.

This kind of name conflict seems to be caused by recent changes to ACK. Older ACK did more to prevent name conflicts between Pascal and C. In older ACK, Pascal programs did not link to libc. Old descr files like lib/i386/descr don't link libc to Pascal programs, but new descr files like plat/linux386/descr do link libc.

Also in older ack, libsys had alternate names for some system calls. These names had underscores, like _exit and _times. They hid from Pascal because Pascal has no underscores in its names. Pascal's libpc called the hidden names. Commit 1c83baa in 2007, and later commits, switched some calls to the regular names like close and open, but the regular names can conflict with Pascal programs.

dram commented 7 years ago

lang/pc/libpc/READ_ME also mentioned this problem. But this file is quite old, it maybe out of time.

davidgiven commented 7 years ago

Hmm, yeah.

Modula-2 doesn't suffer from this because it mangles Modula-2 symbol names to include the module name as well. Possibly Pascal should do the same thing? With the extern function declaration syntax, we could still import C symbols easily enough.

Looks like fpc does exactly this, BTW:

$ nm test.o
[...]
0000000000000000 T P$CALLMALLOC_$$_MALLOC

Luckily there's already at least some code in the Pascal compiler for doing this, in gen_proc_name(): https://github.com/davidgiven/ack/blob/default/lang/pc/comp/misc.c It's used for generating unique names for nested functions, but should be adaptable. I don't know how hard it would be to not mangle extern declarations.

Also, what about multiple compilation? How does Pascal normally handle this?

dram commented 7 years ago

I think that ISO 7185 does not specify module system, which is added in ISO 10206, both can be found at here.

davidgiven commented 7 years ago

The ACK docs for the Pascal compiler (here: http://tack.sourceforge.net/olddocs/pascal.pdf) has a long list of ISO 7185 extensions which are implemented, none of which I can find references for. extern is apparently defined in ISO 6.1.4. However, the doc says later (in section 10.2) that the compiler only works with programs, not modules, so that sounds like it's only possible to use extern with non-Pascal identifiers.

That means that mangling Pascal symbol names but not extern names should work fine here.

kernigh commented 7 years ago

The doc is out of date. Here's our module system at work.

(* part1.p *)
program part1(output);
function secret : integer; extern;
begin
   writeln('The secret is', secret);
end.
(* part2.p *)
function secret : integer;
begin
   secret := 2000;
end;

Compile with ack -o part1 part1.p part2.p. The compiler for part1 can't know if secret is in C or Pascal.

I found this feature by accident while looking for _m_a_i_n in the Pascal runtime. The compiler only emits _m_a_i_n in a program. If the Pascal file isn't a program, it's a module.

davidgiven commented 7 years ago

That's both really useful and very annoying --- because extern is used to link both external Pascal symbols and external C symbols we can't use different mangling to distinguish the two.

Open to suggestions --- I don't know what's the best thing to do here (potentially, nothing, and just live with the libc naming conflict problem).