Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to create malloc in llir/llvm? #52

Closed
dannypsnl opened this issue Dec 6, 2018 · 6 comments
Closed

How to create malloc in llir/llvm? #52

dannypsnl opened this issue Dec 6, 2018 · 6 comments
Milestone

Comments

@dannypsnl
Copy link
Member

dannypsnl commented Dec 6, 2018

Basically what I need is something like this:
https://godoc.org/llvm.org/llvm/bindings/go/llvm#Builder.CreateMalloc

In my case, I'm trying to create a currying function call, it would need to store parameters in a structure

@pwaller
Copy link
Member

pwaller commented Dec 6, 2018

I'm afraid the answer is likely not what you're looking for, but at the moment to the best of my knowledge you need to implement something like this, which is effectively what happens in the bindings you linked to. That's what's going on under the hood:

https://github.com/llvm-mirror/llvm/blob/42f44e618270417470aada33ccecade8eb196b6f/lib/IR/Instructions.cpp#L432-L512

The llir/llvm package doesn't have much notion of 'runtime' at the moment, and malloc is essentially a runtime function call.

I can imagine that at some point llir may have an IR building package somewhere that would help you do this sort of thing. I'm unsure at this point where it would live. @mewmew may also have some opinions on this.

@zegl
Copy link

zegl commented Dec 6, 2018

I don't know if this answers your question, but:

I've been using the glibc malloc like this in tre. I'm then able to use the malloc function like this.

mallocFunc := module.NewFunc("malloc",
    types.NewPointer(types.I8),
    ir.NewParam("", types.I64),
)

mallocatedSpaceRaw := block.NewCall(mallocFunc, constant.NewInt(types.I64, structType.Size()))
alloc := block.NewBitCast(mallocatedSpaceRaw, types.NewPointer(structType.LLVM()))

@dannypsnl
Copy link
Member Author

Thanks @zegl and @pwaller, I think use glibc can solve my problem currently

@mewmew
Copy link
Member

mewmew commented Dec 6, 2018

Perfect! It's brilliant to have a quick answer to this. I didn't know it myself. Closing this issue as it seem to have been resolved.

Cheers,
/u

@mewmew mewmew closed this as completed Dec 6, 2018
@mewmew
Copy link
Member

mewmew commented Dec 6, 2018

I can imagine that at some point llir may have an IR building package somewhere that would help you do this sort of thing. I'm unsure at this point where it would live. @mewmew may also have some opinions on this.

Indeed. A package with IR builder like functionality will most likely live somewhere in llir in the future. Currently we focus on getting the core just right, giving full support for the various language constructs of LLVM IR.

When it comes to the IR builder package, we are essentially collecting experiences from any Gopher playing with LLVM IR to build compilers and other tools and libraries. It may very well be that common practices emerge that are similar but also unlike those used in the C++ builder API, and that is what we want. To see what such an API may look, if re-designed for the Go ecosystem.

The predominant approach today, seem to be to create a structure which tracks the context of the IR generator/builder (i.e. current function being generated, current basic block, etc); e.g. as is done by the Compiler type of tre:

From https://github.com/zegl/tre/blob/f12f93021cbd5344ceb4f204997b95ec45d1db9d/compiler/compiler/compiler.go#L41:

type Compiler struct {
	module *ir.Module
	...
	contextBlock *ir.BasicBlock
	...
}

A similar approach it taken by uc, which uses irgen.Function to keep the context of functions being generated:

From https://github.com/mewmew/uc/blob/0c45fe07f88905b95c012dba4acd700a258d674d/irgen/irgen.go#L49:

// A Function represents an LLVM IR function generator.
type Function struct {
	// Function being generated.
	*ir.Function
	// Current basic block being generated.
	curBlock *BasicBlock
	...

As we gain more experience using llir to develop compilers and analysis tools, we will also see what approaches for IR generation look clean, are general and powerful. We'll probably iterate a few times before declaring an "official" llir irgen / builder package, but we'll definitely look for good examples to point to and learn from.

At least, those are the thoughts on the top of my head. Something similar would probably happen for runtime specific functionality, e.g. interaction with garbage collection, etc; as further tracked by #18.

@mewmew
Copy link
Member

mewmew commented Dec 6, 2018

@zegl Cool, didn't know tre had escape analysis :)

@mewmew mewmew added this to the v0.3 milestone Dec 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants