rubycc 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +56 -0
  3. data/LICENSE.txt +21 -0
  4. data/NOTICE +52 -0
  5. data/README.md +208 -0
  6. data/data/README.md +117 -0
  7. data/data/r10_corpus_scan.json +4082 -0
  8. data/data/r10_manual_classification.json +5342 -0
  9. data/data/r10_verification_m4a.json +1531 -0
  10. data/data/r10_verification_m4b.json +1818 -0
  11. data/data/r10_verification_m4c.json +1489 -0
  12. data/data/r10_verification_m4d.json +318 -0
  13. data/data/r10_verification_rbs.json +192 -0
  14. data/data/verified_gems.json +397 -0
  15. data/exe/rmake +16 -0
  16. data/exe/rubycc +9 -0
  17. data/exe/rubycc-ar +114 -0
  18. data/exe/rubycc-doctor +14 -0
  19. data/exe/rubycc-pkgconf +8 -0
  20. data/include/float.h +87 -0
  21. data/include/iso646.h +18 -0
  22. data/include/libc/alloca.h +18 -0
  23. data/include/libc/arpa/inet.h +61 -0
  24. data/include/libc/assert.h +43 -0
  25. data/include/libc/dirent.h +72 -0
  26. data/include/libc/dlfcn.h +58 -0
  27. data/include/libc/features.h +205 -0
  28. data/include/libc/glibc/aarch64/ctype.h +108 -0
  29. data/include/libc/glibc/aarch64/endian.h +54 -0
  30. data/include/libc/glibc/aarch64/errno.h +154 -0
  31. data/include/libc/glibc/aarch64/fcntl.h +144 -0
  32. data/include/libc/glibc/aarch64/inttypes.h +182 -0
  33. data/include/libc/glibc/aarch64/limits.h +63 -0
  34. data/include/libc/glibc/aarch64/pthread.h +131 -0
  35. data/include/libc/glibc/aarch64/setjmp.h +84 -0
  36. data/include/libc/glibc/aarch64/stdint.h +174 -0
  37. data/include/libc/glibc/aarch64/sys/epoll.h +88 -0
  38. data/include/libc/glibc/aarch64/sys/fcntl.h +19 -0
  39. data/include/libc/glibc/aarch64/sys/select.h +75 -0
  40. data/include/libc/glibc/aarch64/sys/stat.h +136 -0
  41. data/include/libc/glibc/aarch64/sys/syscall.h +167 -0
  42. data/include/libc/glibc/aarch64/sys/time.h +74 -0
  43. data/include/libc/glibc/aarch64/sys/types.h +127 -0
  44. data/include/libc/glibc/aarch64/time.h +113 -0
  45. data/include/libc/glibc/x86_64/ctype.h +108 -0
  46. data/include/libc/glibc/x86_64/endian.h +54 -0
  47. data/include/libc/glibc/x86_64/errno.h +154 -0
  48. data/include/libc/glibc/x86_64/fcntl.h +134 -0
  49. data/include/libc/glibc/x86_64/inttypes.h +182 -0
  50. data/include/libc/glibc/x86_64/limits.h +61 -0
  51. data/include/libc/glibc/x86_64/pthread.h +111 -0
  52. data/include/libc/glibc/x86_64/setjmp.h +82 -0
  53. data/include/libc/glibc/x86_64/stdint.h +163 -0
  54. data/include/libc/glibc/x86_64/sys/epoll.h +91 -0
  55. data/include/libc/glibc/x86_64/sys/fcntl.h +19 -0
  56. data/include/libc/glibc/x86_64/sys/select.h +75 -0
  57. data/include/libc/glibc/x86_64/sys/stat.h +130 -0
  58. data/include/libc/glibc/x86_64/sys/syscall.h +188 -0
  59. data/include/libc/glibc/x86_64/sys/time.h +74 -0
  60. data/include/libc/glibc/x86_64/sys/types.h +123 -0
  61. data/include/libc/glibc/x86_64/time.h +113 -0
  62. data/include/libc/grp.h +50 -0
  63. data/include/libc/langinfo.h +126 -0
  64. data/include/libc/link.h +18 -0
  65. data/include/libc/locale.h +83 -0
  66. data/include/libc/math.h +191 -0
  67. data/include/libc/netinet/in.h +126 -0
  68. data/include/libc/netinet/tcp.h +44 -0
  69. data/include/libc/poll.h +46 -0
  70. data/include/libc/pwd.h +58 -0
  71. data/include/libc/regex.h +53 -0
  72. data/include/libc/sched.h +35 -0
  73. data/include/libc/signal.h +204 -0
  74. data/include/libc/stdio.h +157 -0
  75. data/include/libc/stdlib.h +92 -0
  76. data/include/libc/string.h +74 -0
  77. data/include/libc/strings.h +25 -0
  78. data/include/libc/sys/cdefs.h +126 -0
  79. data/include/libc/sys/inotify.h +111 -0
  80. data/include/libc/sys/ioctl.h +36 -0
  81. data/include/libc/sys/mman.h +65 -0
  82. data/include/libc/sys/param.h +41 -0
  83. data/include/libc/sys/resource.h +109 -0
  84. data/include/libc/sys/socket.h +167 -0
  85. data/include/libc/sys/statfs.h +82 -0
  86. data/include/libc/sys/timerfd.h +55 -0
  87. data/include/libc/sys/uio.h +40 -0
  88. data/include/libc/sys/un.h +25 -0
  89. data/include/libc/sys/utsname.h +35 -0
  90. data/include/libc/sys/wait.h +135 -0
  91. data/include/libc/termios.h +179 -0
  92. data/include/libc/unistd.h +194 -0
  93. data/include/stdalign.h +16 -0
  94. data/include/stdarg.h +31 -0
  95. data/include/stdatomic.h +158 -0
  96. data/include/stdbool.h +15 -0
  97. data/include/stdckdint.h +28 -0
  98. data/include/stddef.h +60 -0
  99. data/include/stdnoreturn.h +18 -0
  100. data/include/x86intrin.h +16 -0
  101. data/lib/rubycc/backend/aarch64.rb +1724 -0
  102. data/lib/rubycc/backend/x86_64.rb +1369 -0
  103. data/lib/rubycc/compile_error.rb +36 -0
  104. data/lib/rubycc/compiler.rb +305 -0
  105. data/lib/rubycc/doctor/builder.rb +151 -0
  106. data/lib/rubycc/doctor/cli.rb +190 -0
  107. data/lib/rubycc/doctor/fetcher.rb +84 -0
  108. data/lib/rubycc/doctor/gemfile.rb +115 -0
  109. data/lib/rubycc/doctor/verified_gems.rb +114 -0
  110. data/lib/rubycc/doctor.rb +16 -0
  111. data/lib/rubycc/driver.rb +463 -0
  112. data/lib/rubycc/front/ast.rb +528 -0
  113. data/lib/rubycc/front/constant_evaluator.rb +631 -0
  114. data/lib/rubycc/front/initializer_resolver.rb +592 -0
  115. data/lib/rubycc/front/lexeme_reader.rb +460 -0
  116. data/lib/rubycc/front/lexer.rb +232 -0
  117. data/lib/rubycc/front/parser.rb +4122 -0
  118. data/lib/rubycc/front/token.rb +49 -0
  119. data/lib/rubycc/ir/call_convention.rb +486 -0
  120. data/lib/rubycc/ir/generator.rb +6036 -0
  121. data/lib/rubycc/ir/ir.rb +417 -0
  122. data/lib/rubycc/link/compat_runtime.rb +89 -0
  123. data/lib/rubycc/link/errors.rb +13 -0
  124. data/lib/rubycc/link/executable_linker.rb +405 -0
  125. data/lib/rubycc/link/library_resolver.rb +437 -0
  126. data/lib/rubycc/link/partial_linker.rb +546 -0
  127. data/lib/rubycc/link/shared_linker.rb +1732 -0
  128. data/lib/rubycc/mkmf_shim.rb +83 -0
  129. data/lib/rubycc/objfile/ar_archive.rb +437 -0
  130. data/lib/rubycc/objfile/elf_reader.rb +646 -0
  131. data/lib/rubycc/objfile/elf_writer.rb +891 -0
  132. data/lib/rubycc/objfile/relocatable_writer.rb +376 -0
  133. data/lib/rubycc/pkgconf/cli.rb +139 -0
  134. data/lib/rubycc/pkgconf/errors.rb +39 -0
  135. data/lib/rubycc/pkgconf/model.rb +28 -0
  136. data/lib/rubycc/pkgconf/parser.rb +109 -0
  137. data/lib/rubycc/pkgconf/pkgconf.rb +15 -0
  138. data/lib/rubycc/pkgconf/resolver.rb +70 -0
  139. data/lib/rubycc/pkgconf/search_path.rb +38 -0
  140. data/lib/rubycc/pkgconf/system_path_filter.rb +131 -0
  141. data/lib/rubycc/preprocess/constant_expression.rb +219 -0
  142. data/lib/rubycc/preprocess/glibc_version.rb +124 -0
  143. data/lib/rubycc/preprocess/pp_token.rb +62 -0
  144. data/lib/rubycc/preprocess/preprocessor.rb +2020 -0
  145. data/lib/rubycc/preprocess/scanner.rb +290 -0
  146. data/lib/rubycc/preprocess/token_converter.rb +157 -0
  147. data/lib/rubycc/rmake/cli.rb +143 -0
  148. data/lib/rubycc/rmake/errors.rb +71 -0
  149. data/lib/rubycc/rmake/executor.rb +818 -0
  150. data/lib/rubycc/rmake/expander.rb +251 -0
  151. data/lib/rubycc/rmake/makefile.rb +352 -0
  152. data/lib/rubycc/rmake/model.rb +137 -0
  153. data/lib/rubycc/rmake/parser.rb +226 -0
  154. data/lib/rubycc/rmake/rmake.rb +15 -0
  155. data/lib/rubycc/type.rb +1236 -0
  156. data/lib/rubycc/version.rb +5 -0
  157. data/lib/rubycc.rb +36 -0
  158. data/lib/rubygems_plugin.rb +102 -0
  159. metadata +219 -0
