Static con/destruction fix

This CL fixes static con/destruction for both C and C++.

Change-Id: I6abd4bba90736e9829efc29e1dce5850c8e81772
diff --git a/hello_vec/CMakeLists.txt b/hello_vec/CMakeLists.txt
index ee14d41..59efb80 100644
--- a/hello_vec/CMakeLists.txt
+++ b/hello_vec/CMakeLists.txt
@@ -5,7 +5,7 @@
 set(TARGET hello_vec)
 set(ELF ${TARGET}.elf)
 
-add_executable(${ELF} main.c)
+add_executable(${ELF} main.cpp)
 
 target_include_directories(${ELF} PUBLIC include)
 
@@ -26,7 +26,6 @@
 target_compile_options(${ELF} PUBLIC
     -Wall
     -Werror
-    -std=c11
     -O3
     -g3
     -ggdb
diff --git a/hello_vec/Makefile b/hello_vec/Makefile
index c30c5c7..77015f0 100644
--- a/hello_vec/Makefile
+++ b/hello_vec/Makefile
@@ -4,48 +4,47 @@
 SRCDIR        := $(abspath .)
 BUILDDIR      := $(OUTPREFIX)build
 
-CFLAGS   += -Wall
-CFLAGS   += -Werror
 CFLAGS   += -std=gnu11
-CFLAGS   += -march=rv32imfv
-CFLAGS   += -I${ROOTDIR}/springbok/include
-CFLAGS   += -O3 -g3 -ggdb
 
-CFLAGS   += -ffreestanding
-CFLAGS   += -ffunction-sections
-CFLAGS   += -fstack-usage
-CFLAGS   += -mstrict-align
+CCFLAGS  += -std=gnu++11
+CCFLAGS  += -fno-exceptions
+
+CXXFLAGS += -Wall
+CXXFLAGS += -Werror
+CXXFLAGS += -march=rv32imfv
+CXXFLAGS += -I${ROOTDIR}/springbok/include
+CXXFLAGS += -O3 -g3 -ggdb
+CXXFLAGS += -fomit-frame-pointer
+CXXFLAGS += -ffreestanding
+CXXFLAGS += -fstack-usage
+CXXFLAGS += -mstrict-align
 
 LDFLAGS  += -nostartfiles
 LDFLAGS  += -specs=nano.specs
 LDFLAGS  += -Wl,--gc-sections
 LDFLAGS  += -Wl,--print-memory-usage
 LDFLAGS  += -Wl,-Map=${BUILDDIR}/hello_vec.map
-LDFLAGS  += -T../springbok/matcha.ld
-
+LDFLAGS  += -T${ROOTDIR}/springbok/matcha.ld
 
 CC       := ${SHODANROOTDIR}/cache/toolchain_vp/bin/riscv32-unknown-elf-gcc
+CPP      := ${SHODANROOTDIR}/cache/toolchain_vp/bin/riscv32-unknown-elf-g++
 
-${BUILDDIR}/hello_vec.elf: ${BUILDDIR}/main.o ${BUILDDIR}/springbok_gloss.o ${BUILDDIR}/Reset_Handler.o ${BUILDDIR}/crt0.o
+${BUILDDIR}/hello_vec.elf: ${BUILDDIR}/main.o ${BUILDDIR}/springbok_gloss.o ${BUILDDIR}/crt0.o
 	mkdir -p $(dir $@)
-	${CC} ${CFLAGS} $^ ${LDFLAGS} -o $@
+	${CPP} ${CXXFLAGS} ${CPPFLAGS} $^ ${LDFLAGS} -o $@
 	@cat ${BUILDDIR}/hello_vec.map | awk '/\.heap/ {printf("%16s: %13s\n", "heap (reserved)", int(strtonum($$3)/1024) " KB")} /\.stack/ {printf("%16s: %13s\n", "stack (reserved)", int(strtonum($$3)/1024) " KB")}'
 
-${BUILDDIR}/main.o: ${SRCDIR}/main.c ${MAKEFILE_LIST}
+${BUILDDIR}/main.o: ${SRCDIR}/main.cpp ${MAKEFILE_LIST}
 	mkdir -p $(dir $@)
-	${CC} ${CFLAGS} -c $< -o $@
+	${CPP} ${CXXFLAGS} ${CPPFLAGS} -c $< -o $@
 
-${BUILDDIR}/springbok_gloss.o: ${ROOTDIR}/springbok/springbok_gloss.c ${MAKEFILE_LIST}
+${BUILDDIR}/springbok_gloss.o: ${ROOTDIR}/springbok/springbok_gloss.cpp ${MAKEFILE_LIST}
 	mkdir -p $(dir $@)
-	${CC} ${CFLAGS} -c $< -o $@
-
-${BUILDDIR}/Reset_Handler.o: ${ROOTDIR}/springbok/Reset_Handler.c ${MAKEFILE_LIST}
-	mkdir -p $(dir $@)
-	${CC} ${CFLAGS} -c $< -o $@
+	${CPP} ${CXXFLAGS} ${CPPFLAGS} -c $< -o $@
 
 ${BUILDDIR}/crt0.o: ${ROOTDIR}/springbok/crt0.s ${MAKEFILE_LIST}
 	mkdir -p $(dir $@)
-	${CC} ${CFLAGS} -c $< -o $@
+	${CC} ${CXXFLAGS} ${CFLAGS} -c $< -o $@
 
 .PHONY: clean
 clean:
diff --git a/hello_vec/main.c b/hello_vec/main.c
deleted file mode 100644
index b1ff42f..0000000
--- a/hello_vec/main.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <stdio.h>
-#include <springbok.h>
-
-int main(void) {
-  unsigned int start = springbok_ccount();
-  printf("%s(%d): Hello printf!\n", __FILE__, __LINE__);
-  unsigned int end = springbok_ccount();
-
-  return end - start;
-}
diff --git a/hello_vec/main.cpp b/hello_vec/main.cpp
new file mode 100644
index 0000000..598adec
--- /dev/null
+++ b/hello_vec/main.cpp
@@ -0,0 +1,41 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <springbok_intrinsics.h>
+
+class ExampleStatic {
+public:
+  ExampleStatic() {
+    springbok_simprint_error("Hello pre-main C++ world.", 0);
+    value = 1279;
+  }
+
+  ~ExampleStatic() {
+    springbok_simprint_error("Goodbye pre-main C++ world.", 0);
+  }
+
+  unsigned int value;
+};
+
+ExampleStatic exampleStatic;
+
+extern "C" __attribute__((constructor)) void boop(void) {
+  springbok_simprint_error("Hello pre-main C world.", 0);
+}
+
+extern "C" __attribute__((destructor)) void beep(void) {
+  springbok_simprint_error("Goodbye pre-main C world.", 0);
+}
+
+extern "C" void blerp(void) {
+  springbok_simprint_error("Fare thee well, atexit.", 0);
+}
+
+extern "C" int main(void) {
+  static char thingy[10] = {13, 14, 15, 16};
+
+  atexit(blerp);
+
+  printf("%s(%d): Hello printf!\n", __PRETTY_FUNCTION__, __LINE__);
+
+  return thingy[0] + thingy[1] + thingy[2] + thingy[3] + exampleStatic.value;
+}
diff --git a/springbok/CMakeLists.txt b/springbok/CMakeLists.txt
index 5cc98c4..41acb68 100644
--- a/springbok/CMakeLists.txt
+++ b/springbok/CMakeLists.txt
@@ -6,8 +6,7 @@
 add_library(springbok_intrinsic STATIC)
 target_sources(springbok_intrinsic PRIVATE
     crt0.s
-    Reset_Handler.c
-    springbok_gloss.c)
+    springbok_gloss.cpp)
 
 target_include_directories(springbok_intrinsic PUBLIC include)
 
