Library for interacting with LLVM IR in pure Go.

llvm

Build Status Coverage Status Go Report Card go.dev reference

Library for interacting with LLVM IR in pure Go.

Introduction

Installation

go get -u github.com/llir/llvm/...

Versions

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

Users

Usage

Input example - Parse LLVM IR assembly

Example usage in GoDoc.

// This example parses an LLVM IR assembly file and pretty-prints the data types
// of the parsed module to standard output.
package main

import (
	"log"

	"github.com/kr/pretty"
	"github.com/llir/llvm/asm"
)

func main() {
	// Parse the LLVM IR assembly file `foo.ll`.
	m, err := asm.ParseFile("foo.ll")
	if err != nil {
		log.Fatalf("%+v", err)
	}
	// Pretty-print the data types of the parsed LLVM IR module.
	pretty.Println(m)
}

Output example - Produce LLVM IR assembly

Example usage in GoDoc.

// This example produces LLVM IR code equivalent to the following C code, which
// implements a pseudo-random number generator.
//
//    int abs(int x);
//
//    int seed = 0;
//
//    // ref: https://en.wikipedia.org/wiki/Linear_congruential_generator
//    //    a = 0x15A4E35
//    //    c = 1
//    int rand(void) {
//       seed = seed*0x15A4E35 + 1;
//       return abs(seed);
//    }
package main

import (
	"fmt"

	"github.com/llir/llvm/ir"
	"github.com/llir/llvm/ir/constant"
	"github.com/llir/llvm/ir/types"
)

func main() {
	// Create convenience types and constants.
	i32 := types.I32
	zero := constant.NewInt(i32, 0)
	a := constant.NewInt(i32, 0x15A4E35) // multiplier of the PRNG.
	c := constant.NewInt(i32, 1)         // increment of the PRNG.

	// Create a new LLVM IR module.
	m := ir.NewModule()

	// Create an external function declaration and append it to the module.
	//
	//    int abs(int x);
	abs := m.NewFunc("abs", i32, ir.NewParam("x", i32))

	// Create a global variable definition and append it to the module.
	//
	//    int seed = 0;
	seed := m.NewGlobalDef("seed", zero)

	// Create a function definition and append it to the module.
	//
	//    int rand(void) { ... }
	rand := m.NewFunc("rand", i32)

	// Create an unnamed entry basic block and append it to the `rand` function.
	entry := rand.NewBlock("")

	// Create instructions and append them to the entry basic block.
	tmp1 := entry.NewLoad(i32, seed)
	tmp2 := entry.NewMul(tmp1, a)
	tmp3 := entry.NewAdd(tmp2, c)
	entry.NewStore(tmp3, seed)
	tmp4 := entry.NewCall(abs, tmp3)
	entry.NewRet(tmp4)

	// Print the LLVM IR assembly of the module.
	fmt.Println(m)
}

Analysis example - Process LLVM IR

Example usage in GoDoc.

// This example program analyses an LLVM IR module to produce a callgraph in
// Graphviz DOT format.
package main

import (
	"fmt"
	"strings"

	"github.com/llir/llvm/asm"
	"github.com/llir/llvm/ir"
)

func main() {
	// Parse LLVM IR assembly file.
	m, err := asm.ParseFile("foo.ll")
	if err != nil {
		panic(err)
	}
	// Produce callgraph of module.
	callgraph := genCallgraph(m)
	// Output callgraph in Graphviz DOT format.
	fmt.Println(callgraph)
}

// genCallgraph returns the callgraph in Graphviz DOT format of the given LLVM
// IR module.
func genCallgraph(m *ir.Module) string {
	buf := &strings.Builder{}
	buf.WriteString("digraph {\n")
	// For each function of the module.
	for _, f := range m.Funcs {
		// Add caller node.
		caller := f.Ident()
		fmt.Fprintf(buf, "\t%q\n", caller)
		// For each basic block of the function.
		for _, block := range f.Blocks {
			// For each non-branching instruction of the basic block.
			for _, inst := range block.Insts {
				// Type switch on instruction to find call instructions.
				switch inst := inst.(type) {
				case *ir.InstCall:
					callee := inst.Callee.Ident()
					// Add edges from caller to callee.
					fmt.Fprintf(buf, "\t%q -> %q\n", caller, callee)
				}
			}
			// Terminator of basic block.
			switch term := block.Term.(type) {
			case *ir.TermRet:
				// do something.
				_ = term
			}
		}
	}
	buf.WriteString("}")
	return buf.String()
}

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.

