项目作者: llir

项目描述 :
Library for interacting with LLVM IR in pure Go.
高级语言: Go
项目地址: git://github.com/llir/llvm.git
创建时间: 2014-09-19T11:18:44Z
项目社区:https://github.com/llir/llvm

开源协议:Other

下载


llvm

Build Status
Coverage Status
Go Report Card
go.dev reference

Library for interacting with LLVM IR in pure Go.

Introduction

Installation

  1. go get github.com/llir/llvm/...

Versions

Map between llir/llvm tagged releases and LLVM release versions.

Users

Usage

Input example, parsing LLVM IR assembly

Example usage in GoDoc.

  1. // This example parses an LLVM IR assembly file and pretty-prints the data types
  2. // of the parsed module to standard output.
  3. package main
  4. import (
  5. "log"
  6. "github.com/kr/pretty"
  7. "github.com/llir/llvm/asm"
  8. )
  9. func main() {
  10. // Parse the LLVM IR assembly file `foo.ll`.
  11. m, err := asm.ParseFile("foo.ll")
  12. if err != nil {
  13. log.Fatalf("%+v", err)
  14. }
  15. // Pretty-print the data types of the parsed LLVM IR module.
  16. pretty.Println(m)
  17. }

Output examples, producing LLVM IR assembly

Hello, World

Example usage in GoDoc.

  1. // This example produces LLVM IR generating "Hello, World" output.
  2. package main
  3. import (
  4. "fmt"
  5. "github.com/llir/llvm/ir"
  6. "github.com/llir/llvm/ir/constant"
  7. "github.com/llir/llvm/ir/types"
  8. )
  9. func main() {
  10. // Create a new LLVM IR module.
  11. m := ir.NewModule()
  12. hello := constant.NewCharArrayFromString("Hello, world!\n\x00")
  13. str := m.NewGlobalDef("str", hello)
  14. // Add external function declaration of puts.
  15. puts := m.NewFunc("puts", types.I32, ir.NewParam("", types.NewPointer(types.I8)))
  16. main := m.NewFunc("main", types.I32)
  17. entry := main.NewBlock("")
  18. // Cast *[15]i8 to *i8.
  19. zero := constant.NewInt(types.I64, 0)
  20. gep := constant.NewGetElementPtr(hello.Typ, str, zero, zero)
  21. entry.NewCall(puts, gep)
  22. entry.NewRet(constant.NewInt(types.I32, 0))
  23. fmt.Println(m)
  24. }

Pseudo Random-Number Generator

Example usage in GoDoc.

  1. // This example produces LLVM IR code equivalent to the following C code, which
  2. // implements a pseudo-random number generator.
  3. //
  4. // int abs(int x);
  5. //
  6. // int seed = 0;
  7. //
  8. // // ref: https://en.wikipedia.org/wiki/Linear_congruential_generator
  9. // // a = 0x15A4E35
  10. // // c = 1
  11. // int rand(void) {
  12. // seed = seed*0x15A4E35 + 1;
  13. // return abs(seed);
  14. // }
  15. package main
  16. import (
  17. "fmt"
  18. "github.com/llir/llvm/ir"
  19. "github.com/llir/llvm/ir/constant"
  20. "github.com/llir/llvm/ir/types"
  21. )
  22. func main() {
  23. // Create convenience types and constants.
  24. i32 := types.I32
  25. zero := constant.NewInt(i32, 0)
  26. a := constant.NewInt(i32, 0x15A4E35) // multiplier of the PRNG.
  27. c := constant.NewInt(i32, 1) // increment of the PRNG.
  28. // Create a new LLVM IR module.
  29. m := ir.NewModule()
  30. // Create an external function declaration and append it to the module.
  31. //
  32. // int abs(int x);
  33. abs := m.NewFunc("abs", i32, ir.NewParam("x", i32))
  34. // Create a global variable definition and append it to the module.
  35. //
  36. // int seed = 0;
  37. seed := m.NewGlobalDef("seed", zero)
  38. // Create a function definition and append it to the module.
  39. //
  40. // int rand(void) { ... }
  41. rand := m.NewFunc("rand", i32)
  42. // Create an unnamed entry basic block and append it to the `rand` function.
  43. entry := rand.NewBlock("")
  44. // Create instructions and append them to the entry basic block.
  45. tmp1 := entry.NewLoad(i32, seed)
  46. tmp2 := entry.NewMul(tmp1, a)
  47. tmp3 := entry.NewAdd(tmp2, c)
  48. entry.NewStore(tmp3, seed)
  49. tmp4 := entry.NewCall(abs, tmp3)
  50. entry.NewRet(tmp4)
  51. // Print the LLVM IR assembly of the module.
  52. fmt.Println(m)
  53. }

Analysis example, processing LLVM IR

Example usage in GoDoc.

  1. // This example program analyses an LLVM IR module to produce a callgraph in
  2. // Graphviz DOT format.
  3. package main
  4. import (
  5. "fmt"
  6. "strings"
  7. "github.com/llir/llvm/asm"
  8. "github.com/llir/llvm/ir"
  9. )
  10. func main() {
  11. // Parse LLVM IR assembly file.
  12. m, err := asm.ParseFile("foo.ll")
  13. if err != nil {
  14. panic(err)
  15. }
  16. // Produce callgraph of module.
  17. callgraph := genCallgraph(m)
  18. // Output callgraph in Graphviz DOT format.
  19. fmt.Println(callgraph)
  20. }
  21. // genCallgraph returns the callgraph in Graphviz DOT format of the given LLVM
  22. // IR module.
  23. func genCallgraph(m *ir.Module) string {
  24. buf := &strings.Builder{}
  25. buf.WriteString("digraph {\n")
  26. // For each function of the module.
  27. for _, f := range m.Funcs {
  28. // Add caller node.
  29. caller := f.Ident()
  30. fmt.Fprintf(buf, "\t%q\n", caller)
  31. // For each basic block of the function.
  32. for _, block := range f.Blocks {
  33. // For each non-branching instruction of the basic block.
  34. for _, inst := range block.Insts {
  35. // Type switch on instruction to find call instructions.
  36. switch inst := inst.(type) {
  37. case *ir.InstCall:
  38. callee := inst.Callee.Ident()
  39. // Add edges from caller to callee.
  40. fmt.Fprintf(buf, "\t%q -> %q\n", caller, callee)
  41. }
  42. }
  43. // Terminator of basic block.
  44. switch term := block.Term.(type) {
  45. case *ir.TermRet:
  46. // do something.
  47. _ = term
  48. }
  49. }
  50. }
  51. buf.WriteString("}")
  52. return buf.String()
  53. }

License

The llir/llvm project is dual-licensed to the public domain and under a zero-clause BSD license. You may choose either license to govern your use of llir/llvm.