Dr. Brian Robert Callahan

academic, developer, with an eye towards a brighter techno-social life



[prev]
[next]

2023-07-05
Porting the Portable C Compiler (PCC) to Illumos

Hot off the heels of getting Oracle Developer Studio 12.6 running on Illumos, I am back with more Illumos compiler support. I got the Portable C Compiler running on my OpenIndiana machine.

It was pretty straightforward to do; below is the diff for the PCC compiler itself:

Index: configure
===================================================================
RCS file: /cvsroot/pcc/configure,v
retrieving revision 1.145
diff -u -p -r1.145 configure
--- configure	6 Dec 2022 15:03:01 -0000	1.145
+++ configure	5 Jul 2023 17:32:13 -0000
@@ -3128,6 +3128,7 @@ case "$target_os" in
         case "$target_cpu" in
             i?86) targmach=i386 ;;
             sparc*) targmach=sparc64 endian=big ;;
+            x86_64) targmach=amd64 ;;
         esac
         ;;
 
Index: configure.ac
===================================================================
RCS file: /cvsroot/pcc/configure.ac,v
retrieving revision 1.165
diff -u -p -r1.165 configure.ac
--- configure.ac	6 Dec 2022 15:03:01 -0000	1.165
+++ configure.ac	5 Jul 2023 17:32:13 -0000
@@ -268,6 +268,7 @@ case "$target_os" in
         case "$target_cpu" in
             i?86) targmach=i386 ;;
             sparc*) targmach=sparc64 endian=big ;;
+            x86_64) targmach=amd64 ;;
         esac
         ;;
 
Index: cc/cc/cc.c
===================================================================
RCS file: /cvsroot/pcc/cc/cc/cc.c,v
retrieving revision 1.328
diff -u -p -r1.328 cc.c
--- cc/cc/cc.c	15 Oct 2021 15:33:09 -0000	1.328
+++ cc/cc/cc.c	5 Jul 2023 17:32:14 -0000
@@ -2046,7 +2046,7 @@ setup_as_flags(void)
 }
 
 struct flgcheck ldflgcheck[] = {
-#ifndef MSLINKER
+#if !defined(MSLINKER) && !defined(os_sunos)
 	{ &vflag, 1, "-v" },
 #endif
 #ifdef os_darwin
Index: os/sunos/ccconfig.h
===================================================================
RCS file: /cvsroot/pcc/os/sunos/ccconfig.h,v
retrieving revision 1.7
diff -u -p -r1.7 ccconfig.h
--- os/sunos/ccconfig.h	24 Dec 2014 08:43:29 -0000	1.7
+++ os/sunos/ccconfig.h	5 Jul 2023 17:32:14 -0000
@@ -32,7 +32,11 @@
  */
 
 /* common cpp predefines */
+#ifdef __illumos__
+#define	CPPADD	{ "-Dunix", "-Dsun", "-D__SVR4", "-D__unix", "-D__sun", "-D__SunOS", "-D__illumos__", "-D__ELF__", NULL }
+#else
 #define	CPPADD	{ "-Dunix", "-Dsun", "-D__SVR4", "-D__unix", "-D__sun", "-D__SunOS", "-D__ELF__", NULL }
+#endif
 
 /* TODO: _ _SunOS_5_6, _ _SunOS_5_7, _ _SunOS_5_8, _ _SunOS_5_9, _ _SunOS_5_10 */
 
@@ -42,16 +46,38 @@
 #define CRTBEGIN	0
 #define CRTEND		0
 
+#ifdef __illumos__
+#define STARTLABEL	"_start"
+#endif
+
 #ifdef LANG_F77
 #define F77LIBLIST { "-L/usr/local/lib", "-lF77", "-lI77", "-lm", "-lc", NULL };
 #endif
 
 /* host-independent */
+#ifndef __illumos__
 #define	DYNLINKARG	"-Bdynamic"
 #define	DYNLINKLIB	"/usr/lib/ld.so"
+#endif
 
+/* TODO: Detect if you're using the Sun assembler instead of the GNU assembler.
+   The PCC_EARLY_AS_ARGS below assume the GNU assembler. PCC does generate
+   assembly that the Sun assembler understands, so this assumption is unfounded.
+   We also assume use of the Sun linker.  */
 #if defined(mach_i386)
 #define	CPPMDADD { "-D__i386__", "-D__i386", NULL, }
+#define PCC_EARLY_AS_ARGS strlist_append(&args, "--32");
+#define PCC_SETUP_LD_ARGS { strlist_append(&early_linker_flags, "-Qy"); \
+			strlist_append(&early_linker_flags, "-Y"); \
+			strlist_append(&early_linker_flags, "P,/usr/ccs/lib:/lib:/usr/lib"); }
+#elif defined(mach_amd64)
+#define	CPPMDADD { "-D__amd64__", "-D__amd64", "-D__x86_64__", "-D__x86_64", \
+		   "-D__LP64__", "-D_LP64", NULL, }
+#define PCC_EARLY_AS_ARGS strlist_append(&args, "--64");
+#define PCC_SETUP_LD_ARGS { strlist_append(&early_linker_flags, "-Qy"); \
+			strlist_append(&early_linker_flags, "-Y"); \
+			strlist_append(&early_linker_flags, "P,/usr/ccs/lib/amd64:/lib/amd64:/usr/lib/amd64"); }
+#define DEFLIBDIRS	{ "/usr/lib/amd64", 0 }
 /* Let's keep it here in case of Polaris. ;) */
 #elif defined(mach_powerpc)
 #define	CPPMDADD { "-D__ppc__", NULL, }

And then the diff for the pcc-libs:

