Avoid -fwhole-program on broken gcc instead of stopping build.
authorKevin O'Connor <kevin@koconnor.net>
Tue, 16 Jun 2009 02:27:01 +0000 (22:27 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Tue, 16 Jun 2009 02:27:01 +0000 (22:27 -0400)
Enhance build to detect and avoid gcc with broken -fwhole-program
Also, remove workaround for older gcc that mess up global exports.

Makefile
README
src/boot.c
src/post.c
src/resume.c
tools/test-gcc.sh

index 8cb6625995d540b746fc893048a1d3bf11c4e9f2..c22a6c2cc66689917e9cefdd9692d163148a67ae 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,10 +22,9 @@ cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
 # Default compiler flags
 COMMONCFLAGS = -Wall -Os -MD -m32 -march=i386 -mregparm=3 \
                -mpreferred-stack-boundary=2 -mrtd -freg-struct-return \
-               $(call cc-option,$(CC),-fwhole-program -DWHOLE_PROGRAM,) \
                -ffreestanding -fomit-frame-pointer \
                -fno-delete-null-pointer-checks -Wno-strict-aliasing \
-               -ffunction-sections -fdata-sections \
+               -ffunction-sections -fdata-sections -fno-common \
                -minline-all-stringops
 COMMONCFLAGS += $(call cc-option,$(CC),-nopie,)
 COMMONCFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
@@ -59,28 +58,36 @@ vpath %.S src vgasrc
 
 ################ Build rules
 
+# Verify the gcc configuration and test if -fwhole-program works.
 TESTGCC:=$(shell CC=$(CC) tools/test-gcc.sh)
 ifeq "$(TESTGCC)" "-1"
 $(error "Please upgrade GCC")
 endif
 
-ifndef AVOIDCOMBINE
-AVOIDCOMBINE=$(TESTGCC)
+ifndef COMPSTRAT
+COMPSTRAT=$(TESTGCC)
 endif
 
-# Do a whole file compile - two methods are supported.  The first
-# involves including all the content textually via #include
-# directives.  The second method uses gcc's "-combine" option.
-ifeq "$(AVOIDCOMBINE)" "1"
+# Do a whole file compile - three methods are supported.
+ifeq "$(COMPSTRAT)" "1"
+# First method - use -fwhole-program without -combine.
+define whole-compile
+@echo "  Compiling whole program $3"
+$(Q)printf '$(foreach i,$2,#include "../$i"\n)' > $3.tmp.c
+$(Q)$(CC) $1 -fwhole-program -DWHOLE_PROGRAM -c $3.tmp.c -o $3
+endef
+else ifeq "$(COMPSTRAT)" "2"
+# Second menthod - don't use -fwhole-program at all.
 define whole-compile
 @echo "  Compiling whole program $3"
 $(Q)printf '$(foreach i,$2,#include "../$i"\n)' > $3.tmp.c
 $(Q)$(CC) $1 -c $3.tmp.c -o $3
 endef
 else
+# Third (and preferred) method - use -fwhole-program with -combine
 define whole-compile
 @echo "  Compiling whole program $3"
-$(Q)$(CC) $1 -combine -c $2 -o $3
+$(Q)$(CC) $1 -fwhole-program -DWHOLE_PROGRAM -combine -c $2 -o $3
 endef
 endif
 
diff --git a/README b/README
index 1ccf5eddea1e7865bc8cd6cb304b8733653e428a..ea734fd496844a599973f75d92f51f456f3af09a 100644 (file)
--- a/README
+++ b/README
@@ -4,11 +4,6 @@ compiled using standard gnu tools (eg, gas and gcc).
 To build, one should be able to run "make" in the main directory.  The
 resulting file "out/bios.bin" contains the processed bios image.
 
-The build requires gcc v4.1 or later.  Some buggy versions of gcc have
-issues with the '-combine' compiler option - in particular, recent
-versions of Ubuntu are affected.  One can use "make AVOIDCOMBINE=1" to
-get around this.
-
 
 Testing of images:
 
@@ -51,8 +46,8 @@ Overview of files:
 
 The src/ directory contains the bios source code.  Several of the
 files are compiled twice - once for 16bit mode and once for 32bit
-mode.  (The gcc compile option '-fwhole-program' is used to remove
-code that is not needed for a particular mode.)
+mode.  (The build system will remove code that is not needed for a
+particular mode.)
 
 The tools/ directory contains helper utilities for manipulating and
 building the final rom.
@@ -64,10 +59,11 @@ temporary and final files.
 Build overview:
 
 The 16bit code is compiled via gcc to assembler (file out/ccode.16.s).
-The gcc "-fwhole-program" option is used to optimize the process so
-that gcc can efficiently compile and discard unneeded code.  (In the
-code, one can use the macros 'VISIBLE16' and 'VISIBLE32' to instruct a
-symbol to be outputted in 16bit and 32bit mode respectively.)
+The gcc "-fwhole-program" and "-ffunction-sections -fdata-sections"
+options are used to optimize the process so that gcc can efficiently
+compile and discard unneeded code.  (In the code, one can use the
+macros 'VISIBLE16' and 'VISIBLE32' to instruct a symbol to be
+outputted in 16bit and 32bit mode respectively.)
 
 This resulting assembler code is pulled into romlayout.S.  The gas
 option ".code16gcc" is used prior to including the gcc generated
@@ -122,16 +118,17 @@ macros (GET/SET_GLOBAL, GET/SET_BDA, and GET/SET_EBDA) are available
 to simplify these accesses.
 
 Global variables defined in the C code can be read in 16bit mode if
-the variable declaration is marked with VAR16 or VAR16_32.  The
-GET_GLOBAL macro will then allow read access to the variable.  Global
-variables are stored in the 0xf000 segment, and their values are
-persistent across soft resets.  Because the f-segment is marked
-read-only during run-time, the 16bit code is not permitted to change
-the value of 16bit variables (use of the SET_GLOBAL macro from 16bit
-mode will cause a link error).  Code running in 32bit mode can not
-access variables with VAR16, but can access variables marked with
-VAR16_32 or with no marking at all.  The 32bit code can use the
-GET/SET_GLOBAL macros, but they are not required.
+the variable declaration is marked with VAR16, VAR16_32, VAR16EXPORT,
+or VAR16FIXED.  The GET_GLOBAL macro will then allow read access to
+the variable.  Global variables are stored in the 0xf000 segment, and
+their values are persistent across soft resets.  Because the f-segment
+is marked read-only during run-time, the 16bit code is not permitted
+to change the value of 16bit variables (use of the SET_GLOBAL macro
+from 16bit mode will cause a link error).  Code running in 32bit mode
+can not access variables with VAR16, but can access variables marked
+with VAR16_32, VAR16EXPORT, VAR16FIXED, or with no marking at all.
+The 32bit code can use the GET/SET_GLOBAL macros, but they are not
+required.
 
 
 GCC 16 bit stack limitations:
@@ -158,8 +155,8 @@ structures can also help.  It is also possible to transition to/from
 an extra stack stored in the EBDA using the stack_hop helper function.
 
 Some useful stats: the overhead for the entry to a bios handler that
-takes a 'struct bregs' is 38 bytes of stack space (6 bytes from
-interrupt insn, 28 bytes to store registers, and 4 bytes for call
+takes a 'struct bregs' is 42 bytes of stack space (6 bytes from
+interrupt insn, 32 bytes to store registers, and 4 bytes for call
 insn).  An entry to an ISR handler without args takes 30 bytes (6 + 20
 + 4).
 
index 5dc6761f4c4b11777ca7d86c78dee9850cf6447b..26427ba51f8e46e6988eb3a486449d9ee861d219 100644 (file)
@@ -463,7 +463,3 @@ handle_19()
     SET_EBDA(boot_sequence, 0);
     do_boot(0);
 }
-
-// Ughh - some older gcc compilers have a bug which causes VISIBLE32
-// functions to not be exported as global variables.
-asm(".global handle_18, handle_19");
index 97fe6accf2dfca0d7e1dd5bb6f5147a951c301dc..3c68990bedc1b3281cc298337b7ec5cb617f7997 100644 (file)
@@ -220,8 +220,3 @@ _start()
     memset(&br, 0, sizeof(br));
     call16_int(0x19, &br);
 }
