github.com/llir/llvm@v0.3.6/README.md (about)

     1  # llvm
     2  
     3  [![Build Status](https://github.com/llir/llvm/workflows/Go/badge.svg?branch=master)](https://github.com/llir/llvm/actions/workflows/go.yml)
     4  [![Coverage Status](https://coveralls.io/repos/github/llir/llvm/badge.svg?branch=master)](https://coveralls.io/github/llir/llvm?branch=master)
     5  [![Go Report Card](https://goreportcard.com/badge/github.com/llir/llvm)](https://goreportcard.com/report/github.com/llir/llvm)
     6  [![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/github.com/llir/llvm)
     7  
     8  Library for interacting with [LLVM IR](http://llvm.org/docs/LangRef.html) in pure Go.
     9  
    10  ## Introduction
    11  
    12  * [Introductory blog post "LLVM IR and Go"](https://blog.gopheracademy.com/advent-2018/llvm-ir-and-go/)
    13  * [Our Document](https://llir.github.io/document/)
    14  
    15  ## Installation
    16  
    17  ```bash
    18  go get -u github.com/llir/llvm/...
    19  ```
    20  
    21  ## Versions
    22  
    23  Map between `llir/llvm` tagged releases and LLVM release versions.
    24  
    25  * [llir/llvm v0.3.6](https://github.com/llir/llvm/tree/v0.3.6): LLVM 14.0
    26  * [llir/llvm v0.3.5](https://github.com/llir/llvm/tree/v0.3.5): LLVM 13.0
    27  * [llir/llvm v0.3.4](https://github.com/llir/llvm/tree/v0.3.4): LLVM 12.0
    28  * [llir/llvm v0.3.3](https://github.com/llir/llvm/tree/v0.3.3): LLVM 11.0
    29  * [llir/llvm v0.3.2](https://github.com/llir/llvm/tree/v0.3.2): LLVM 10.0
    30  * [llir/llvm v0.3.0](https://github.com/llir/llvm/tree/v0.3.0): LLVM 9.0
    31  
    32  ## Users
    33  
    34  * [decomp](https://github.com/decomp/decomp): LLVM IR to Go decompiler by [@decomp](https://github.com/decomp).
    35  * [geode](https://github.com/geode-lang/geode): Geode to LLVM IR compiler by [@nickwanninger](https://github.com/nickwanninger).
    36  * [leaven](https://github.com/andybalholm/leaven): LLVM IR to Go decompiler by [@andybalholm](https://github.com/andybalholm).
    37  * [slate](https://github.com/nektro/slate): Slate to LLVM IR compiler by [@nektro](https://github.com/nektro).
    38  * [tre](https://github.com/zegl/tre): Go to LLVM IR compiler by [@zegl](https://github.com/zegl).
    39  * [uc](https://github.com/mewmew/uc): µC to LLVM IR compiler by [@sangisos](https://github.com/sangisos) and [@mewmew](https://github.com/mewmew).
    40  * [B++](https://github.com/Nv7-Github/Bpp): B++ to LLVM IR compiler by [@Nv7-Github](https://github.com/Nv7-Github).
    41  
    42  ## Usage
    43  
    44  ### Input example - Parse LLVM IR assembly
    45  
    46  [Example usage in GoDoc](https://pkg.go.dev/github.com/llir/llvm/asm#example-package).
    47  
    48  ```go
    49  // This example parses an LLVM IR assembly file and pretty-prints the data types
    50  // of the parsed module to standard output.
    51  package main
    52  
    53  import (
    54  	"log"
    55  
    56  	"github.com/kr/pretty"
    57  	"github.com/llir/llvm/asm"
    58  )
    59  
    60  func main() {
    61  	// Parse the LLVM IR assembly file `foo.ll`.
    62  	m, err := asm.ParseFile("foo.ll")
    63  	if err != nil {
    64  		log.Fatalf("%+v", err)
    65  	}
    66  	// Pretty-print the data types of the parsed LLVM IR module.
    67  	pretty.Println(m)
    68  }
    69  ```
    70  
    71  ### Output example - Produce LLVM IR assembly
    72  
    73  [Example usage in GoDoc](https://pkg.go.dev/github.com/llir/llvm/ir#example-package).
    74  
    75  ```go
    76  // This example produces LLVM IR code equivalent to the following C code, which
    77  // implements a pseudo-random number generator.
    78  //
    79  //    int abs(int x);
    80  //
    81  //    int seed = 0;
    82  //
    83  //    // ref: https://en.wikipedia.org/wiki/Linear_congruential_generator
    84  //    //    a = 0x15A4E35
    85  //    //    c = 1
    86  //    int rand(void) {
    87  //       seed = seed*0x15A4E35 + 1;
    88  //       return abs(seed);
    89  //    }
    90  package main
    91  
    92  import (
    93  	"fmt"
    94  
    95  	"github.com/llir/llvm/ir"
    96  	"github.com/llir/llvm/ir/constant"
    97  	"github.com/llir/llvm/ir/types"
    98  )
    99  
   100  func main() {
   101  	// Create convenience types and constants.
   102  	i32 := types.I32
   103  	zero := constant.NewInt(i32, 0)
   104  	a := constant.NewInt(i32, 0x15A4E35) // multiplier of the PRNG.
   105  	c := constant.NewInt(i32, 1)         // increment of the PRNG.
   106  
   107  	// Create a new LLVM IR module.
   108  	m := ir.NewModule()
   109  
   110  	// Create an external function declaration and append it to the module.
   111  	//
   112  	//    int abs(int x);
   113  	abs := m.NewFunc("abs", i32, ir.NewParam("x", i32))
   114  
   115  	// Create a global variable definition and append it to the module.
   116  	//
   117  	//    int seed = 0;
   118  	seed := m.NewGlobalDef("seed", zero)
   119  
   120  	// Create a function definition and append it to the module.
   121  	//
   122  	//    int rand(void) { ... }
   123  	rand := m.NewFunc("rand", i32)
   124  
   125  	// Create an unnamed entry basic block and append it to the `rand` function.
   126  	entry := rand.NewBlock("")
   127  
   128  	// Create instructions and append them to the entry basic block.
   129  	tmp1 := entry.NewLoad(i32, seed)
   130  	tmp2 := entry.NewMul(tmp1, a)
   131  	tmp3 := entry.NewAdd(tmp2, c)
   132  	entry.NewStore(tmp3, seed)
   133  	tmp4 := entry.NewCall(abs, tmp3)
   134  	entry.NewRet(tmp4)
   135  
   136  	// Print the LLVM IR assembly of the module.
   137  	fmt.Println(m)
   138  }
   139  ```
   140  
   141  ### Analysis example - Process LLVM IR
   142  
   143  [Example usage in GoDoc](https://pkg.go.dev/github.com/llir/llvm/ir#example-package--Callgraph).
   144  
   145  ```go
   146  // This example program analyses an LLVM IR module to produce a callgraph in
   147  // Graphviz DOT format.
   148  package main
   149  
   150  import (
   151  	"fmt"
   152  	"strings"
   153  
   154  	"github.com/llir/llvm/asm"
   155  	"github.com/llir/llvm/ir"
   156  )
   157  
   158  func main() {
   159  	// Parse LLVM IR assembly file.
   160  	m, err := asm.ParseFile("foo.ll")
   161  	if err != nil {
   162  		panic(err)
   163  	}
   164  	// Produce callgraph of module.
   165  	callgraph := genCallgraph(m)
   166  	// Output callgraph in Graphviz DOT format.
   167  	fmt.Println(callgraph)
   168  }
   169  
   170  // genCallgraph returns the callgraph in Graphviz DOT format of the given LLVM
   171  // IR module.
   172  func genCallgraph(m *ir.Module) string {
   173  	buf := &strings.Builder{}
   174  	buf.WriteString("digraph {\n")
   175  	// For each function of the module.
   176  	for _, f := range m.Funcs {
   177  		// Add caller node.
   178  		caller := f.Ident()
   179  		fmt.Fprintf(buf, "\t%q\n", caller)
   180  		// For each basic block of the function.
   181  		for _, block := range f.Blocks {
   182  			// For each non-branching instruction of the basic block.
   183  			for _, inst := range block.Insts {
   184  				// Type switch on instruction to find call instructions.
   185  				switch inst := inst.(type) {
   186  				case *ir.InstCall:
   187  					callee := inst.Callee.Ident()
   188  					// Add edges from caller to callee.
   189  					fmt.Fprintf(buf, "\t%q -> %q\n", caller, callee)
   190  				}
   191  			}
   192  			// Terminator of basic block.
   193  			switch term := block.Term.(type) {
   194  			case *ir.TermRet:
   195  				// do something.
   196  				_ = term
   197  			}
   198  		}
   199  	}
   200  	buf.WriteString("}")
   201  	return buf.String()
   202  }
   203  ```
   204  
   205  ## License
   206  
   207  The `llir/llvm` project is dual-licensed to the [public domain](UNLICENSE) and under a [zero-clause BSD license](LICENSE). You may choose either license to govern your use of `llir/llvm`.