-
Notifications
You must be signed in to change notification settings - Fork 3
/
FAQ
115 lines (84 loc) · 4.32 KB
/
FAQ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
***** OK, why write another toy C compiler?
It's better than getting drunk in a bar.
***** Why doesn't signal() work on some systems?
The signal(2) system call exists only on rather ancient Unix
systems. Modern systems implement it in libc as a thin wrapper
around the sigaction(2) system call. This is what SubC's libc
also attempts to do.
However, in the latest iteration of Unix, the sigaction(2)
system call itself seems to be a wrapper around something
even more complex. Basically a lot of the signal handling
functionality is implemented in libc on those systems, and
installing signal handlers with sigaction(2) in the usual
way results in core dumps when invoking a signal handler.
This is because "signal trampolines" have moved from kernel
space to user space and installing the proper trampoline is
now done on a per-signal basis by some code in libc. See, for
example, the sigtramp(9) man page on NetBSD for all the gory
details.
Unfortunately, K&R II specifies signal() as a standard function,
so I am doing my best to implement it for all supported systems.
It seems to work fine on most 32-bit Unixes and seems to crash
on most 64-bit ones, except for FreeBSD (10.1-RELEASE).
Note that SIG_DFL and SIG_IGN do work, even on newer systems,
only signal handlers crash when invoked.
One work-around is to use the signal wrapper in the system's
C library, which may cause other problems, though. It also
causes a massive increase in executable size.
A better, albeit more complicated, work-around would be to
implement signal() properly. See the implementation by Minux in
the NetBSD ports for a starting point.
***** What if the triple test fails?
It depends. When the test script reports that the triple test
failed, it failed, and you cannot assume that you have a
working compiler. In this case, *please* send a bug report to
me and include the _stagedump.tar file that the test script
generated.
The test may also pass at assembly level, but then fail at
binary level, i.e. stages 2 and 3 generate identical assembly
programs, but the binaries differ nevertheless. Even in this
case, please send me the file generated by the script!
When the compiler passes at assembly level, you can assume that
it works fine and the cause of failure is beyond its scope. The
most probably cause is that the executables on your system
contain a timestamp or some other kind of build id.
However, I have also seen stage 2/3 binaries that differed at
thousands of locations, while assembly output still matched,
which is weird. So especially if you get stage 2/3 binaries
that are completely different (not only in a few bytes), please
do send me the test script output!
***** What about code quality?
Code quality has improved a lot since the 2012 book version:
Book 5/2014
scc -t *.c 0.53s 0.48s (9% faster)
text size 66,576 52,672 (21% smaller)
Run times were obtained by syntax-testing and compiling the book
version on a 386-class machine. The 2014 compiler is 9% faster,
although it uses an optimizer, and generates 21% smaller code.
SubC generates compact, but not very runtime-efficient code. In
general, its code reaches about 67% of the speed of code emitted
by GCC or Clang at optimization level 0.
The compiler executables generated by SubC are tyically <33% the
size of those generated by GCC or Clang, though. This is mostly
because SubC does not use a bloated libc implementation.
Here are some concrete numbers. Run times were obtained by
bootstrapping the SubC compiler multiple times and taking the
best results. All sizes refer to statically linked executables.
The boot stage 0 time is the time taken by the GCC-compiled
or Clang-compiled SubC compilers, while the boot stage 1 time
is the time taken by a self-compiled SubC compiler.
FreeBSD 8.2-RELEASE, 686 CPU @ 600 MHz
GCC 4.2.1 SUBC 2014-05-25
boot stage 0 2.40s 0.80s
boot stage 1 1.35s (40% slower)
text size 229,965 71,764 (75% smaller)
FreeBSD 10.0-RC5, armv6 CPU @ 700 MHz
Clang 3.3 SUBC 2014-05-25
boot stage 0 14.22s 4.68s
boot stage 1 6.14s (24% slower)
text size 450,411 143,508 (69% smaller)
FreeBSD 10.0-RELEASE, x86-64 CPU @ 875 MHz
Clang 3.3 SUBC 2014-05-25
boot stage 0 1.26s 0.67s
boot stage 1 1.03s (35% slower)
text size 478,370 93,510 (80% smaller)