@@ -0,0 +1,40 @@
1
+ /* rubycc bundled <sys/uio.h>: scatter/gather I/O (POSIX.1). Provenance: clean
2
+ room against the POSIX public interface and the Linux kernel UAPI
3
+ (linux/uio.h); struct iovec's member names, types and order are that ABI's
4
+ own public contract, not glibc implementation detail. Reuses the
5
+ _RUBYCC_STRUCT_IOVEC guard sys/socket.h already defines the struct under, so
6
+ the two headers agree rather than redefine when both are included; its
7
+ 16-byte size and both members' offsets were measured against the glibc
8
+ oracle on both x86-64 and aarch64 (see sys/socket.h's SOCKET case and this
9
+ header's UIO case in test/test_header_abi.rb) and the two agreed exactly (a
10
+ pointer-and-size_t struct has no arch-dependent field widths on either LP64
11
+ target), so this header lives in the common layer. readv/writev are POSIX
12
+ declarations whose bodies resolve from the host libc at link time
13
+ (Step 123, M5 H2). */
14
+
15
+ #ifndef _RUBYCC_SYS_UIO_H
16
+ #define _RUBYCC_SYS_UIO_H
17
+
18
+ #ifndef _RUBYCC_SIZE_T
19
+ #define _RUBYCC_SIZE_T
20
+ typedef unsigned long size_t;
21
+ #endif
22
+ #ifndef _RUBYCC_SSIZE_T
23
+ #define _RUBYCC_SSIZE_T
24
+ typedef long ssize_t;
25
+ #endif
26
+
27
+ /* struct iovec: 16 bytes, 8-byte aligned (measured, both arches). Shared with
28
+ sys/socket.h under the same guard. */
29
+ #ifndef _RUBYCC_STRUCT_IOVEC
30
+ #define _RUBYCC_STRUCT_IOVEC
31
+ struct iovec {
32
+ void *iov_base; /* offset 0 */
33
+ size_t iov_len; /* offset 8 */
34
+ };
35
+ #endif
36
+
37
+ ssize_t readv(int __fd, const struct iovec *__iov, int __iovcnt);
38
+ ssize_t writev(int __fd, const struct iovec *__iov, int __iovcnt);
39
+
40
+ #endif /* _RUBYCC_SYS_UIO_H */
@@ -0,0 +1,25 @@
1
+ /* rubycc bundled <sys/un.h>: struct sockaddr_un, the AF_UNIX (local) socket
2
+ address. Provenance: clean room against the Linux kernel UAPI (linux/un.h)
3
+ and the glibc socket ABI, not derived from musl. The 110-byte layout
4
+ (sun_family then a 108-byte sun_path) is that ABI reproduced as a measured
5
+ field layout (an ABI fact, not copied text -- see docs/HEADER-LICENSING.md),
6
+ the same treatment as sys/socket.h. Common layer: the layout is identical on
7
+ x86-64 and aarch64. sa_family_t is shared with <sys/socket.h> and
8
+ <netinet/in.h> through the same guard, so including any combination never
9
+ redefines it. */
10
+
11
+ #ifndef _RUBYCC_SYS_UN_H
12
+ #define _RUBYCC_SYS_UN_H
13
+
14
+ #ifndef _RUBYCC_SA_FAMILY_T
15
+ #define _RUBYCC_SA_FAMILY_T
16
+ typedef unsigned short sa_family_t;
17
+ #endif
18
+
19
+ /* struct sockaddr_un: 110 bytes, 2-byte aligned (measured, both arches). */
20
+ struct sockaddr_un {
21
+ sa_family_t sun_family; /* offset 0 */
22
+ char sun_path[108]; /* offset 2 */
23
+ };
24
+
25
+ #endif /* _RUBYCC_SYS_UN_H */
@@ -0,0 +1,35 @@
1
+ /* rubycc bundled <sys/utsname.h>: system identification (POSIX.1 4.4).
2
+ Provenance: clean room against the Linux kernel ABI (struct new_utsname,
3
+ returned by the uname(2) syscall) and the POSIX public interface. Member
4
+ names, order and per-field length (65) are the ABI's own public contract --
5
+ the raw syscall fills exactly six 65-byte fields (sysname, nodename,
6
+ release, version, machine, domainname; the sixth is the NIS domain name the
7
+ kernel added alongside the original five POSIX fields) -- so reproducing
8
+ them is not a glibc derivation. Every member is used directly by callers, so
9
+ it cannot be an opaque byte blob; the struct's size (390) and every member's
10
+ offset were measured against the glibc oracle on both x86-64 and aarch64
11
+ (see test/test_header_abi.rb's UTSNAME case) and the two agreed exactly (a
12
+ plain char-array struct has no arch-dependent field widths), so this header
13
+ lives in the common layer. glibc gates the sixth field's name behind
14
+ __USE_GNU (plain `domainname' vs. `__domainname'); rubycc's bundled header
15
+ exposes the flat `domainname' spelling unconditionally, the same choice
16
+ sys/stat.h's unconditional st_atim makes. uname is a POSIX declaration whose
17
+ body resolves from the host libc at link time (Step 123, M5 H2). */
18
+
19
+ #ifndef _RUBYCC_SYS_UTSNAME_H
20
+ #define _RUBYCC_SYS_UTSNAME_H
21
+
22
+ #define _UTSNAME_LENGTH 65
23
+
24
+ struct utsname {
25
+ char sysname[_UTSNAME_LENGTH]; /* Operating system name. */
26
+ char nodename[_UTSNAME_LENGTH]; /* Name on the network. */
27
+ char release[_UTSNAME_LENGTH]; /* Release level. */
28
+ char version[_UTSNAME_LENGTH]; /* Version level. */
29
+ char machine[_UTSNAME_LENGTH]; /* Hardware type. */
30
+ char domainname[_UTSNAME_LENGTH]; /* NIS/YP domain name. */
31
+ };
32
+
33
+ int uname(struct utsname *__name);
34
+
35
+ #endif /* _RUBYCC_SYS_UTSNAME_H */
@@ -0,0 +1,135 @@
1
+ /* rubycc bundled <sys/wait.h>: waiting for process state changes (POSIX.1).
2
+ Provenance: clean room against the POSIX public interface and the Linux
3
+ kernel's wait-status encoding, not derived from musl or glibc source. Two
4
+ kinds of ABI fact are reproduced here, both measured rather than copied
5
+ (see docs/HEADER-LICENSING.md sec. 4):
6
+
7
+ (a) The option flags (WNOHANG/WUNTRACED/WCONTINUED and the waitid
8
+ WEXITED/WSTOPPED/WNOWAIT set, plus glibc's __WALL family) and the
9
+ idtype_t enumerators, printed from the glibc oracle on x86-64 and on
10
+ aarch64 (cross gcc + qemu); the two agreed on every value.
11
+
12
+ (b) The wait-status *encoding* behind WIFEXITED and kin. Rather than copy
13
+ glibc's macro bodies, rubycc re-derived the encoding from observed
14
+ behaviour and then proved the re-derivation exact: a probe compared
15
+ rubycc's formula against the host glibc macro for *every* one of the
16
+ 2^32 int status values, for all eight macros, on both x86-64 and
17
+ aarch64, and found zero mismatches (including the exact non-boolean
18
+ return of WCOREDUMP, which yields the 0x80 flag bit rather than 1).
19
+ The formulas below are therefore rubycc's own spelling of a measured
20
+ fact; they are also written to evaluate their argument exactly once,
21
+ which glibc's differently-shaped bodies also do. That exhaustive
22
+ comparison had a glibc oracle; on musl the harness measured a
23
+ difference in WIFSTOPPED alone, so that macro (and only that one) has a
24
+ musl branch below.
25
+
26
+ Common layer: every value and every macro result above is identical on
27
+ x86-64 and aarch64, so this header is arch-neutral (unlike sys/epoll.h,
28
+ whose struct packing differs between the two).
29
+
30
+ <signal.h> is included for siginfo_t, which waitid's third parameter needs:
31
+ glibc reaches for its own bits/types/siginfo_t.h here under
32
+ __USE_XOPEN_EXTENDED, and rubycc has no split types layer to reach for, so
33
+ it includes the whole bundled <signal.h> (the same way the bundled
34
+ <string.h> reaches for <strings.h> to reproduce glibc's __USE_MISC
35
+ pull-in). pid_t arrives with it.
36
+
37
+ Not included: wait3/wait4 (they take a `struct rusage *`, which would mean
38
+ either cross-including <sys/resource.h> or duplicating struct rusage under
39
+ a shared guard, and no corpus census hit needs them -- nio4r, the gem that
40
+ put this header on the list, reaches only waitpid and the status macros),
41
+ the obsolete `union wait` overloads, and WAIT_ANY/WAIT_MYPGRP. */
42
+
43
+ #ifndef _RUBYCC_SYS_WAIT_H
44
+ #define _RUBYCC_SYS_WAIT_H
45
+
46
+ #include <signal.h>
47
+
48
+ #ifndef _RUBYCC_ID_T
49
+ #define _RUBYCC_ID_T
50
+ typedef unsigned int id_t;
51
+ #endif
52
+
53
+ /* waitpid / waitid options (measured, both arches). */
54
+ #if defined(WNOHANG) && WNOHANG != 1
55
+ /* ruby.h's ruby/missing.h supplies a zero fallback before this header. That
56
+ fallback is only for platforms without waitpid; on Linux this measured ABI
57
+ value must replace it rather than trigger a conflicting redefinition. */
58
+ #undef WNOHANG
59
+ #endif
60
+ #define WNOHANG 1
61
+ #define WUNTRACED 2
62
+ #define WSTOPPED 2
63
+ #define WEXITED 4
64
+ #define WCONTINUED 8
65
+ #define WNOWAIT 0x01000000
66
+
67
+ /* glibc's Linux-specific selectors for which children to wait on. */
68
+ #define __WNOTHREAD 0x20000000
69
+ #define __WALL 0x40000000
70
+ #define __WCLONE 0x80000000
71
+
72
+ /* The wait-status encoding (Linux kernel ABI), re-derived from measurement:
73
+ bits 0..6 terminating signal; 0 means "exited normally" and the
74
+ reserved value 0x7f means "stopped"
75
+ bit 7 core-dump flag
76
+ bits 8..15 exit code, or the stopping signal when bits 0..7 are 0x7f
77
+ 0xffff the whole word, meaning "continued"
78
+ Each macro evaluates its argument once, WIFSTOPPED's musl branch excepted
79
+ (see its own note). WIFSIGNALED's unsigned compare is
80
+ the single-evaluation way to say "the signal field is neither 0 nor the
81
+ 0x7f stopped marker": subtracting one wraps the 0 case past the range. */
82
+ #define WTERMSIG(status) ((status) & 0x7f)
83
+ #define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
84
+ #define WSTOPSIG(status) (((status) & 0xff00) >> 8)
85
+ #define WIFEXITED(status) (((status) & 0x7f) == 0)
86
+ #define WIFSIGNALED(status) ((unsigned)(((status) & 0x7f) - 1) < 0x7eu)
87
+ /* WIFSTOPPED is the one status macro the two C libraries answer differently:
88
+ musl also requires the stopping-signal byte to be non-zero, so the bare
89
+ 0x007f word is not "stopped" there. Measured on the four status words the
90
+ ABI harness probes (docs/STEPS.md Step 193; glibc's side on this host):
91
+ status glibc musl
92
+ 0x0000 0 0
93
+ 0x007f 1 0
94
+ 0x137f 1 1
95
+ 0xffff 0 0
96
+ The musl form below is the narrowest formula that reproduces all four; no
97
+ other status word was measured on musl, so nothing stronger is claimed.
98
+ Unlike every other macro here it names its argument twice -- there is no
99
+ single-evaluation spelling of "low byte is 0x7f and high byte is not zero"
100
+ that does not go through a helper -- so an argument with a side effect is
101
+ evaluated twice under musl. */
102
+ #if defined(__RUBYCC_LIBC_MUSL__)
103
+ #define WIFSTOPPED(status) (((status) & 0xff) == 0x7f && ((status) & 0xff00) != 0)
104
+ #else
105
+ #define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
106
+ #endif
107
+ #define WIFCONTINUED(status) ((status) == 0xffff)
108
+ #define WCOREDUMP(status) ((status) & 0x80)
109
+
110
+ /* waitid's id interpretation. Measured: a 4-byte, 4-byte-aligned enum whose
111
+ enumerators run 0, 1, 2 (and 3 for the recent P_PIDFD addition). */
112
+ typedef enum {
113
+ P_ALL = 0,
114
+ P_PID = 1,
115
+ P_PGID = 2,
116
+ P_PIDFD = 3
117
+ } idtype_t;
118
+
119
+ /* siginfo_t::si_code values for SIGCHLD, which is how waitid reports what
120
+ happened (measured, both arches). glibc keeps these in the same
121
+ bits/siginfo-consts.h that both <signal.h> and <sys/wait.h> reach for; the
122
+ bundled <signal.h> does not define them, so they live here, next to the one
123
+ call that needs them. */
124
+ #define CLD_EXITED 1
125
+ #define CLD_KILLED 2
126
+ #define CLD_DUMPED 3
127
+ #define CLD_TRAPPED 4
128
+ #define CLD_STOPPED 5
129
+ #define CLD_CONTINUED 6
130
+
131
+ pid_t wait(int *__status);
132
+ pid_t waitpid(pid_t __pid, int *__status, int __options);
133
+ int waitid(idtype_t __idtype, id_t __id, siginfo_t *__infop, int __options);
134
+
135
+ #endif /* _RUBYCC_SYS_WAIT_H */
@@ -0,0 +1,179 @@
1
+ /* rubycc bundled <termios.h>: general terminal interface (POSIX.1).
2
+ Provenance: clean room against the POSIX public interface and the glibc/
3
+ Linux ABI (bits/termios.h, the generic layout every mainline Linux arch
4
+ except a handful of legacy ports -- alpha/mips/powerpc/sparc -- shares;
5
+ x86-64 and aarch64 both use it). struct termios's member names, order and
6
+ the `c_cc` array holding NCCS control characters are that ABI's own public
7
+ contract, not glibc implementation detail (the same treatment sys/
8
+ resource.h gives struct rlimit/struct rusage). Every member (including
9
+ c_cc's individual slots, indexed by the V* constants) is read/written
10
+ directly by callers, so the struct cannot be an opaque byte blob; its size
11
+ (60), NCCS (32) and every member's offset were measured against the glibc
12
+ oracle on both x86-64 and aarch64 (see test/test_header_abi.rb's TERMIOS
13
+ case) and the two agreed exactly (tcflag_t/speed_t are `unsigned int` and
14
+ cc_t is `unsigned char` on either LP64 target, so no member has an
15
+ arch-dependent width), so this header lives in the common layer. speed_t/
16
+ tcflag_t/cc_t and every c_iflag/c_oflag/c_cflag/c_lflag bit and V* index
17
+ are the standard Linux/glibc values (measured, both arches agree).
18
+ Narrowed to the surface io-console's corpus sample actually reaches
19
+ (Step 124, M5 H2): the termios-path (HAVE_TERMIOS_H) getattr/setattr pair
20
+ built from tcgetattr/tcsetattr/TCSANOW, tcflush plus its TC*FLUSH queue
21
+ selectors, and the c_iflag/c_oflag/c_cflag/c_lflag bits and VMIN/VTIME/
22
+ VINTR/.../XCASE indices it flips to build raw mode. cfgetispeed/
23
+ cfsetispeed/cfgetospeed/cfsetospeed/tcdrain/tcsendbreak are declared as
24
+ the POSIX-mandated companions of tcgetattr/tcsetattr even though no corpus
25
+ sample calls them, the same completeness precedent pwd.h/grp.h set for
26
+ their reentrant *_r siblings. Not included: tcflow/tcgetsid/cfsetspeed and
27
+ the termio.h/sgtty.h fallback paths (BSD/pre-POSIX ioctl-based terminal
28
+ control that HAVE_TERMIOS_H skips on Linux), and the NLDLY/CRDLY/TABDLY/
29
+ BSDLY/VTDLY/FFDLY output-delay bits (line-printer timing, not used to
30
+ build raw mode). cfmakeraw was missing from that Step 124 pass: the corpus
31
+ census that drove it only looks at which headers a #include reaches, not
32
+ which functions the reached header's caller actually calls, so a function
33
+ io-console calls without pulling in any new header slipped past it.
34
+ Building io-console for real (Step 167) surfaced the gap -- mkmf's
35
+ have_func probe for it passed regardless (it declares the function itself
36
+ before linking), so -DHAVE_CFMAKERAW was set and the implicit-declaration
37
+ error only showed up compiling the body -- and cfmakeraw was added then. */
38
+
39
+ #ifndef _RUBYCC_TERMIOS_H
40
+ #define _RUBYCC_TERMIOS_H
41
+
42
+ typedef unsigned char cc_t;
43
+ typedef unsigned int speed_t;
44
+ typedef unsigned int tcflag_t;
45
+
46
+ /* Size of c_cc (measured, both arches). */
47
+ #define NCCS 32
48
+
49
+ /* struct termios: 60 bytes, 4-byte aligned (measured, both arches). */
50
+ struct termios {
51
+ tcflag_t c_iflag; /* offset 0: input mode flags */
52
+ tcflag_t c_oflag; /* offset 4: output mode flags */
53
+ tcflag_t c_cflag; /* offset 8: control mode flags */
54
+ tcflag_t c_lflag; /* offset 12: local mode flags */
55
+ cc_t c_line; /* offset 16: line discipline */
56
+ cc_t c_cc[NCCS]; /* offset 17: control characters */
57
+ speed_t c_ispeed; /* offset 52: input speed */
58
+ speed_t c_ospeed; /* offset 56: output speed */
59
+ };
60
+
61
+ /* c_cc subscripts (measured, both arches agree). */
62
+ #define VINTR 0
63
+ #define VQUIT 1
64
+ #define VERASE 2
65
+ #define VKILL 3
66
+ #define VEOF 4
67
+ #define VTIME 5
68
+ #define VMIN 6
69
+ #define VSWTC 7
70
+ #define VSTART 8
71
+ #define VSTOP 9
72
+ #define VSUSP 10
73
+ #define VEOL 11
74
+ #define VREPRINT 12
75
+ #define VDISCARD 13
76
+ #define VWERASE 14
77
+ #define VLNEXT 15
78
+ #define VEOL2 16
79
+
80
+ /* c_iflag bits. */
81
+ #define IGNBRK 0000001
82
+ #define BRKINT 0000002
83
+ #define IGNPAR 0000004
84
+ #define PARMRK 0000010
85
+ #define INPCK 0000020
86
+ #define ISTRIP 0000040
87
+ #define INLCR 0000100
88
+ #define IGNCR 0000200
89
+ #define ICRNL 0000400
90
+ #define IXON 0002000
91
+ #define IXANY 0004000
92
+ #define IXOFF 0010000
93
+ #define IMAXBEL 0020000
94
+ #define IUTF8 0040000
95
+
96
+ /* c_oflag bits. */
97
+ #define OPOST 0000001
98
+ #define ONLCR 0000004
99
+ #define OCRNL 0000010
100
+ #define ONOCR 0000020
101
+ #define ONLRET 0000040
102
+ #define OFILL 0000100
103
+ #define OFDEL 0000200
104
+
105
+ /* c_cflag bits. */
106
+ #define CSIZE 0000060
107
+ #define CS5 0000000
108
+ #define CS6 0000020
109
+ #define CS7 0000040
110
+ #define CS8 0000060
111
+ #define CSTOPB 0000100
112
+ #define CREAD 0000200
113
+ #define PARENB 0000400
114
+ #define PARODD 0001000
115
+ #define HUPCL 0002000
116
+ #define CLOCAL 0004000
117
+
118
+ /* c_lflag bits. */
119
+ #define ISIG 0000001
120
+ #define ICANON 0000002
121
+ #define ECHO 0000010
122
+ #define ECHOE 0000020
123
+ #define ECHOK 0000040
124
+ #define ECHONL 0000100
125
+ #define NOFLSH 0000200
126
+ #define TOSTOP 0000400
127
+ #define IEXTEN 0100000
128
+ /* Linux extension (glibc gates this behind __USE_MISC; rubycc exposes it
129
+ unconditionally, the same flat-surface choice sys/resource.h made for
130
+ RUSAGE_THREAD). */
131
+ #define XCASE 0000004
132
+
133
+ /* Baud rate selectors, for cfsetispeed/cfsetospeed (the traditional POSIX
134
+ set; the GNU-extension rates above B38400, e.g. B57600/B115200, are not
135
+ included -- no corpus sample needs them). */
136
+ #define B0 0000000
137
+ #define B50 0000001
138
+ #define B75 0000002
139
+ #define B110 0000003
140
+ #define B134 0000004
141
+ #define B150 0000005
142
+ #define B200 0000006
143
+ #define B300 0000007
144
+ #define B600 0000010
145
+ #define B1200 0000011
146
+ #define B1800 0000012
147
+ #define B2400 0000013
148
+ #define B4800 0000014
149
+ #define B9600 0000015
150
+ #define B19200 0000016
151
+ #define B38400 0000017
152
+
153
+ /* tcsetattr's __optional_actions. */
154
+ #define TCSANOW 0
155
+ #define TCSADRAIN 1
156
+ #define TCSAFLUSH 2
157
+
158
+ /* tcflush's __queue_selector. */
159
+ #define TCIFLUSH 0
160
+ #define TCOFLUSH 1
161
+ #define TCIOFLUSH 2
162
+
163
+ int tcgetattr(int __fd, struct termios *__termios_p);
164
+ int tcsetattr(int __fd, int __optional_actions, const struct termios *__termios_p);
165
+ int tcflush(int __fd, int __queue_selector);
166
+ int tcdrain(int __fd);
167
+ int tcsendbreak(int __fd, int __duration);
168
+ speed_t cfgetispeed(const struct termios *__termios_p);
169
+ speed_t cfgetospeed(const struct termios *__termios_p);
170
+ int cfsetispeed(struct termios *__termios_p, speed_t __speed);
171
+ int cfsetospeed(struct termios *__termios_p, speed_t __speed);
172
+
173
+ /* cfmakeraw is a BSD/GNU extension, not POSIX (POSIX only standardizes the
174
+ getattr/setattr/cfset*speed calls above); glibc and the BSDs all provide it
175
+ as the conventional shortcut that sets the termios flags/c_cc for raw mode
176
+ in one call, which is exactly what io-console uses it for. */
177
+ void cfmakeraw(struct termios *__termios_p);
178
+
179
+ #endif /* _RUBYCC_TERMIOS_H */
@@ -0,0 +1,194 @@
1
+ /* rubycc bundled <unistd.h>: the POSIX system-call declarations (POSIX.1).
2
+ Derived from musl's <unistd.h> declaration set; the few ABI-typed names
3
+ (ssize_t, off_t, pid_t, ...) reuse the shared _RUBYCC_* guards and carry the
4
+ LP64 widths. The STDIN_FILENO / *_OK values are the standard ones. Common
5
+ layer: the surface is declarations plus universal constants. */
6
+
7
+ #ifndef _RUBYCC_UNISTD_H
8
+ #define _RUBYCC_UNISTD_H
9
+
10
+ #ifndef NULL
11
+ #define NULL ((void*)0)
12
+ #endif
13
+
14
+ #ifndef _RUBYCC_SIZE_T
15
+ #define _RUBYCC_SIZE_T
16
+ typedef unsigned long size_t;
17
+ #endif
18
+ #ifndef _RUBYCC_SSIZE_T
19
+ #define _RUBYCC_SSIZE_T
20
+ typedef long ssize_t;
21
+ #endif
22
+ #ifndef _RUBYCC_OFF_T
23
+ #define _RUBYCC_OFF_T
24
+ typedef long off_t;
25
+ #endif
26
+ #ifndef _RUBYCC_PID_T
27
+ #define _RUBYCC_PID_T
28
+ typedef int pid_t;
29
+ #endif
30
+ #ifndef _RUBYCC_UID_T
31
+ #define _RUBYCC_UID_T
32
+ typedef unsigned int uid_t;
33
+ #endif
34
+ #ifndef _RUBYCC_GID_T
35
+ #define _RUBYCC_GID_T
36
+ typedef unsigned int gid_t;
37
+ #endif
38
+ #ifndef _RUBYCC_USECONDS_T
39
+ #define _RUBYCC_USECONDS_T
40
+ typedef unsigned int useconds_t;
41
+ #endif
42
+ #ifndef _RUBYCC_INTPTR_T
43
+ #define _RUBYCC_INTPTR_T
44
+ typedef long intptr_t;
45
+ #endif
46
+
47
+ #define STDIN_FILENO 0
48
+ #define STDOUT_FILENO 1
49
+ #define STDERR_FILENO 2
50
+
51
+ #define F_OK 0
52
+ #define X_OK 1
53
+ #define W_OK 2
54
+ #define R_OK 4
55
+
56
+ /* POSIX option macro: the monotonic clock option is supported, and the two C
57
+ libraries say so with different strengths. glibc's value is 0, meaning
58
+ support must still be confirmed at runtime via
59
+ sysconf(_SC_MONOTONIC_CLOCK); musl's is 200809, the standard revision it
60
+ supports unconditionally. Both measured with the ABI harness, glibc's on
61
+ this host and musl's on the CI musl run (docs/STEPS.md Step 193). Needed for
62
+ stackprof: it branches on `#ifdef _POSIX_MONOTONIC_CLOCK`, and the #else arm
63
+ it would otherwise take is upstream dead code containing a real syntax
64
+ error, so a toolchain that never defines this macro cannot build stackprof
65
+ at all -- and both values above define it. Scope: only this one _POSIX_*
66
+ macro is added here, not the full POSIX options set (same scoping judgment
67
+ as sys/syscall.h's non-exhaustive number list). */
68
+ #if defined(__RUBYCC_LIBC_MUSL__)
69
+ #define _POSIX_MONOTONIC_CLOCK 200809
70
+ #else
71
+ #define _POSIX_MONOTONIC_CLOCK 0
72
+ #endif
73
+ #define _POSIX_TIMERS 200809L
74
+
75
+ #ifndef SEEK_SET
76
+ #define SEEK_SET 0
77
+ #define SEEK_CUR 1
78
+ #define SEEK_END 2
79
+ #endif
80
+
81
+ int access(const char *__name, int __type);
82
+ int close(int __fd);
83
+ ssize_t read(int __fd, void *__buf, size_t __nbytes);
84
+ ssize_t write(int __fd, const void *__buf, size_t __n);
85
+ /* Positioned I/O at __offset, without moving the file's own offset. */
86
+ ssize_t pread(int __fd, void *__buf, size_t __nbytes, off_t __offset);
87
+ ssize_t pwrite(int __fd, const void *__buf, size_t __n, off_t __offset);
88
+ off_t lseek(int __fd, off_t __offset, int __whence);
89
+ int pipe(int __pipedes[2]);
90
+ int dup(int __fd);
91
+ int dup2(int __fd, int __fd2);
92
+ int unlink(const char *__name);
93
+ int rmdir(const char *__path);
94
+ int chdir(const char *__path);
95
+ char *getcwd(char *__buf, size_t __size);
96
+ int fsync(int __fd);
97
+ /* Linux exposes fdatasync() from <unistd.h>; bootsnap probes it and then calls
98
+ it when flushing its cache. Keep the declaration in the bundled surface so
99
+ the probe and the extension compile against the same measured ABI. */
100
+ int fdatasync(int __fd);
101
+ int ftruncate(int __fd, off_t __length);
102
+ int truncate(const char *__file, off_t __length);
103
+ int isatty(int __fd);
104
+ char *ttyname(int __fd);
105
+ /* ttyname's POSIX reentrant pair: the caller supplies the buffer instead of
106
+ getting back a pointer into static storage. */
107
+ int ttyname_r(int __fd, char *__buf, size_t __buflen);
108
+ int link(const char *__from, const char *__to);
109
+ int symlink(const char *__from, const char *__to);
110
+ ssize_t readlink(const char *__restrict __path, char *__restrict __buf, size_t __len);
111
+ int chown(const char *__file, uid_t __owner, gid_t __group);
112
+ int fchown(int __fd, uid_t __owner, gid_t __group);
113
+ int gethostname(char *__name, size_t __len);
114
+ int getpagesize(void);
115
+
116
+ pid_t fork(void);
117
+ pid_t getpid(void);
118
+ pid_t getppid(void);
119
+ /* GNU's raw system-call escape hatch; libev's io_uring backend uses it when
120
+ the libc wrapper is not available. */
121
+ long syscall(long __number, ...);
122
+ uid_t getuid(void);
123
+ uid_t geteuid(void);
124
+ gid_t getgid(void);
125
+ gid_t getegid(void);
126
+ int setuid(uid_t __uid);
127
+ int setgid(gid_t __gid);
128
+
129
+ unsigned int alarm(unsigned int __seconds);
130
+ unsigned int sleep(unsigned int __seconds);
131
+ int usleep(useconds_t __useconds);
132
+ int pause(void);
133
+
134
+ int execv(const char *__path, char *const __argv[]);
135
+ int execvp(const char *__file, char *const __argv[]);
136
+ int execve(const char *__path, char *const __argv[], char *const __envp[]);
137
+ int execl(const char *__path, const char *__arg, ...);
138
+ int execlp(const char *__file, const char *__arg, ...);
139
+ /* sysconf() is answered by the host's runtime libc, so its __name argument
140
+ must match the host's own numbering (glibc's <bits/confname.h> enum), not
141
+ a value rubycc invents. _SC_PAGE_SIZE is just an alias of _SC_PAGESIZE. */
142
+ #define _SC_ARG_MAX 0
143
+ #define _SC_CHILD_MAX 1
144
+ #define _SC_CLK_TCK 2
145
+ #define _SC_NGROUPS_MAX 3
146
+ #define _SC_OPEN_MAX 4
147
+ #define _SC_PAGESIZE 30
148
+ #define _SC_PAGE_SIZE _SC_PAGESIZE
149
+ /* _SC_IOV_MAX answers how many struct iovec a single writev may carry; kgio's
150
+ writev.c asks for it once and caches the answer to size its own batches. */
151
+ #define _SC_IOV_MAX 60
152
+ #define _SC_NPROCESSORS_CONF 83
153
+ #define _SC_NPROCESSORS_ONLN 84
154
+ #define _SC_PHYS_PAGES 85
155
+ #define _SC_AVPHYS_PAGES 86
156
+ long sysconf(int __name);
157
+
158
+ /* confstr()/fpathconf()/pathconf() are likewise answered by the host's
159
+ runtime libc, so their __name arguments must match the host's own
160
+ <bits/confname.h> numbering, the same reasoning _SC_ rests on above
161
+ (measured with gcc on the reference platform; x86-64 and aarch64 agree to
162
+ the value, checked with a cross gcc + qemu run). Step 157 gap D: etc's
163
+ ext/etc/mkconstants.rb conditionally exposes about 50 _CS_ and _PC_ names
164
+ in total, and all of them exist on the host glibc, but the corpus has
165
+ exactly one consumer (etc) and its own test suite exercises only
166
+ Etc::CS_PATH and Etc::PC_PIPE_BUF (guarded by "if defined?", so the rest
167
+ silently vanishing costs coverage, not a failure). Following the same
168
+ non-exhaustive judgment as sys/syscall.h's number list and
169
+ _POSIX_MONOTONIC_CLOCK above, only those two are added -- the POSIX_V6/V7
170
+ build-environment names (CFLAGS/LDFLAGS/LIBS variants),
171
+ CS_GNU_LIBC_VERSION, CS_GNU_LIBPTHREAD_VERSION, and the rest of the SUSv4
172
+ _PC_ set have no consumer in the corpus and would just be an unconsumed
173
+ measurement surface to re-check every release. */
174
+ #define _CS_PATH 0
175
+ #define _PC_PIPE_BUF 5
176
+ size_t confstr(int __name, char *__buf, size_t __len);
177
+ long fpathconf(int __fd, int __name);
178
+ /* pathconf() has no direct corpus consumer either (etc's io_pathconf() only
179
+ ever calls fpathconf()), but it is fpathconf()'s standard POSIX pair over
180
+ the same _PC_* names, its prototype carries no per-name numeric surface of
181
+ its own to re-measure, and this header's declaration layer is the general
182
+ POSIX surface (like execl/alarm/pause above) rather than a per-consumer
183
+ scoped one -- so it is kept alongside fpathconf() rather than left out. */
184
+ long pathconf(const char *__path, int __name);
185
+ void _exit(int __status) __attribute__((__noreturn__));
186
+ void *sbrk(intptr_t __delta);
187
+ int brk(void *__addr);
188
+
189
+ /* getopt and its globals. */
190
+ extern char *optarg;
191
+ extern int optind, opterr, optopt;
192
+ int getopt(int __argc, char *const __argv[], const char *__optstring);
193
+
194
+ #endif /* _RUBYCC_UNISTD_H */
@@ -0,0 +1,16 @@
1
+ /* rubycc freestanding <stdalign.h>: alignment macros (ISO C 7.15).
2
+ alignas and alignof map onto rubycc's _Alignas specifier and _Alignof
3
+ operator, both of which the compiler implements. */
4
+
5
+ #ifndef _RUBYCC_STDALIGN_H
6
+ #define _RUBYCC_STDALIGN_H
7
+
8
+ #ifndef __cplusplus
9
+ #define alignas _Alignas
10
+ #define alignof _Alignof
11
+ #endif
12
+
13
+ #define __alignas_is_defined 1
14
+ #define __alignof_is_defined 1
15
+
16
+ #endif
data/include/stdarg.h ADDED
@@ -0,0 +1,31 @@
1
+ /* rubycc freestanding <stdarg.h>: variable arguments (ISO C 7.16).
2
+ Maps onto rubycc's __builtin_va_* intrinsics and __builtin_va_list. */
3
+
4
+ /* __gnuc_va_list is provided for the glibc partial-include protocol
5
+ (stdio.h/wchar.h "#define __need___va_list" then include this). */
6
+ #if !defined _RUBYCC_GNUC_VA_LIST
7
+ #define _RUBYCC_GNUC_VA_LIST
8
+ typedef __builtin_va_list __gnuc_va_list;
9
+ #endif
10
+ #undef __need___va_list
11
+
12
+ /* __isoc_va_list is musl's name for the same type, where glibc writes
13
+ __gnuc_va_list. Both are provided unconditionally rather than per libc: they
14
+ are aliases of one type, so offering both costs nothing and lets a source
15
+ written against either libc's internal spelling compile. Repeating a typedef
16
+ with the same type is legal (C11 6.7p3), so a host header that defines its
17
+ own afterwards is not a conflict. Measured on musl in CI, where a probe
18
+ spelling it __isoc_va_list did not compile (docs/STEPS.md Step 190). */
19
+ #if !defined _RUBYCC_ISOC_VA_LIST
20
+ #define _RUBYCC_ISOC_VA_LIST
21
+ typedef __builtin_va_list __isoc_va_list;
22
+ #endif
23
+
24
+ #ifndef _RUBYCC_STDARG_H
25
+ #define _RUBYCC_STDARG_H
26
+ typedef __builtin_va_list va_list;
27
+ #define va_start(ap, last) __builtin_va_start(ap, last)
28
+ #define va_arg(ap, type) __builtin_va_arg(ap, type)
29
+ #define va_end(ap) __builtin_va_end(ap)
30
+ #define va_copy(d, s) __builtin_va_copy(d, s)
31
+ #endif