-
-// Ughh - some older gcc compilers have a bug which causes VISIBLE32
-// functions to not be exported as a global variable - force _start
-// to be global here.
-asm(".global _start");
index 6db6b714142f9019a347d9f1a6d6e7e12d4802e6..e7d41013563074ba811a573675fe396f7ab79fd0 100644 (file)
@@ -125,7 +125,3 @@ s3_resume()
     call16big(&br);
 }
 #endif
-
-// Ughh - some older gcc compilers have a bug which causes VISIBLE32
-// functions to not be exported as global variables.
-asm(".global s3_resume");
index 55f359faccd61657a712b8e8a5a81bd5af4bb4d9..5b2d4a911c5ef944e662d74bf161fc2d0bb22983 100755 (executable)
@@ -12,42 +12,27 @@ TMPFILE3o=out/tmp_testcompile3.o
 $CC -fwhole-program -S -o /dev/null -xc /dev/null > /dev/null 2>&1
 if [ $? -ne 0 ]; then
     echo "  Working around no -fwhole-program" > /dev/fd/2
-    echo 1
+    echo 2
     exit 0
 fi
 
-# Test if "visible" variables are marked global.
-cat - > $TMPFILE1 <<EOF
-unsigned char t1 __attribute__((section(".data16.foo.19"))) __attribute__((externally_visible));
-EOF
-$CC -Os -c -fwhole-program $TMPFILE1 -o $TMPFILE1o > /dev/null 2>&1
-cat - > $TMPFILE2 <<EOF
-extern unsigned char t1;
-int __attribute__((externally_visible)) main() { return t1; }
-EOF
-$CC -Os -c -fwhole-program $TMPFILE2 -o $TMPFILE2o > /dev/null 2>&1
-$CC -nostdlib -Os $TMPFILE1o $TMPFILE2o -o $TMPFILE3o > /dev/null 2>&1
-if [ $? -ne 0 ]; then
-    echo "This version of gcc does not properly handle" > /dev/fd/2
-    echo "  global variables in -fwhole-program mode." > /dev/fd/2
-    echo "Please upgrade to a newer gcc (eg, v4.3 or later)" > /dev/fd/2
-    echo -1
-    exit 1
-fi
-
-# Test if "visible" functions are marked global.
+# Test if "visible" variables and functions are marked global.
 cat - > $TMPFILE1 <<EOF
 void __attribute__((externally_visible)) t1() { }
+unsigned char v1 __attribute__((section(".data16.foo.19"))) __attribute__((externally_visible));
 EOF
 $CC -Os -c -fwhole-program $TMPFILE1 -o $TMPFILE1o > /dev/null 2>&1
 cat - > $TMPFILE2 <<EOF
 void t1();
-void __attribute__((externally_visible)) main() { t1(); }
+extern unsigned char v1;
+int __attribute__((externally_visible)) main() { t1(); return v1; }
 EOF
 $CC -Os -c -fwhole-program $TMPFILE2 -o $TMPFILE2o > /dev/null 2>&1
 $CC -nostdlib -Os $TMPFILE1o $TMPFILE2o -o $TMPFILE3o > /dev/null 2>&1
 if [ $? -ne 0 ]; then
-    echo "  Working around non-global functions in -fwhole-program" > /dev/fd/2
+    echo "  Working around non-functional -fwhole-program" > /dev/fd/2
+    echo 2
+    exit 0
 fi
 
 # Test if "-combine" works