Documentation ¶
Overview ¶
Package codegen provides code generation of GoCaml language.
MIR compilation unit is compiled to an LLVM IR, an assembly, an object then finally linked to an executable. You can add many optimizations and debug information (DWARF).
Example ¶
file := filepath.FromSlash("../testdata/from-mincaml/ack.ml") src, err := locerr.NewSourceFromFile(file) if err != nil { // File not found panic(err) } ast, err := syntax.Parse(src) if err != nil { // When parse failed panic(err) } // Resolving symbols, type analysis and converting AST into MIR instruction block env, block, err := sema.SemanticsCheck(ast) if err != nil { // Type error detected panic(err) } // Eliminate redundant refs mir.ElimRefs(block, env) // Create MIR compilation unit program := closure.Transform(block) // Make options to emit the result options := EmitOptions{ Optimization: OptimizeDefault, // Optimization level Triple: "x86_64-apple-darwin16.4.0", // Compilation target (Empty string means default target on your machine) DebugInfo: true, // Add debug information to the result or not } // Emitter object, which compiles MIR to LLVM IR and emits assembly, object file or executable // In factory function, given MIR code is already converted to LLVM IR emitter, err := NewEmitter(program, env, src, options) if err != nil { panic(err) } // You need to defer finalization defer emitter.Dispose() // Run LLVM IR level optimizations emitter.RunOptimizationPasses() // Show LLVM IR compiled from `program` fmt.Println("LLVMIR:\n" + emitter.EmitLLVMIR()) // Emit platform-dependant assembly file asm, err := emitter.EmitAsm() if err != nil { panic(err) } fmt.Println("Assembly:\n" + asm) // Emit object file contents as bytes (MIR -> LLVM IR -> object file) object, err := emitter.EmitObject() if err != nil { panic(err) } fmt.Printf("Object file:\n%v\n", object) // Emit executable file as "a.out". This is the final result we want! // It links the object file and runtime with a linker. // (MIR -> LLVM IR -> assembly -> object -> executable) if err := emitter.EmitExecutable("a.out"); err != nil { panic(err) }
Output:
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type EmitOptions ¶
type EmitOptions struct { // Optimization determines how many optimizations are added Optimization OptLevel // Triple represents target triple "{arch}-{vendor}-{sys}". Empty string means a default target // on your machine. // https://clang.llvm.org/docs/CrossCompilation.html#target-triple Triple string // Additional linker flags used at linking generated object files LinkerFlags string // DebugInfo determines to generate debug information or not. If true, debug information will // be added and you can debug the generated executable with debugger like an LLDB. DebugInfo bool }
EmitOptions represents emitter options to customize emitter behavior
type Emitter ¶
type Emitter struct { EmitOptions MIR *mir.Program Env *types.Env Source *locerr.Source Module llvm.Module Machine llvm.TargetMachine Disposed bool }
Emitter object to emit LLVM IR, object file, assembly or executable.
func NewEmitter ¶
func NewEmitter(prog *mir.Program, env *types.Env, src *locerr.Source, opts EmitOptions) (*Emitter, error)
NewEmitter creates new emitter object.
func (*Emitter) Dispose ¶
func (emitter *Emitter) Dispose()
Dispose does finalization for internal module and target machine. You need to call this with defer statement.
func (*Emitter) EmitExecutable ¶
EmitExecutable creates executable file with specified name. This is the final result of compilation!
func (*Emitter) EmitLLVMIR ¶
EmitLLVMIR returns LLVM IR as string.
func (*Emitter) EmitObject ¶
EmitObject returns object file contents as byte sequence.
func (*Emitter) RunOptimizationPasses ¶
func (emitter *Emitter) RunOptimizationPasses()
RunOptimizationPasses passes optimizations on generated LLVM IR module following specified optimization level.