fspl/generator
Sasha Koshka c934a6c76c Updated readme (conditional comp. -> GOOS/GOARCH) 2024-04-09 19:00:59 +00:00
..
native Generator native uses GOARCH and GOOS instead of cond. compilation 2024-03-28 16:02:56 -04:00
README.md Updated readme (conditional comp. -> GOOS/GOARCH) 2024-04-09 19:00:59 +00:00
assignment.go Fix assignment from array to slice 2024-03-24 19:57:24 -04:00
blockmanager.go Loops now handle multiple break statements correctly 2024-03-20 04:19:47 -04:00
cast_test.go Putting complete covering of bit casts on hold for now 2024-02-28 20:08:54 -05:00
control-flow_test.go Generate switch statements 2024-03-26 00:42:27 -04:00
data.go Generate match statements 2024-03-06 00:42:40 -05:00
doc.go Added module-level doc comments to generator and generator/native 2024-02-09 00:57:06 -05:00
expression-loc.go Changed repository import paths 2024-02-22 19:22:53 -05:00
expression-multiplex.go Generate switch statements 2024-03-26 00:42:27 -04:00
expression-val.go Fix calling methods on pointers to types in other units 2024-03-13 11:51:51 -04:00
expression.go Generate switch statements 2024-03-26 00:42:27 -04:00
function.go Update generator 2024-03-14 03:20:47 -04:00
function_test.go Add TestMethodPtr to generator 2024-03-11 11:50:12 -04:00
generator.go Add OS field to Target 2024-03-27 12:05:30 -04:00
interface_test.go Change interface symbol from ~ to & 2024-03-13 23:05:58 -04:00
literal.go Changed repository import paths 2024-02-22 19:22:53 -05:00
literal_test.go Remove the star from array literals 2024-03-24 20:31:25 -04:00
misc_test.go Fix test cases 2024-03-20 11:19:24 -04:00
multiunit_test.go Changed restricted access specified from ~ to # 2024-03-14 01:42:19 -04:00
test-common.go Add and fix test case for #47 (on the generator side at least) 2024-02-28 13:36:21 -05:00
type-multiplex.go Update generator 2024-03-14 03:20:47 -04:00
type.go Generate union types 2024-03-05 03:15:44 -05:00
type_test.go Change interface symbol from ~ to & 2024-03-13 23:05:58 -04:00
union_test.go Update generator tests 2024-03-24 20:02:57 -04:00

README.md

generator

Responsibilities

Given a compilation target, turn a well-formed FSPL semantic tree into an LLVM IR module tree.

Organization

Generator defines the Target type, which contains information about the system that the program is being compiled for. The native sub-package uses GOOS and GOARCH to provide a default Target that matches the system the compiler has been natively built for.

The entry point for all logic defined in this package is Target.Generate(). This method creates a new generator, and uses it to recursively generate and return an LLVM module. The details of the generator are hidden from other packages, and instances of it only last for the duration of Target.Generate().

The generator contains a stack of blockManagers, which plays a similar role to analyzer.scopeContextManager, except that the stack of blockManagers is managed directly by the generator, which contains appropriate methods for pushing/popping them.

Like the analyzer, the generator greedily generates code, and one function may be generated in the middle of the generation process of another function. Thus, each blockManager is tied to a specific LLVM function, and is in charge of variables/stack allocations and to a degree, control flow flattening (specifically loops). It also embeds the current active block, allowing for generator routines to call its methods to add new instructions to the current block, and switch between different blocks when necessary.

Operation

When Target.Generate() is called, a new generator is created. It is given the semantic tree to generate, as well as a copy of the Target. All data structure initialization within the generator happens at this point.

Then, the generate() method on the newly created generator is called. This is the entry point for the actual generation logic. This routine is comprised of two phases:

  • Function generation
  • Method generation

You'll notice that there is no step for type generation. This is because types are generated on-demand in order to reduce IR clutter.

Expression Generation

Since expressions make up the bulk of FSPL, expression generation makes up the bulk of the code generator. The generator is able to produce expressions in one of three modes:

  • Location: The generator will return an IR register that contains a pointer to the result of the expression.
  • Value: The generator will return an IR register that directly contains the result of the expression.
  • Any: The generator will decide which of these two options is best for the specific expression, and will let the caller know which was chosen, in case it cares. Some expressions are better suited to returning a pointer, such as array subscripting or member access. Other expressions are better suited to returning a value, such as arithmetic operators and function calls.

It is important to note that generating a Value expression may return a pointer, because FSPL pointers are first-class values. The distinction between location and value generation modes is purely to do with LLVM. It is similar to the concept of location expressions within the analyzer, but not 100% identical all of the time.

Whenever an expression needs to be generated, one of the following routines is called:

  • generator.generateExpression()
  • generator.generateAny()
  • generator.generateVal()
  • generator.generateLoc()

The generator.generateExpression() routine takes in a mode value and depending on it, calls one of the other more specific routines. Each of these routines, in turn, calls a more specialized generation routine depending on the specific expression.

If it is specifically requested to generate a value for an expression with only its location component defined or vice versa, generator.generateVal/Loc() will automatically perform the conversion.