@@ -21,7 +20,6 @@
 target_compile_options(springbok_intrinsic PUBLIC
     -Wall
     -Werror
-    -std=c11
     -Os
     -g3
     -ggdb
@@ -33,4 +31,4 @@
 target_link_options(springbok
 INTERFACE
 -Wl,--whole-archive ${CMAKE_CURRENT_BINARY_DIR}/libspringbok_intrinsic.a -Wl,--no-whole-archive
-)
\ No newline at end of file
+)
diff --git a/springbok/Reset_Handler.c b/springbok/Reset_Handler.c
deleted file mode 100644
index e76a0e8..0000000
--- a/springbok/Reset_Handler.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <stdlib.h>
-
-extern int main(void);
-
-extern void (**__CTOR_LIST__)(void);
-extern void (**__DTOR_LIST__)(void);
-
-void Fini_Handler(void) {
-  // Destructors are called in forward order.
-  // The first element can have a few different meanings (always zero, always
-  // one, number of constructors) depending upon the compiler, but the list is
-  // guaranteed to be null terminated. So let's just ignore the first element
-  // and take advantage of the null termination.
-//   int dtor_count = 1;
-//   while (__DTOR_LIST__[dtor_count] != NULL) {
-//     __DTOR_LIST__[dtor_count]();
-//     dtor_count++;
-//   }
-}
-
-int Reset_Handler(void) {
-  // Constructors are called in reverse order
-  // The first element in the constructor has the same weird meaning as the
-  // destructor list, so best to just ignore it, too.
-//   int ctor_count = 0;
-//   while (__CTOR_LIST__[ctor_count+1] != NULL) {
-//     ctor_count++;
-//   }
-//   while (ctor_count > 0) {
-//     __CTOR_LIST__[ctor_count]();
-//     ctor_count--;
-//   }
-
-  // Call any other C-friendly initialization routines here.
-
-  int retval = main();
-
-  Fini_Handler();
-
-  return retval;
-}
diff --git a/springbok/crt0.s b/springbok/crt0.s
index 654a123..8904159 100644
--- a/springbok/crt0.s
+++ b/springbok/crt0.s
@@ -68,17 +68,47 @@
         jal  ra, _clear_mem
         jal  ra, _setup_stack_sentinels
 
-        ##############################################################################################
-        # Jump to C Reset_Handler, which will perform C initialization calls and then jump into main #
-        ##############################################################################################
-        la   ra, Reset_Handler
-        jalr ra, ra
+        ##########################
+        # Register fini handlers #
+        ##########################
+        la   a0, __libc_fini_array
+        call atexit
 
-        ###################################################################################################
-        # Save main's retval, then verify stack sentinels are unchanged and that sp is where we expect it #
-        ###################################################################################################
-        # Save main's return value
+        ##################################
+        # Perform C initialization calls #
+        ##################################
+        call __libc_init_array
+
+        #############
+        # Call main #
+        #############
+        li   a0, 0 #argv
+        li   a1, 0 #argc
+        li   a2, 0 #envp
+        la   ra, main
+        jalr ra, ra
+        # Save main's return value into s0
         mv   s0, a0
+
+        ######################
+        # Call C destructors #
+        ######################
+        li   a1, 0
+        call __call_exitprocs
+
+        # Restore main's return value
+        mv   a0, s0
+
+        # Don't clear the stack if the program returned from main
+        j    1f
+
+_exit:
+        # Clear the stack
+        la   sp, _stack_ptr
+1:
+        ##########################################################################
+        # Verify stack sentinels are unchanged and that sp is where we expect it #
+        ##########################################################################
         # Check the stack, and fix it if it's broken
         jal  ra, _check_stack
         # Save check_stack's return value
