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)
}
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.