SJC – Small Java Compiler
User Manual Stefan Frenz
Translation: Jonathan Brase
original version: 2011/06/08 latest document update: 2011/08/24
Compiler Version: 182
Java is a registered trademark of Oracle/Sun
Table of Contents
- 1
- Quick introduction.............................................................................................................................4
1.1 Windows...........................................................................................................................................4 1.2 Linux.................................................................................................................................................5 1.3 JVM Environment.............................................................................................................................5 1.4 QEmu................................................................................................................................................5
2
3
Hello World.......................................................................................................................................6
2.1 Source Code......................................................................................................................................6 2.2 Compilation and Emulation...............................................................................................................8 2.3 Details...............................................................................................................................................9
Introduction.....................................................................................................................................11
3.1 Origins, Legal Matters, Resources, and Acknowledgements...........................................................11 3.2 Basic Principles and Objectives.......................................................................................................11 3.3 Memory Image Format....................................................................................................................12 3.4 Object Format..................................................................................................................................12 3.5 Stack Frame Format........................................................................................................................13 3.6 Compiler Structure..........................................................................................................................13 3.7 Implemented Modules.....................................................................................................................15 3.8 Differences from Sun Java..............................................................................................................16
4
56
Frontend Modules for non-Java Files..............................................................................................17
4.1 Importing Binary Files....................................................................................................................17 4.2 Source File Lists..............................................................................................................................17
Compiler Functions.........................................................................................................................18
5.1 Compile Options..............................................................................................................................18 5.2 Symbol Information.........................................................................................................................22
Runtime Environment.....................................................................................................................25
6.1 Root Object.....................................................................................................................................25 6.2 Strings.............................................................................................................................................25 6.3 Typesystem and Code Related Classes............................................................................................25 6.4 Definition of the Runtime Environment for Allocation and Type Checking...................................26 6.5 Example Implementation of Required 32 Bit Runtime Routines.....................................................27 6.6 Runtime Extensions for the Use of Java Exceptions........................................................................30 6.7 Runtime Extensions for the Use of Synchronized Blocks................................................................31 6.8 Runtime Extensions for Stack Limit Checking................................................................................32 6.9 Runtime Extensions for the Use of Assert Statements.....................................................................32 6.10 Definition of the Optional Arithmetic Library.................................................................................32
- 7
- Special Classes................................................................................................................................34
7.1 MAGIC...........................................................................................................................................34 7.2 SJC Annotations..............................................................................................................................38 7.3 STRUCT.........................................................................................................................................40 7.4 FLASH............................................................................................................................................40
89
Inline Arrays....................................................................................................................................41
8.1 Changes to the Object Structure......................................................................................................41
Indirect Scalars................................................................................................................................43
9.1 Changes to the Object Structure......................................................................................................43 9.2 Changes to the Runtime Environment.............................................................................................44
10
11 12
In-Image Symbol Information.........................................................................................................46
10.1 raw Symbol Information..................................................................................................................46 10.2 rte Symbol Information...................................................................................................................47 10.3 Mthd Symbol Information...............................................................................................................48
Native Linux and Windows Programs.............................................................................................49
11.1 Basic Functionality..........................................................................................................................49 11.2 Native Linux Programs....................................................................................................................49 11.3 Native Microsoft Windows Programs.............................................................................................52
Examples.........................................................................................................................................54
12.1 Use of Inlining.................................................................................................................................54 12.2 Access to I/O Ports..........................................................................................................................54 12.3 Writing Interrupt Handlers..............................................................................................................54 12.4 Use of STRUCTs.............................................................................................................................55 12.5 Initialization in Embedded Mode....................................................................................................56 12.6 Handcoded Method Calls................................................................................................................56 12.7 TextualCall......................................................................................................................................57
13 14
Bootloader.......................................................................................................................................59 References.......................................................................................................................................64
1 Quick introduction
For a quick introduction, download the executable package (see [sjc] in the References section), which contains all the necessary files for the development of 32 and 64-bit operating systems:
- File
- Description
b64_dsk.bin Floppy bootloader for 64-bit target systems bootconf.txt Configuration file for the boot image writer bts_dsk.bin Floppy bootloader for 32-bit target systems
- compile
- Compiler executable for Linux
compile.exe Compiler executable for Windows hello.java Example "Hello World" program
- rte.java
- Basic runtime environment framework
No programs outside this package are necessary for the compilation of an operating system. However, testing the compiled system requires a PC emulator such as QEmu (see [qemu]). This introduction assumes that a QEmu installation is available.
The next four sections of this chapter demonstrate the invocation of the compiler under Windows, Linux, and a JVM, as well as booting the resulting system in QEmu. These instructions will compile the included "Hello World" program (discussed in chapter 2) for a 32-bit target system.
In developing a new system with the compiler, it is reccomended that the user read at least chapters 2, 3.4, 3.8, 5.1, 6.5 and 7. Examples can be found in chapter 12. Furthermore, an example system supporting 32-bit protected mode and 64-bit long mode can be found in the reference section under [picos].
1.1 Windows
If the executable package has been unpacked into C:\Compiler, the installation can be tested with this command line:
C:\Compiler>compile hello.java rte.java -o boot
This should produce approximately the following output (shown here with a few extra status messages):
The above command line will also produce the files BOOT_FLP.IMG and syminfo.txt. The first contains a floppy image of the example program, the second contains symbol information, described in detail in chapter 5.2.
1.2 Linux
If the executable package has been unpacked into ~/compiler, it may be necessary to set the executable flag:
smf@linplu:~/compiler> chmod a+x compile
The installation can then be tested with the following command line:
smf@linplu:~/compiler> ./compile hello.java rte.java -o boot
This should produce approximately the following output: As under Windows (see the previous section), the files BOOT_FLP.IMG (a floppy image) and syminfo.txt (containing symbol information) will be produced.
1.3 JVM Environment
In addition to the Windows and Linux versions, there is also, since version 181, a precompiled JAR version of the compiler. Instead of the native compilers, the JVM is executed with sjc.jar as a parameter. All other parameters, as well as the output, correspond to the Linux and Windows versions:
C:\Compiler>compile hello.java rte.java -o boot
1.4 QEmu
The following command lines can be used to boot the compiled floppy image in QEmu:
"C:\Compiler>\Program Files\QEmu\qemu.exe" -m 32 -boot a -fda BOOT_FLP.IMG smf@linplu:~/compiler> qemu -m 32 -boot a -fda BOOT_FLP.IMG
These should (depending on the versions of QEmu and its BIOS) result in the following output: If the system starts, but hangs without any error message, the cause could be a faulty KVM module. This can be deactivated with -no-kvm, the resulting command line would then be:
> qemu -no-kvm -m 32 -boot a -fda BOOT_FLP.IMG
2 Hello World
This chapter will introduce the source code for a simple "Hello World" program, and the command lines to compile it (all necessary files are in the executable package, see [sjc]), and to boot it in QEmu. Afterwards, the individual steps in this process and the default options assumed by the compiler will be explained.
2.1 Source Code
Program (hello.java)
package kernel; public class Kernel { private static int vidMem=0xB8000; public static void main() { print("Hello World"); while(true); } public static void print(String str) { int i; for (i=0; i<str.length(); i++) print(str.charAt(i)); } public static void print(char c) { MAGIC.wMem8(vidMem++, (byte)c); MAGIC.wMem8(vidMem++, (byte)0x07); } }
Runtime Environment (rte.java)
package java.lang; import rte.SClassDesc; public class Object { public final SClassDesc _r_type; public final Object _r_next; public final int _r_relocEntries, _r_scalarSize; }package java.lang; public class String { private char[] value; private int count; @SJC.Inline public int length() { return count; } @SJC.Inline public char charAt(int i) { return value[i]; } }package rte; public class SArray { public final int length=0, _r_dim=0, _r_stdType=0; public final Object _r_unitType=null; }package rte; public class SClassDesc { public SClassDesc parent; public SIntfMap implementations; }package rte; public class SIntfDesc { /*optional: public SIntfDesc[] parents;*/ } package rte; public class SIntfMap { public SIntfDesc owner; public SIntfMap next; }package rte; public class SMthdBlock { } package rte; public class DynamicRuntime { public static Object newInstance(int scalarSize, int relocEntries, SClassDesc type) { while(true); } public static SArray newArray(int length, int arrDim, int entrySize, int stdType, Object unitType) { while(true); } public static void newMultArray(SArray[] parent, int curLevel, int destLevel, int length, int arrDim, int entrySize, int stdType, Object unitType) { while(true); } public static boolean isInstance(Object o, SClassDesc dest, boolean asCast) { while(true); } public static SIntfMap isImplementation(Object o, SIntfDesc dest, boolean asCast) { while(true); } public static boolean isInstance(Object o, SClassDesc dest, Object unitType, int arrDim, boolean asCast) { while(true); } public static void checkArrayStore(SArray dest, Object newEntry) { while (true); } }
Bootloader configuration (bootconf.txt)
section floppy32 section default destfile boot_flp.img blocksize 512 maximagesize 1474048 readbuf bts_dsk.bin offset 30.l4 value imageaddr offset 34.l4 value unitaddr offset 38.l4 value codeaddr offset 42.l4 crc 0x82608EDB offset 46.l2 value blockcnt writebuf appendimage endsection
2.2 Compilation and Emulation
If the files designated in the last subchapter have been placed in the same directory, along with a compiler executable appropriate to the platform and the file bts_dsk.bin (required to setup the bootsector), the "Hello World" program can be compiled with:
compile hello.java rte.java -o boot
bts_dsk.bin is contained in the executable package (see [sjc]) or can be assembled with yasm (see [yasm]) from the source code found in chapter 13. The output of the compiler should look something like this (for a screenshot see chapter 1):
Welcome to the smfCompiler SJC (v178) Compiling static fullsized objects for 32-bit, assign pointers directly Parse file "rte.java"... progress: . Parse file "hello.java"... Created 20 objects for 11 units, 12 methods and 1 strings. Included 244 b code and 11 string-chars (80 b) in an 724 b image.
A successful compilation will create the file BOOT_FLP.IMG, which can either be written to a floppy (on Windows this can be accomplished with programs such as rawrite (see [rawrite]), on Linux it can be done with dd), or can be used directly with an emulator such as QEmu. If QEmu (see [qemu]) has been properly installed to C:\Program Files\QEmu, the floppy image can be booted with:
"C:\Program Files\Qemu\qemu.exe" -m 32 -boot a -fda BOOT_FLP.IMG
A screenshot can be found in chapter 1. Under some circumstances, QEmu's KVM module may be defective. The module can be deactivated with the option -no-kvm.
2.3 Details
Program
The static variable vidMem is created by the compiler as a class variable. Its value in the disk image is initialized to 0xB8000, the address of the beginning of video memory for VGA compatible graphics cards.
The method main() is called by the code in the bootsector and is the entry point to the Java code. It calls a method to print a string, and then puts the processor into an infinite loop.
String output is implemented in the method print(String str), which, for each character in the given string, calls a character output method.
The method print(char c) copies the lower 8 bits of the given character, with the help of
MAGIC.wMem8(.), to the address given by the current value of vidMem. The graphics card then, in text mode, interprets the copied value as an ASCII character. The post-increment of vidMem causes it to point to the next byte, which determines the color of the character that has just been written. A second use of MAGIC.wMem8(.) sets the color byte to 0x07, which signifies "gray on black", and vidMem is then post-incremented to point to the next character in video memory.
Runtime Environment
The root of the type hierarchy is the class java.lang.Object, which requires the instance variables
_r_type, _r_next, _r_relocEntries and _r_scalarSize (in this order). However, the given "Hello World" program does not use _r_next, _r_relocEntries und _r_scalarSize so these can
be omitted by means of the compiler option -l. The implementation of String for this example conforms to the Java standard, so the array and length variables cannot be directly accessed. The array type used, char[] also conforms to the Java standard, but in this example no use of Unicode characters is made and thus a byte[] implementation (compiler option -y) would be sufficient.
The @SJC.Inline annotation is used to mark the methods length() and charAt(int) so that the
compiler tries to insert the body of the method in question directly into the calling method, instead of making a subroutine call (See section 7.2).