Code Generation

Code Generation

The codegen stage walks the analyzed AST with a visitor (codegen_visitor.h) and emits LLVM IR. It relies entirely on the types and annotations stamped by the semantic analyzer — by this point every expression already knows its resolved sun::Type, and generic specializations have been recorded for it to emit as ordinary non-generic code.

Key Conventions

  • LLVM is accessed through a shared context: ctx.builder and ctx.context.
  • Sun types map to LLVM types via the type resolver: typeResolver.resolve(type) for variables and typeResolver.resolveForReturn(type) for function returns.
  • Classes are value types: functions returning a class return the struct by value, and callers materialize it on the stack for addressability.
  • Arrays are fat pointers: { ptr data, i32 ndims, ptr dims }.
  • Throwing functions (T, IError) return plain T; errors are native LLVM exceptions (__gxx_personality_v0, landing pads), so throw unwinds and catch selects a handler by the thrown class's type id.
  • Lambdas use closure structs; named functions use direct calls. Class methods use the closure ABI: arg 0 is a ptr to { ptr func, ptr env } with the receiver in env, and obj.method in value position is a lambda-typed bound method { methodFn, objPtr }.
  • Call arguments are never re-examined here. Semantic analysis records an ArgConversion per argument on the call node, and every kind of call — plain, module-qualified, generic, method, lambda, interface, constructor, extern "C" — lowers its arguments through one loop, emitCallArguments, that switches on those tags (take the address for a borrow, zero the source for a move, build a fat pointer for an interface, extend a number, ...). Codegen does no semantic analysis of its own.

Source Layout

The code generation is split across multiple files under src/codegen/ by expression type:

FileResponsibility
codegen_visitor.cppMain visitor dispatch, module initialization
functions_lambdas.cppFunction/lambda codegen with closure support
classes.cppClass definitions, constructors, methods
call_expressions.cppFunction calls, method calls
variable_creation.cppVariable declarations (var, let)
variable_references.cppVariable loads, assignments
if_expressions.cppConditionals, ternary expressions
loops.cppfor, while, and for-in loops
match_expressions.cppPattern matching (match expressions)
block_expressions.cppBlock scoping
return_statements.cppReturn value handling
error_handling.cpptry/catch/throw codegen
arrays.cppArray literals and indexing
intrinsics.cppCompiler intrinsic codegen (_sizeof, _load, etc.)
threads.cppOS thread spawning and joining
thread_utils.cppThread utility helpers

Adding a New Expression Type

  1. Add an ASTNodeType enum value and AST class.
  2. Implement a codegen method in the appropriate src/codegen/*.cpp file.
  3. Update the codegenExpression() dispatch switch.