Index: configure
===================================================================
RCS file: /cvsroot/pcc-libs/configure,v
retrieving revision 1.31
diff -u -p -r1.31 configure
--- configure	6 Dec 2022 15:00:26 -0000	1.31
+++ configure	5 Jul 2023 17:33:15 -0000
@@ -2216,6 +2216,7 @@ case "$target_os" in
 	case "$target_cpu" in
 	    i?86) targmach=i386 ;;
 	    sparc*) targmach=sparc64 endian=big ;;
+	    x86_64) targmach=amd64 ;;
 	esac
 	;;
 
Index: configure.ac
===================================================================
RCS file: /cvsroot/pcc-libs/configure.ac,v
retrieving revision 1.31
diff -u -p -r1.31 configure.ac
--- configure.ac	6 Dec 2022 15:00:27 -0000	1.31
+++ configure.ac	5 Jul 2023 17:33:15 -0000
@@ -126,6 +126,7 @@ case "$target_os" in
 	case "$target_cpu" in
 	    i?86) targmach=i386 ;;
 	    sparc*) targmach=sparc64 endian=big ;;
+	    x86_64) targmach=amd64 ;;
 	esac
 	;;
 

OK, porting is a bit of a stretch. I simply taught PCC how to live in an Illumos environment. Nevertheless, this might well be the first time PCC has ever run on an Illumos system.

PCC is a nice little C99 compiler. It is much faster than clang and GCC, though slower than TCC. With that said, PCC almost certainly generates better code than TCC, as PCC has a real optimizer. PCC certainly has a place in the pantheon of C compilers.

State of affairs

It looks like some time ago someone added configuration for 32-bit x86 and SPARC64 support for the Solaris family. But no one ever tried to support 64-bit x86. So first we had to teach the configure script for both pcc and pcc-libs that 64-bit x86 Solaris exists. The Illumos people have sunset 32-bit kernel support. But that only affects the kernel; you can still run 32-bit binaries and, if you really want to, create new 32-bit binaries. So in theory, PCC should support Illumos, it'll just create 32-bit binaries but that's fine those binaries should work.

Building 32-bit x86 PCC

I figured I would start with building a 32-bit x86 PCC in order to understand what might be needed for 64-bit x86 support.

Unfortunately, it wasn't that easy. First, you need to install the flex package, as the in-base lex utility cannot build the scan.l file that PCC uses to create its lexer. After that, it turns out that Developer Studio can't build PCC; it dies on code where a void function returns another void function. The workaround is simply to remove the return, which has been committed upstream.

Next, it is the case that PCC outputs assembly that the Sun assembler does not fully understand, so we need to install the GNU binutils package so that we can use the GNU assembler. We are not going to use the GNU linker; even the GCC package for OpenIndiana uses the Sun linker.

That's actually half-true: PCC generates 32-bit assembly that the Sun assembler understands but the 64-bit assembly PCC generates is not fully understood by the Sun assembler. Specifically, PCC emits a .end directive that the Sun assembler does not understand. That one is easy enough to simply remove. But PCC also emits .short directives and the Sun assembler does not understand that either. I am guessing that if .short was replaced with .word, that would work. But it might be the case that PCC supports platforms where .short and .word are not the same, and so I don't want to inadvertently break other configurations. I might well be the only person who as an Illumos machine with the Sun assembler on it, so we are going to assume that if you are running Illumos, you need the GNU assembler. Actually, we're going to assume that for all x86 Solaris family platforms. The GNU assembler is easy to come by on Solaris family machines; anyone who would use PCC probably already has GCC and the GNU assembler installed on their system.

Linking

At this point, I had a 32-bit PCC running on my OpenIndiana machine that could compile and assemble code, but it could not link the code. Trying to debug matters using the -v flag with PCC also failed: the Sun linker uses -V to show its version information whereas the GNU linker uses -v and this caused the Sun linker to refuse to link anything when running in verbose mode. This flag difference is also true of the Sun assembler. The fix for that is very easy: in the PCC driver cc/cc/cc.c, we can say if we're on a Solaris family machine, don't use the -v flag with the linker. We will lose out on the version information printing, but that is easy enough to get ourselves if we ever need it.

Next, it seems like whoever did the original Solaris family support I think assumed you would be using the GNU linker, as it uses flags that the Sun linker does not understand. We can just remove those flags. We also need to change the start label: PCC defaults to __start but Illumos uses _start as the start label.

We should also add some additional linker flags. First is -Qy which adds a comment in the binary identifying the linker. Both the LLVM linker and the GNU linker do this; I think the flag for those linkers is -fident. Then there is the -Y P, flag, which changes the default directories used for finding libraries. I saw both Developer Studio and GCC issuing both of these flags to the linker, so I think PCC should do the same.

Finally, for good measure, we should add __illumos__ to the list of preprocessor defines. GCC does this. Developer Studio does not, though I think that's because Developer Studio does not officially support Illumos.

64-bit support

All I needed to do to get 64-bit Illumos support is to tweak the linker flags to point to the library directories that contain the 64-bit libraries. Very easy.

And that's it. It was not terribly difficult to support Illumos. But it is good that it is done. Now more people can benefit from PCC. These patches are being committed. The 32-bit support had already been committed and I am sure the 64-bit support will be committed soon too.

A PCC package for Illumos

I wanted to make things easy for Illumos users to use PCC, so I read this page and created a package of PCC. This package is of the 64-bit PCC generating 64-bit binaries. In this package, I tweaked the linker flags to use the -V flag for the linker in verbose mode, so you will get linker version output in verbose mode.

You can download the package here. It uses the OpenIndiana package repository to resolve dependencies; I don't know if that's good or bad but that's what I did.

Conclusion

This was a fun little morning project to get PCC supported on Illumos. Now more people can use PCC, and Illumos users have a new C compiler to use on their machines.

Top

RSS