Merge pull request #139 from whiteh0le/fix-spelling

Fix various spelling mistakes
This commit is contained in:
water111 2020-11-23 16:24:30 -05:00 committed by GitHub
commit d8b1feaa3d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 26 additions and 27 deletions

View file

@ -27,7 +27,6 @@ Our objectives are:
- Our GOAL compiler's performance should be around the same as unoptimized C.
- try to match things from the original game and development as possible. For example, the original GOAL compiler supported live modification of code while the game is running, so we do the same, even though it's not required for just porting the game.
- support modifications. It should be possible to make edits to the code without everything else breaking.
-
We support both Linux and Windows on x86-64.
@ -112,7 +111,7 @@ The final component is the "runtime", located in `game`. This is the part of the
- `build`: C++ CMake build folder
- `common`: common C++ code shared between the compiler, decompiler, and game.
- `cross_os_debug`: platform-independent library for implementing the OpenGOAL debugger. Linux-only currently
- `cross_sockets`: platform-indpendent library for sockets. Used to connect the compiler to a running game. Linux and Windows.
- `cross_sockets`: platform-independent library for sockets. Used to connect the compiler to a running game. Linux and Windows.
- `goos`: the compiler-time macro language and parser for OpenGOAL.
- `type_system`: the OpenGOAL type system
- `util`: Random utility functions for accessing files, timers, etc.
@ -126,7 +125,7 @@ The final component is the "runtime", located in `game`. This is the part of the
- `ObjectFile`: Utilities for processing the GOAL object file format.
- `scripts`: Useful scripts for setting up the decompilation
- `util`: random utilities
- `decompiler_out`: output of the decompiler that's not automaically used by the compiler. This is for humans to read and use. Not included in the repository.
- `decompiler_out`: output of the decompiler that's not automatically used by the compiler. This is for humans to read and use. Not included in the repository.
- `doc`: more documentation!
- `game`: the source code for the game executable
- `common`: shared stuff between the `kernel` and `overlord`
@ -145,7 +144,7 @@ The final component is the "runtime", located in `game`. This is the part of the
- `debugger`: The OpenGOAL debugger (part of the compiler)
- `emitter`: x86-64 emitter and object file generator
- `listener`: The OpenGOAL listener, which connects the compiler to a running GOAL program for the interactive REPL
- `regalloc`: Register alocator
- `regalloc`: Register allocator
- `iso_data`:
- `out`: Outputs from the build process. Only the `iso` subfolder should contain assets used by the game.
- `iso`: Final outputs that are used by the game.

View file