diff --git a/springbok/include/springbok_intrinsics.h b/springbok/include/springbok_intrinsics.h
index 6f18e94..e829416 100644
--- a/springbok/include/springbok_intrinsics.h
+++ b/springbok/include/springbok_intrinsics.h
@@ -71,10 +71,10 @@
 //   none
 static inline void springbok_hostreq(void) {
   // hostreq # "-----------------010-----1111011"
-    __asm__ volatile ("\t.word 0x0000207B\n" :
-                  /* no outputs */ :
-                  /* no inputs */ :
-                  /* no clobbers */);
+  __asm__ volatile ("\t.word 0x0000207B\n" :
+                    /* no outputs */ :
+                    /* no inputs */ :
+                    /* no clobbers */);
 }
 
 // finish
@@ -88,9 +88,9 @@
 //   none
 __attribute__((noreturn)) static inline void springbok_finish(void) {
   // finish # "-----------------011-----1111011"
-    __asm__ volatile ("\t.word 0x0000307B\n" :
-                  /* no outputs */ :
-                  /* no inputs */ :
-                  /* no clobbers */);
+  __asm__ volatile ("\t.word 0x0000307B\n" :
+                    /* no outputs */ :
+                    /* no inputs */ :
+                    /* no clobbers */);
   while(1);
 }
diff --git a/springbok/matcha.ld b/springbok/matcha.ld
index 0cdfae8..81adbc7 100644
--- a/springbok/matcha.ld
+++ b/springbok/matcha.ld
@@ -1,4 +1,3 @@
-ENTRY(_start)
 
 MEMORY
 {
@@ -29,6 +28,29 @@
                 _erodata = .;
         } > DTCM
 