Owner
Unofficial libraries for interacting with LLVM IR.
null
Comments
  • NewFloat does not generate the expected output

    NewFloat does not generate the expected output

    Hello all,

    I would first like to say thanks for an amazing library and I appreciate the hard work and dedication to support LLVM through Go.

    However, using the library in a project of my own to generate LLVM instructions for different variables, I ran into a problem where using NewFloat did not produce the expected results. I will demonstrate using a C program as a comparison.

    Using clang -S -emit-llvm main.c on the following program:

    Input C Program:

    int main() {
      float j = 1.1;
    
      return 0;
    }
    

    Produces the following store instruction for the float variable:

    store float 0x3FF19999A0000000, float* %2, align 4
    

    This is a 64 bit float with the last 28 bits dropped and converted to hex. (According to: http://lists.llvm.org/pipermail/llvm-dev/2011-April/039811.html)

    However, attempting to generate the same instruction using this library:

    mainBlock.NewStore(constant.NewFloat(value, types.Float), mainBlock.NewAlloca(types.Float))
    

    where value is the float literal 1.1.

    I obtained the following instruction:

    store float 1.1, float* %1
    

    Putting this into LLVM to generate assembly using:

    llc -march=x86 -o main.expr.assembly main.expr.ll
    

    Generates an error of:

    llc: main.expr.ll:6:14: error: floating point constant invalid for type
            store float 1.1, float* %1
    

    I can provide more information if needed, but a few questions:

    1. Is this expected behavior?
    2. Should this be expected behavior?
    3. If yes, why does this produce code that doesn't work?

    I can get it to work using types.Double, and if that is the solution then so be it for now, but I'd like to investigate if this is actually the expected output.

    Again, Thanks for the work and dedication

  • Formal Grammar of LLVM IR

    Formal Grammar of LLVM IR

    I've been unable to locate an official formal grammar for LLVM IR. If anyone has information about work in this direction, please point it out to me.

    To address this issue a formal grammar of LLVM IR will be created, prior to the implementation of the LLVM IR Assembly Language parser. This work was taking place at mewlang/llvm/asm/grammar (old link superseded by https://github.com/llir/llvm/blob/master/asm/internal/ll.bnf).

    Edit: For anyone who happen to stumble upon this issue. The latest version of the grammar is located in the llir/grammar repository, more specifically see ll.tm for an EBNF grammar for LLVM IR assembly.

  • Rewrite Git history to prune large 'old files'?

    Rewrite Git history to prune large 'old files'?

    Update summary, 23/11/2018: This repository currently requires ~10MiB of download, which isn't ideal considering the source is only a few hundreds of kilobytes. @mewmew and I propose to shrink it to ~800kiB, to give a faster "Go install" experience for anyone using the repository.

    The reason for the blowup is that there were some large test cases (including sqlite) which measure in the 10's of MiBs, and various other bits relating to parsing were also quite large. Those have now moved into other repositories in the llir organization, so we don't need to download those anymore if you just want to import llir.


    Original issue text.

    I just saw @mewmew's comment in ec48d546f5c3761fa2e8d1c0bec1a49865083072 but thought it would be easier to have a separate issue for discussion - the commit itself is very long so if I commented on the commit the discussion would be way down at the bottom!

    First, can I clarify the question - are you asking how to remove lots of old large assets from the history of the repository?

    If that is the question, the answer is, yes you can do it, but anyone who cloned the repository needs to know about it otherwise they might get in a mess, since it requires rewriting history. At least, that's the best I know. See github's guidance on the issue.

  • Requirements

    Requirements

    This issue summarizes the requirements of the LLVM packages, as specified by its intended use cases.

    The requirements of llgo as stated by @axw (in this issue) are as follows:

    As for llgo's requirements:

    • [x] in terms of using the LLVM API for generating code, it's mostly write-only via the builder API. Bitcode and IR reading is not important (at the moment?), but writing is; one or the other is required, but preferably both.
    • [x] llgo uses the DIBuilder API for generating debug metadata (DWARF, et al.). This could be built outside of the core (it's just a matter of creating metadata nodes in a particular format), just be aware that it's pretty finicky and easy to break.
    • [x] llgo needs to be able to look up target data (arch word size, alignment, etc.) from triples

    For the decompilation pipeline the llvm packages should be able to:

    • [x] represent the LLVM IR using Control Flow Graphs, where each node represents a BasicBlock.
    • [x] insert new nodes and rearrange existing ones.
  • `module.NewTypeDef` has unexpected side effects

    `module.NewTypeDef` has unexpected side effects

    The following code has unexpected side effects on the convenience types:

    m.NewTypeDef("hello", types.I64)
    

    Because NewTypeDef sets the type's name. Which is okay, but next time if I use types.I64 it will have name hello since, the convenience type is a pointer. To be honest, I don't really have an idea how to solve this. But it took me about 3 hours of debugging till I figured out why my i64 types called hello in LLVM IR.

  • Upcoming release of the llir/llvm project

    Upcoming release of the llir/llvm project

    This notice is intended to give a heads up for those using the llir/llvm library. The next release will include complete support for all intrinsics of the LLVM IR language. The work is currently in a flux, and to experiment with different API designs and simplify the parser logic and reduce the code duplication in the project, a new repo has been created during the experimental phase.

    https://github.com/mewmew/l

    At the current stage, the grammar is capable of parsing the entirety of the LLVM IR language, including specialized metadata nodes (#26).

    While working on this we will also try to take into consideration previous issues that have been identified with the parser (such as the handling of quoted strings #24).

    The llir/llvm/ir package will be extended to support the entire LLVM IR language; thus resolving #23 as linkage information will be present in the in-memory intermediate representation form.

    With the upcoming release, read support for all of the LLVM IR language concepts will have been implemented; thus resolving #15.

    Similarly; we will now have a grammar covering the entire LLVM IR language; thus resolving #2.

    With the addition of support for specialized metadata nodes, the second requirement of llgo will also be fully supported (#3); llgo uses the DIBuilder API for generating debug metadata (DWARF, et al.). This could be built outside of the core (it's just a matter of creating metadata nodes in a particular format), just be aware that it's pretty finicky and easy to break..

    For IR construction, a similar approach will be used as has been done before. Personally, we feel this approach has worked out well and has been quite pleasant to use. If anyone has input on their own experience using the API of the llir/llvm/ir package to construct LLVM IR, please let us know as that could help shape the upcoming release. As for llgo, the first requirement in terms of using the LLVM API for generating code, it's mostly write-only via the builder API. Bitcode and IR reading is not important (at the moment?), but writing is; one or the other is required, but preferably both. is satisfied by this API, and has been for a while. Although, now the llir/llvm/ir package will contain the support for the entire LLVM IR language, and now just a subset; thus the requirement should be satisfied in full.

    Module top-level information such as target triple and data layout has been and will continue to be recorded and maintained by the IR API, thus supporting the third requirement of llgo; llgo needs to be able to look up target data (arch word size, alignment, etc.) from triples.

    Generating C-shared library bindings compatible with the official C library of the LLVM project is an ambitious goal that is left for a future release (#12). Anyone specifically interested in this topic, feel free to get in touch with us or continue the discussion in the dedicated issue.

    Similarly, interaction with the Go runtime is targeted for a future release, and those with knowledge in this domain are happily invited to the discussion on what is needed and how to bring this about (#18).

    As for use-tracking and data analysis support (#19), more thought will be required to get a clean API. This is therefore targeted for a future release.

    So, to summarize, the upcoming release of the llir/llvm project will include read and write support for the entire LLVM IR language. In other words, it will be possible to parse arbitrary LLVM IR assembly files into an in-memory representation, aka the one defined in package llir/llvm/ir. And the in-memory IR representation will have support for the entire LLVM IR language, and can be converted back to LLVM IR assembly for interaction with other tools, such as the LLVM optimizer.

    Any feedback is welcome, so we know we're heading in the right direction.

    Cheerful regards, /u & i

  • irgen: starter instructions

    irgen: starter instructions

    According to language reference: phi:

    There must be no non-phi instructions between the start of a basic block and the PHI instructions: i.e. PHI instructions must be first in a basic block.

    and the following code can be compiled by llc:

    Loop:       ; Infinite loop that counts from 0 on up...
      %indvar = phi i32 [ 0, %LoopHeader ], [ %nextindvar, %Loop ]
      %indvar2 = phi i32 [ 0, %LoopHeader ], [ %nextindvar, %Loop ]
      %nextindvar = add i32 %indvar, 1
      br label %Loop
    

    That means phi is kind of starter instruction, and we can have several starter instructions which always be put at the beginning of the basic block, then we can avoid this kind of code:

    firstAppear := loopCtx.NewPhi(ir.NewIncoming(loopCtx.compileExpr(s.InitExpr), ctx.Block))
    step := loopCtx.compileExpr(s.Step)
    firstAppear.Incs = append(firstAppear.Incs, ir.NewIncoming(step, loopCtx.Block))
    

    We can do like this:

    step := loopCtx.compileExpr(s.Step)
    firstAppear := loopCtx.NewPhi(
        ir.NewIncoming(loopCtx.compileExpr(s.InitExpr), ctx.Block),
        ir.NewIncoming(step, loopCtx.Block))
    

    but won't break order we expected, and we would have new BasicBlock definition.

    type Block struct {
        Starters []Starter
    }
    
  • proposal: remove cached type of instructions

    proposal: remove cached type of instructions

    The proposal of this issue is to remove the result type cache of instructions in the ir package. Or at least investigate the benefits and drawbacks of removing the type cache. First, lets start with a background of what the type cache is, before getting into discussing if we should remove or keep it.

    For most value instructions (i.e. ir.Instructions implementing the value.Value interface), the type of the resulting value computed by the instruction is currently cached.

    To give an example, lets consider the InstXor instruction.

    type InstXor struct {
        // Name of local variable associated with the result.
        LocalIdent
        // Operands.
        X, Y value.Value // integer scalars or vectors
    
        // Type of result produced by the instruction.
        Typ types.Type
        // (optional) Metadata.
        Metadata
    }
    

    The result type is cached in the Typ field of the InstXor struct, and the cached type is computed as follows:

    From: https://github.com/llir/llvm/blob/b85ca175725ff59102503c86be2934bd3b9a99d3/ir/inst_bitwise.go#L328

    func (inst *InstXor) Type() types.Type {
    	// Cache type if not present.
    	if inst.Typ == nil {
    		inst.Typ = inst.X.Type()
    	}
    	return inst.Typ
    }
    

    If we were to remove the result type cache of InstXor, the Type() method would look as follows:

    func (inst *InstXor) Type() types.Type {
    	return inst.X.Type()
    }
    

    The result type cache was introduced primarily as a (potentially premature) optimization to avoid memory allocation when invoking the Type method for instructions that need to compute their result type.

    The issue with caching the result type is that if you were to modify a given IR and change say the type of a function parameter from i32 to i64, then this change would propagate correctly for all uses of the function parameter, but if the parameter was used as the parameter of an instruction (say an xor instruction), then the result type of the xor instruction would have a cached i32 type, ever after updating the type of the function parameter to i64. To recompute the type, a user of the ir package would then have to reset the Typ field of InstXor to nil, so that the next invocation of Type() would recompute the cache.

    This approach is indeed doable, although fragile and perhaps unintuitive, at least to users not firmly aware of the internal details of result type caching.

    For now, I've added a ResetTypes convenience function to the irutil package which resets the type cache of value instructions. This function is analogous to the ResetNames function which is used to reset the IDs of unnamed local identifiers in functions.

    While introducing the ResetTypes function makes handling reset of type caches less painful, there are still subtle bugs that may exist for users who does not know of its existence and thus forget to call ResetTypes where appropriate.

    I propose that we investigate removing cached result types of value instructions altogether. Potentially keeping one edge case where we cache the result of the getelementptr instruction, as essentially all this function does is to compute a result type. With this rationale, we may also wish to keep the cached type of call instructions and the invoke and callbr terminators, since they record information about the callee/invokee which may otherwise be unavailable.

    The potential downside of removing the type cache is that we may get more memory allocations if the Type() method is invoked a lot. However, if that ever were to become an issue, then tight loops invoking Type could introduce a purpose specific type cache should the need arise.

    The benefit of removing the type cache is a less confusing and more intuitive ir API.

    Food for thought.

    Cheers, Robin

    cc: @pwaller

  • reject non-pointer type for global

    reject non-pointer type for global

    If we define a new global

    module.NewGlobal(name, types.I8)
    

    it would cause an error that global variable reference must have pointer type

    Thus, I think this check is acceptable.

  • update llir/llvm to support 11.0

    update llir/llvm to support 11.0

    Current Status

    11.0 already released, reference: https://releases.llvm.org/download.html#11.0.0

    Changes

    Below from https://releases.llvm.org/11.0.0/docs/ReleaseNotes.html#id4

    • [ ] The callsite attribute vector-function-abi-variant has been added to describe the mapping between scalar functions and vector functions, to enable vectorization of call sites. The information provided by the attribute is interfaced via the API provided by the VFDatabase class. When scanning through the set of vector functions associated with a scalar call, the loop vectorizer now relies on VFDatabase, instead of TargetLibraryInfo.

    • [x] dereferenceable attributes and metadata on pointers no longer imply anything about the alignment of the pointer in question. Previously, some optimizations would make assumptions based on the type of the pointer. This behavior was undocumented. To preserve optimizations, frontends may need to be updated to generate appropriate align attributes and metadata.

    • [x] The DIModule metadata is extended to contain file and line number information. This information is used to represent Fortran modules debug info at IR level.

    • [x] LLVM IR now supports two distinct llvm::FixedVectorType and llvm::ScalableVectorType vector types, both derived from the base class llvm::VectorType. A number of algorithms dealing with IR vector types have been updated to make sure they work for both scalable and fixed vector types. Where possible, the code has been made generic to cover both cases using the base class. Specifically, places that were using the type unsigned to count the number of lanes of a vector are now using llvm::ElementCount. In places where uint64_t was used to denote the size in bits of a IR type we have partially migrated the codebase to using llvm::TypeSize.

    • [x] Branching on undef/poison is undefined behavior. It is needed for correctly analyzing value ranges based on branch conditions. This is consistent with MSan’s behavior as well.

    • [x] memset/memcpy/memmove can take undef/poison pointer(s) if the size to fill is zero.

    • [x] Passing undef/poison to a standard I/O library function call (printf/fputc/…) is undefined behavior. The new noundef attribute is attached to the functions’ arguments. The full list is available at llvm::inferLibFuncAttributes.

  • update llir/llvm to support 12.0

    update llir/llvm to support 12.0

    • 2021/03/11 https://www.phoronix.com/scan.php?page=news_item&px=LLVM-12.0-RC3-Released
    • 2021/04/01 https://www.phoronix.com/scan.php?page=news_item&px=LLVM-12.0-rc4-Released

    NOTE: send pull requests to branch llvm12.

    Changes to LLVM IR

    • Added the byref attribute to better represent argument passing for the amdgpu_kernel calling convention.
    • Added type parameter to the sret attribute to continue work on removing pointer element types.
    • The llvm.experimental.vector.reduce family of intrinsics has been renamed to drop the “experimental” from the name, reflecting their now fully supported status in the IR.
  • update llir/llvm to support LLVM 15.0

    update llir/llvm to support LLVM 15.0

    ref: #220.

    LLVM 15.0 is yet to be released (release candidate at: https://github.com/llvm/llvm-project/releases/tag/llvmorg-15.0.0-rc1)

    TODO: Once released, create a diff as follows:

    wget https://github.com/llvm/llvm-project/archive/llvmorg-14.0.6.tar.gz
    wget https://github.com/llvm/llvm-project/archive/llvmorg-15.0.0.tar.gz
    tar zxf llvmorg-14.0.6.tar.gz
    tar zxf llvmorg-15.0.0.tar.gz
    git diff -w llvm-project-llvmorg-14.0.6/llvm/lib/AsmParser llvm-project-llvmorg-15.0.0/llvm/lib/AsmParser > llvm14.diff
    git diff -w llvm-project-llvmorg-14.0.6/llvm/include/llvm/IR/Attributes.td llvm-project-llvmorg-15.0.0/llvm/include/llvm/IR/Attributes.td >> llvm15.diff
    
  • `sizeof`?

    `sizeof`?

    How do you call the sizeof function from LLVM? When C code using sizeof is generated, the code generated just has a constant. Is there a way to find the size of an object from LLVM?

  • irutil: add stdlib package for C standard library declarations

    irutil: add stdlib package for C standard library declarations

    As suggested in https://github.com/llir/llvm/pull/187#issuecomment-860148771:

    I would say the biggest difficulty was the C standard library - it would be super cool to have a stdlib package, with bindings to the standard library. In the compiler/builtins.go file I wrote out the function signatures for a bit of the stdlib, but it would be awesome to automatically have bindings to the whole C stdlib.

    Add a new irutil/stdlib package containing function (and global variable) declarations for interacting with the C standard library.

    We should consider automatically doing this, perhaps using the LLVM compiler to parse the C standard library headers and generating LLVM IR function (and global variable) declarations.

    Then, we could parse the LLVM IR output using llir/llvm/asm to get the llir/llvm/ir representation to interact with.

    Will require some experimentation to find what approach works well, and is easy to work with.

    Edit: related issues #22, #178, #180.

  • Ignore type-checking

    Ignore type-checking

    I don't know what type my function's return type will be until I have made all of the code up to the return statement. Most of the time this works, however, when I try to do recursion, I get errors due to mismatching types. In addition, these errors are panics, so I can't ignore them. Is there any way to ignore these types, and have it figure out the types when converting a module to a string (because, by then, the types will all be figured out)?

  • Precision loss during round-trip of `ppc_fp128` hexadecimal floating-point constants (double-double arithmetic)

    Precision loss during round-trip of `ppc_fp128` hexadecimal floating-point constants (double-double arithmetic)

    There is a known precision loss when parsing and printing LLVM IR assembly containing ppc_fp128 hexadecimal floating-point constants. This issue was identified by @dannypsnl, and the cause has been researched by @dannypsnl (see https://github.com/llir/llvm/issues/31#issuecomment-569254215) and @scottshotgg (see https://github.com/llir/llvm/issues/31#issuecomment-569358328).

    Below follows a proof of concept illustrating the precision loss for the ppc_fp128 constant 0xM400C0000000000300000000010000000. From https://github.com/llir/llvm/issues/31#issuecomment-569254215

    The problem happened, in this case, was because the sum of high and low is not exact, I create an example for it:

    package main
    
    import (
    	"fmt"
    	"math/big"
    	"math"
    )
    
    func main() {
    	precision := uint(106)
    	// Operate on numbers of different precision.
    	var z big.Float
    	x := big.NewFloat(math.Float64frombits(0x0000000010000000)).SetPrec(precision)
    	y := big.NewFloat(math.Float64frombits(0x400C000000000030)).SetPrec(precision)
    	z.SetPrec(precision)
    	z.Add(x, y)
    	fmt.Printf("x = %.10g (%s, prec = %d, acc = %s)\n", x, x.Text('p', 0), x.Prec(), x.Acc())
    	fmt.Printf("y = %.10g (%s, prec = %d, acc = %s)\n", y, y.Text('p', 0), y.Prec(), y.Acc())
    	fmt.Printf("z = %.10g (%s, prec = %d, acc = %s)\n", &z, z.Text('p', 0), z.Prec(), z.Acc())
    }
    // Result:
    // x = 1.326247369e-315 (0x.8p-1045, prec = 106, acc = Exact)
    // y = 3.5 (0x.e000000000018p+2, prec = 106, acc = Exact)
    // z = 3.5 (0x.e000000000018p+2, prec = 106, acc = Below)
    

    Link to failing test case: https://github.com/llir/llvm/blob/433f268c042117d5b3e4a0d12976e5fc35db8ba8/ir/constant/const_float_test.go#L16

    go test github.com/llir/llvm/ir/constant -run TestNewFloatFromStringForPPCFP128
    

    Changing the precision of the math/big.Float from 106 (which is the precision of double-double arithmetic) to 1048 fixes this issue and resolves the loss of precision (see https://github.com/llir/llvm/issues/31#issuecomment-569124567). However, simply changing the precision to 1048 does not seem like the right fix, since it will affect the results of future arithmetic on these constants and may result in more memory usage and loss of performance.

    Leaving this issue open in the hopes that someone has the expertise needed to figure out what is going wrong, and come up with a solution.

    ref to sister issue #31.

  • cloning functions

    cloning functions

    Is there a simple way how to clone functions?

    I'd like to duplicate a function like this:

    func duplicate(m *ir.Module, foo string) {
        for _, f := range m.Funcs {                                             
            if f.GlobalIdent.GlobalName == foo {                      
                DuplicateFunc(m, f, foo + "_v2")
            }                                              
        } 
    }
    

    And afterwards I'd do some minor changes in the function code.

Silotools: Tooling for interacting with SiLos

KONG SiLo USB NFC Tool Description Node script for verifying KONG SiLos via a NFC USB reader such as the ACR-122. Learn more about SiLos at KONG Cash

Dec 8, 2021
libFFM-gp: Pure Golang implemented library for FM (factorization machines)

libFFM-gp: Pure Golang implemented library for FM (factorization machines)

Oct 10, 2022
Library to work with MimeHeaders and another mime types. Library support wildcards and parameters.

Mime header Motivation This library created to help people to parse media type data, like headers, and store and match it. The main features of the li

Nov 9, 2022
Evolutionary optimization library for Go (genetic algorithm, partical swarm optimization, differential evolution)
Evolutionary optimization library for Go (genetic algorithm, partical swarm optimization, differential evolution)

eaopt is an evolutionary optimization library Table of Contents Changelog Example Background Features Usage General advice Genetic algorithms Overview

Dec 30, 2022
cross-platform, normalized battery information library

battery Cross-platform, normalized battery information library. Gives access to a system independent, typed battery state, capacity, charge and voltag

Dec 22, 2022
GoLang Library for Browser Capabilities Project

Browser Capabilities GoLang Project PHP has get_browser() function which tells what the user's browser is capable of. You can check original documenta

Sep 27, 2022
Go bindings for unarr (decompression library for RAR, TAR, ZIP and 7z archives)

go-unarr Golang bindings for the unarr library from sumatrapdf. unarr is a decompression library and CLI for RAR, TAR, ZIP and 7z archives. GoDoc See

Dec 29, 2022
Type-safe Prometheus metrics builder library for golang

gotoprom A Prometheus metrics builder gotoprom offers an easy to use declarative API with type-safe labels for building and using Prometheus metrics.

Dec 5, 2022
An easy to use, extensible health check library for Go applications.

Try browsing the code on Sourcegraph! Go Health Check An easy to use, extensible health check library for Go applications. Table of Contents Example M

Dec 30, 2022
An simple, easily extensible and concurrent health-check library for Go services
An simple, easily extensible and concurrent health-check library for Go services

Healthcheck A simple and extensible RESTful Healthcheck API implementation for Go services. Health provides an http.Handlefunc for use as a healthchec

Dec 30, 2022
Simple licensing library for golang.

license-key A simple licensing library in Golang, that generates license files containing arbitrary data. Note that this implementation is quite basic

Dec 24, 2022
atomic measures + Prometheus exposition library

About Atomic measures with Prometheus exposition for the Go programming language. This is free and unencumbered software released into the public doma

Sep 27, 2022
Morse Code Library in Go

morse Morse Code Library in Go Download and Use go get -u -v github.com/alwindoss/morse or dep ensure -add github.com/alwindoss/morse Sample Usage pac

Dec 30, 2022
A Golang library to manipulate strings according to the word parsing rules of the UNIX Bourne shell.

shellwords A Golang library to manipulate strings according to the word parsing rules of the UNIX Bourne shell. Installation go get github.com/Wing924

Sep 27, 2022
Notification library for gophers and their furry friends.
Notification library for gophers and their furry friends.

Shoutrrr Notification library for gophers and their furry friends. Heavily inspired by caronc/apprise. Quick Start As a package Using shoutrrr is easy

Jan 3, 2023
Go library for creating state machines
Go library for creating state machines

Stateless Create state machines and lightweight state machine-based workflows directly in Go code: phoneCall := stateless.NewStateMachine(stateOffHook

Jan 6, 2023
biogo is a bioinformatics library for Go
biogo is a bioinformatics library for Go

bíogo Installation $ go get github.com/biogo/biogo/... Overview bíogo is a bioinformatics library for the Go language. Getting help Help or simil

Jan 5, 2023
a cron library for go

cron Cron V3 has been released! To download the specific tagged release, run: go get github.com/robfig/cron/[email protected] Import it in your program as: im

Jan 1, 2023
Functional programming library for Go including a lazy list implementation and some of the most usual functions.

functional A functional programming library including a lazy list implementation and some of the most usual functions. import FP "github.com/tcard/fun

May 21, 2022