@ -40,7 +40,7 @@ If you were to `code.print()`, you would get:
There are a few details worth mentioning about this process:
- The reader will expand `'my-symbol` to `(quote my-symbol)`
- The reader will throw errors on synatx errors (mismatched parentheses, bad strings/numbers, etc.)
- The reader will throw errors on syntax errors (mismatched parentheses, bad strings/numbers, etc.)
- Using `read_from_file` adds information about where each thing came from to a map stored in the reader. This map is used to determine the source file/line for compiler errors.
# IR Pass
@ -335,7 +335,7 @@ Once the `CodeGenerator` is done going through all functions and static data, it
```
return m_gen.generate_data_v3().to_vector();
```
This actually lays out everything in memory. It takes a few passes because x86 instructions are variable length (may even change based on which reigsters are used!), so it's a little bit tricky to figure out offsets between different instructions or instructions and data. Finally it generates link data tables, which efficiently pack together links to the same symbols into a single entry, to avoid duplicated symbol names. The link table also contains information about linking references in between different segments, as different parts of the object file may be loaded into different spots in memory, and will need to reference each other.
This actually lays out everything in memory. It takes a few passes because x86 instructions are variable length (may even change based on which registers are used!), so it's a little bit tricky to figure out offsets between different instructions or instructions and data. Finally it generates link data tables, which efficiently pack together links to the same symbols into a single entry, to avoid duplicated symbol names. The link table also contains information about linking references in between different segments, as different parts of the object file may be loaded into different spots in memory, and will need to reference each other.
This is the final result for top-level function (stored in top-level segment)
```
@ -433,7 +433,7 @@ memcpy(buffer.c(), msg.c(), MessCount);
ListenerLinkBlock->value = buffer.offset + 4;
ListenerFunction->value = link_and_exec(buffer, "*listener*", 0, kdebugheap, LINK_FLAG_FORCE_DEBUG).offset;
```
- The `link_and_exec` function doesn't actually exectue anything becuase it doesn't have the `LINK_FLAG_EXECUTE` set, it just links things. It moves the top level function and linking data to the top of the heap (temporary storage for the kernel) and keep both the main segment and debug segment of the code on the debug heap. It'll move them together and eliminate gaps before linking. After linking, the `ListenerFunction->value` will contain a pointer to the top level function, which is stored in the top temp area of the heap. This `ListenerFunction` is the GOAL `*listener-function*` symbol.
- The `link_and_exec` function doesn't actually execute anything because it doesn't have the `LINK_FLAG_EXECUTE` set, it just links things. It moves the top level function and linking data to the top of the heap (temporary storage for the kernel) and keep both the main segment and debug segment of the code on the debug heap. It'll move them together and eliminate gaps before linking. After linking, the `ListenerFunction->value` will contain a pointer to the top level function, which is stored in the top temp area of the heap. This `ListenerFunction` is the GOAL `*listener-function*` symbol.
- The next time the GOAL kernel runs, it will notice that `*listener-function*` is set, then call this function, then set it to `#f` to indicate it called the function.
- This
- After this, `ClearPending()` is called, which sends all of the `print` messages with the `Deci2Server` back to the compiler.

View file

@ -194,7 +194,7 @@ The `daddiu v1, fp, L109` loads a `string` into the `v1` register which is never
## Return-From evaluates to 0 bug
We would expect the value of `(return-from #f x)` to be nothing, as there's no possible way to use it. However, GOAL seems to have a small bug where `(return-from #f x)` always attempts to evaluate to 0. This would be like implementing it as:
```lisp
(set! retrun-reg return-value)
(set! return-reg return-value)
(goto end-of-function)
0 ;; oops
```

View file

@ -20,5 +20,5 @@ x86-64 has a lot of instructions. They are described in Volume 2 of the 5 Volum
- `sub rdest, roff` : convert real pointer to GOAL pointer
- `mov rdest, [rdest + roff + variable_offset]` : access memory through normal GOAL deref.
- Note - we should check that the register allocator gets this right always, and eliminates moves and avoid using a temporary register.
- Again, the constant propagation should give use enough information, if we ever want/need to implement a more efficient `mov rdest, [rsp + varaible_offset]` type instructions.
- Again, the constant propagation should give use enough information, if we ever want/need to implement a more efficient `mov rdest, [rsp + variable_offset]` type instructions.
- Memory access to static data should use `rip` addressing, like `mov rdest, [rip + offset]`. And creating pointers to static data could be `lea rdest, [rip - roff + offset]`

View file

@ -56,7 +56,7 @@ The file will be the exact size of `EE_MAIN_MEM_SIZE`, but the first `EE_LOW_MEM
Anywhere an address can be used, you can also use an "address spec", which gives you easier ways to input addresses. For now, the address spec is pretty simple, but there will be more features in the future.
- `(sym-val <sym-name>)`. Get the address stored in the symbol with the given name. Currently there's no check to see if the symbol actually stores an address or not. This is like "evaluate `<sym-name>`, then treat the value as an address"
- `(sym <sym-name>)`. Get the address of the symbol object itself, including the basic offet.
- `(sym <sym-name>)`. Get the address of the symbol object itself, including the basic offset.
Example to show the difference:
```lisp

View file