+        .preinit_array :
+        {
+                PROVIDE(__preinit_array_start = .);
+                KEEP(*(.preinit_array))
+                PROVIDE(__preinit_array_end = .);
+        } > DTCM
+
+        .init_array :
+        {
+                PROVIDE(__init_array_start = .);
+                KEEP(*(SORT(.init_array.*)))
+                KEEP(*(.init_array))
+                PROVIDE(__init_array_end = .);
+        } > DTCM
+
+        .fini_array :
+        {
+                PROVIDE(__fini_array_start = .);
+                KEEP(*(SORT(.fini_array.*)))
+                KEEP(*(.fini_array))
+                PROVIDE(__fini_array_end = .);
+        } > DTCM
+
         .data :
         {
                 . = ALIGN(64);
diff --git a/springbok/springbok_gloss.c b/springbok/springbok_gloss.cpp
similarity index 71%
rename from springbok/springbok_gloss.c
rename to springbok/springbok_gloss.cpp
index f582fad..1376240 100644
--- a/springbok/springbok_gloss.c
+++ b/springbok/springbok_gloss.cpp
@@ -1,29 +1,29 @@
+#include <stdlib.h>
 #include <errno.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <stdint.h>
 
 #include <springbok_intrinsics.h>
 
-void _exit(int rc) {
-  springbok_finish();
+void* __dso_handle = (void*) &__dso_handle;
 
-  while (1) { }
-}
+extern "C" void *_sbrk(int nbytes) {
+  extern char _sheap, _eheap;
+  static char *_heap_ptr = &_sheap;
 
-void *_sbrk(int nbytes) {
-  extern int _sheap, _eheap;
-  static void *_heap_ptr = (void *)&_sheap;
-  if ((void*)&_eheap >= _heap_ptr + nbytes) {
-    void *base = _heap_ptr;
-    _heap_ptr += nbytes;
-    return base;
-  } else {
+  if ((nbytes < 0) ||
+      (_heap_ptr + nbytes > &_eheap)) {
     errno = ENOMEM;
     return (void *)-1;
   }
+
+  void *base = _heap_ptr;
+  _heap_ptr += nbytes;
+  return base;
 }
 
-int _read(int file, char *ptr, int len) {
+extern "C" int _read(int file, char *ptr, int len) {
   if (file != STDIN_FILENO) {
     errno = EBADF;
     return -1;
@@ -32,8 +32,7 @@
   return 0;
 }
 
-
-int _write(int file, char *buf, int nbytes) {
+extern "C" int _write(int file, char *buf, int nbytes) {
   static int _write_line_buffer_len[2] = {0, 0};
   static char _write_line_buffer[2][256];
 
@@ -75,12 +74,12 @@
   return nbytes;
 }
 
-int _close(int file) {
+extern "C" int _close(int file) {
   errno = EBADF;
   return -1;
 }
 
-int _lseek(int file, int offset, int whence) {
+extern "C" int _lseek(int file, int offset, int whence) {
   if (file != STDOUT_FILENO && file != STDERR_FILENO) {
     errno = EBADF;
     return -1;
@@ -89,7 +88,7 @@
   return 0;
 }
 
-int _fstat(int file, struct stat *st) {
+extern "C" int _fstat(int file, struct stat *st) {
   if (file != STDOUT_FILENO && file != STDERR_FILENO) {
     errno = EBADF;
     return -1;
@@ -104,7 +103,7 @@
   return 0;
 }
 
-int _isatty(int file) {
+extern "C" int _isatty(int file) {
   if (file != STDOUT_FILENO && file != STDERR_FILENO) {
     errno = EBADF;
     return -1;
@@ -112,3 +111,11 @@
 
   return 1;
 }
+
+void operator delete(void *p) noexcept {
+  free(p);
+}
+
+extern "C" void operator delete(void *p, unsigned long c) noexcept {
+  operator delete(p);
+}
diff --git a/vector_executive/CMakeLists.txt b/vector_executive/CMakeLists.txt
index 326e2c5..1f762cc 100644
--- a/vector_executive/CMakeLists.txt
+++ b/vector_executive/CMakeLists.txt
@@ -24,7 +24,6 @@
 target_compile_options(${ELF} PUBLIC
     -Wall
     -Werror
-    -std=c11
     -O3
     -g3
     -ggdb
diff --git a/vector_load_tests/CMakeLists.txt b/vector_load_tests/CMakeLists.txt
index 4b2820f..7d13871 100644
--- a/vector_load_tests/CMakeLists.txt
+++ b/vector_load_tests/CMakeLists.txt
@@ -30,7 +30,6 @@
 	-ffunction-sections
 	-Wall
 	-Werror
-	-std=gnu11
 	-O3
 	-g)
 
diff --git a/vector_tests/CMakeLists.txt b/vector_tests/CMakeLists.txt
index 554cacd..d7f6bc1 100644
--- a/vector_tests/CMakeLists.txt
+++ b/vector_tests/CMakeLists.txt
@@ -12,7 +12,6 @@
 target_compile_options(vector_tests PUBLIC
     -Wall
     -Werror
-    -std=c11
     -O3
     -g3
     -ggdb
diff --git a/vector_vadd_vsub_tests/CMakeLists.txt b/vector_vadd_vsub_tests/CMakeLists.txt
index 1b7af84..008773a 100644
--- a/vector_vadd_vsub_tests/CMakeLists.txt
+++ b/vector_vadd_vsub_tests/CMakeLists.txt
@@ -35,9 +35,8 @@
 	-Wall
 	-Werror
     -Wno-unused-value
-	-std=gnu11
 	-O3
 	-g
     -D=TEST_${OPERAND_TYPE})
 
-endforeach()
\ No newline at end of file
+endforeach()
diff --git a/vector_vset_tests/CMakeLists.txt b/vector_vset_tests/CMakeLists.txt
index b0efd24..ba64c6b 100644
--- a/vector_vset_tests/CMakeLists.txt
+++ b/vector_vset_tests/CMakeLists.txt
@@ -30,7 +30,6 @@
 	-ffunction-sections
 	-Wall
 	-Werror
-	-std=gnu11
 	-O3
 	-g)