@ -306,7 +306,7 @@ A normal Lisp/Scheme `unless`.
```
If `test` is false, evaluate all forms and return the value of the last one. If `test` isn't false, return `#f`.
# Compiler Forms - Defintion
# Compiler Forms - Definition
@ -379,7 +379,7 @@ Make this function call inlined.
```
Example: inline call `my-function`
```
((inline my-funciton) my-arg)
((inline my-function) my-arg)
```
Attempts to make the function call inline. If it is not possible, it will throw an error. You can't save the value of `(inline my-function)`, only use it immediately in a function call. You must provide a name of a global function as the function, not a function pointer.
@ -472,10 +472,10 @@ The constant is available in both GOOS and GOAL. You can use it in `#cond` expre
There are a few restrictions:
- Currently constants do not work in `deftype`. (this should be fixed eventually)
- Constants may not work in places where the compiler is expecting a symbol which isn't actually compiled. So `(+ MY_CONSTANT 2)` is fine, but `(defun MY_CONSANT () ...)` isn't. Don't use constants for type names, function names, or symbol names. It is fine to have a constant with a value of a symbol, but don't `(define MY_CONSTANT)` or `(set! MY_CONSTANT)` or `(new MY_CONSTANT)` or things like that.
- Constants may not work in places where the compiler is expecting a symbol which isn't actually compiled. So `(+ MY_CONSTANT 2)` is fine, but `(defun MY_CONSTANT () ...)` isn't. Don't use constants for type names, function names, or symbol names. It is fine to have a constant with a value of a symbol, but don't `(define MY_CONSTANT)` or `(set! MY_CONSTANT)` or `(new MY_CONSTANT)` or things like that.
- Don't use constants with `method` form.
- You can modify constants created with `defglobalconstant` in GOOS (effect won't be seen in GOAL) with `(set!)`
- There is no warning if one `defglobalconstant` changes the value of an exisiting `defglobalconstant`
- There is no warning if one `defglobalconstant` changes the value of an existing `defglobalconstant`
In general constants should have `UPPERCASE` names otherwise things get very confusing when there are name conflicts.
@ -483,7 +483,7 @@ The recommendation is to use constants for things like numbers or expressions li
## `mlet`
Scoped constants in GOAL. Syntax is like a `let`. This feature has all the restrictions of `defglobalconstant`.
Avoid using `mlet` becuase it's confusing and not useful.
Avoid using `mlet` because it's confusing and not useful.
```lisp
(mlet ((constant-name constant-value)...)
body...
@ -636,9 +636,9 @@ If the `type` and the `thing` are both numbers, it will automatically convert be
If the `thing` is a number:
- If `type` is `binteger`, convert the number to a `binteger`
- If `type` is `int` or `uint` (or some user-defined child type of these), convert the number to an integer.
- If `type` is `float`, conver the number to a `float`
- If `type` is `float`, convert the number to a `float`
In all other cases, directly use the 64-bit value in the reigster as the value of the desired `type`.
In all other cases, directly use the 64-bit value in the register as the value of the desired `type`.
Example of number conversions:
@ -826,7 +826,7 @@ GOAL pointers work a lot like C/C++ pointers, but have some slight differences:
In both C and GOAL, there is a connection between arrays and pointers. A GOAL array field will have a pointer-to-element type, and a pointer can be accessed as an array.
One confusing thing is that a `(pointer int32)` is a C `int32_t*`, but a `(pointer my-structure-type)` is a C `my_structure_type**`, becuase a GOAL `my-structure-type` is like a C `my_structure_type*`.
One confusing thing is that a `(pointer int32)` is a C `int32_t*`, but a `(pointer my-structure-type)` is a C `my_structure_type**`, because a GOAL `my-structure-type` is like a C `my_structure_type*`.
## Inline Arrays
One limitation of the system above is that an array of `my_structure_type` is actually an array of references to structures (C `object*[]`). It would be more efficient if instead we had an array of structures, laid out together in memory (C `object[]`).
@ -962,7 +962,7 @@ The following destinations are currently supported:
The global variable `*print-column*` can be used to automatically print at a certain indentation. The very first thing printed during a frame will not have the indentation applied.
The format string excape sequences all start with `~`, then have arguments (possibly none), then have a single character code. The arguments look like:
The format string escape sequences all start with `~`, then have arguments (possibly none), then have a single character code. The arguments look like:
- `~A`, the `A` code with no arguments
- `~12A`, the `A` code with an integer argument of `12`
- `~'zA`, the `A` code with a character argument of `z`

View file

@ -9,7 +9,7 @@ To access a GOOS REPL, run `(goos)` from the `goal>` prompt (note, currently thi
This document assumes some familiarity with the Scheme programming language. It's recommended to read a bit about Scheme first.
Note that most Scheme things will work in GOOS, with the following exceptions:
- Scheme supports fractions, GOOS does not (it has seaparate integer/floating point types)
- Scheme supports fractions, GOOS does not (it has separate integer/floating point types)
- The short form for defining functions is `(desfun function-name (arguments) body...)`
- GOOS does not have tail call optimization and prefers looping to recursion (there is a `while` form)
@ -27,7 +27,7 @@ Usually, each argument is evaluated, then passed to the operation, and the resul
(do-y)
)
```
In this case, only one of `(do-x)` and `(do-y)` are executed. This doesn't follow the pattern of "evaluate all arugments...", so it is a *SPECIAL FORM*. It's not possible for a function call to be a special form - GOOS will automatically evaluate all arguments. It is possible to build macros which act like special forms. There are some special forms built-in to the GOOS interpreter, which are deocumented in this section.
In this case, only one of `(do-x)` and `(do-y)` are executed. This doesn't follow the pattern of "evaluate all arguments...", so it is a *SPECIAL FORM*. It's not possible for a function call to be a special form - GOOS will automatically evaluate all arguments. It is possible to build macros which act like special forms. There are some special forms built-in to the GOOS interpreter, which are documented in this section.
### define
This is used to define a value in the current lexical environment.

View file

@ -14,7 +14,7 @@ The code in `game/sce` is my implementation of the Sony libraries. When possible
The PS2's main CPU is called the EE. It runs GOAL code and the C Kernel, which is Naughty Dog's C++ code. The C Kernel is responsible for bootstrapping GOAL's kernel and exposing Sony library functions to GOAL code. The C Kernel is in `game/kernel`. In OpenGOAL the "EE Thread" runs code than ran on the EE on the PS2. This includes the C Kernel and all GOAL code. There is a single EE thread - GOAL implements its own threading, but this all runs in the same Linux/Windows thread.
The PS2 has a separate I/O Processor called the IOP. It runs the OVERLORD driver written by Naughty Dog in C. OpenGOAL uses C++ for its implementation of OVERLORD. Like with the EE, there are Sony libraries for the IOP. These are in `game/sce/iop` to distiguish them from EE code. The IOP can run independently from the EE. Unlike the EE, the IOP itself has multiple threads (7 threads) that each have their own OS thread. But only one IOP thread runs at a time, as the IOP was a single-core CPU.
The PS2 has a separate I/O Processor called the IOP. It runs the OVERLORD driver written by Naughty Dog in C. OpenGOAL uses C++ for its implementation of OVERLORD. Like with the EE, there are Sony libraries for the IOP. These are in `game/sce/iop` to distinguish them from EE code. The IOP can run independently from the EE. Unlike the EE, the IOP itself has multiple threads (7 threads) that each have their own OS thread. But only one IOP thread runs at a time, as the IOP was a single-core CPU.
To give an idea of the size of these (counted by `wc -l`):
- OVERLORD is 3700 lines, but still has a lot to implement,
@ -41,7 +41,7 @@ The IOP was a separate I/O Processor on the PS2. It runs a cooperative multi-tas
The library in `game/sce/iop.h` wraps the `IOP_Kernel` in an interface that looks like the Sony libraries used by the game so the IOP code can be ported directly.
There are a few stub functions that are hardcoded to return the correct values for stuff like CD drive initialization. The main features currently supported are:
- Threads (create, wakup, start, sleep, delay, get ID)
- Threads (create, wakeup, start, sleep, delay, get ID)
- Messageboxes to pass data between threads (send, poll)
- SIF RPC, a library to receive remote procedure calls from the EE. See `game/sce/sif_ee.h` for the wrapper of the EE side library, and `game/kernel/kdgo.cpp` and `ksound.cpp` for the wrapper around the EE library that's exposed to GOAL.
- DMA to the EE for sending data from the IOP to GOAL.
@ -93,7 +93,7 @@ The final chunk is not double buffered. This is so it can be loaded directly int
The IOP side state machine for this is in `iso.cpp`, implemented inside of the DGO load buffer complete callback and is somewhat complicated because DGO info may be split between multiple buffers, and you have to deal with getting partial info. The EE side is in `kdgo.cpp`.
The DGO syncronization is pretty confusing but I believe I have it working. It may be worth documenting it more (I thought I did already, but where did I put it?).
The DGO synchronization is pretty confusing but I believe I have it working. It may be worth documenting it more (I thought I did already, but where did I put it?).
## IOP Server/Ramdisk (3)
This is implemented, but so far unused and untested.

View file

@ -1,5 +1,5 @@
# Reader
GOOS and GOAL both use the same reader, which converts text files to S-Expressions and allows these s-expressions to be mapped back to a line in a source file for error messages. This docuemnt explains the syntax of the reader. Note that these rules do not explain the syntax of the language (for instance, GOAL has a much more complicated system of integers and many more restrictions), but rather the rules of how your program source must look.
GOOS and GOAL both use the same reader, which converts text files to S-Expressions and allows these s-expressions to be mapped back to a line in a source file for error messages. This document explains the syntax of the reader. Note that these rules do not explain the syntax of the language (for instance, GOAL has a much more complicated system of integers and many more restrictions), but rather the rules of how your program source must look.
## Integer Input
Integers handled by the reader are 64-bits. Any overflow is considered an error. An integer can be specified as a decimal, like `0` or `-12345`; in hex, like `#xbeef`; or in binary, like `#b101001`. All three representations can be used anywhere an integer is used. Hex numbers do not care about the case of the characters. Decimal numbers are signed, and wrapping from a large positive number to a negative number will generate an error. The valid input range for decimals is `INT64_MIN` to `INT64_MAX`. Hex and binary are unsigned and do not support negative signs, but allow large positive numbers to wrap to negative. Their input range is `0` to `UINT64_MAX`. For example, `-1` can be entered as `-1` or `#xffffffffffffffff`, but not as `UINT64_MAX` in decimal.

View file

@ -109,7 +109,7 @@ For value types, arrays work as you expect. They have type `(pointer your-type)
- Array of references: `(pointer your-type)`, like a C array of pointers
- Array of inline objects: `(inline-array your-type)`, like a C array of structs
The default alignment of structs is 16 bytes, which is also the minimum alignment of `kmalloc`, and the minimum alignment used when using a refence type as an inline field. However, it's possible to violate this rule in a `(inline-array your-type)` to be more efficient. The `your-type` can set a flag indicating it should be packed in an inline array.
The default alignment of structs is 16 bytes, which is also the minimum alignment of `kmalloc`, and the minimum alignment used when using a reference type as an inline field. However, it's possible to violate this rule in a `(inline-array your-type)` to be more efficient. The `your-type` can set a flag indicating it should be packed in an inline array.
I believe the alignment then becomes the maximum of the minimum alignment of the `your-type` fields. So if you have a type with two `uint32`s (alignment 4 bytes), an `(inline-array your-type)` can then have spacing of 8 bytes, instead of the usual minimum 16. The behavior of a `(field-name your-type :inline #t)` is unchanged and will still align at the minimum of 16 bytes. I _believe_ that the first element of the array will still have an alignment of 16.
@ -123,7 +123,7 @@ There's a single type system library, located in `common/type_system`. It will
- Type Checking for compiler
- Parsing of type definitions for compiler
- Lowest common ancestor implementation for compiler to figure out return types for branching forms.
- Logic to catch multiple incompatible type defintions for both compiler warnings and decompiler sanity checks
- Logic to catch multiple incompatible type definitions for both compiler warnings and decompiler sanity checks
Compile Time vs. Run Time types
------------------------