Closed ghost closed 8 months ago
Hi @dequeb,
Here's an example to get you started. It's not identical, but showcases how to get external global variables and add parameter attributes to the LLVM IR.
In general, remember to take a look at the ir/types and ir/enum packages, in addition to ir.
Note, however that llir/llvm
does not yet support opaque pointers (see https://github.com/llir/llvm/issues/222#issuecomment-1202279183).
package main
import (
"fmt"
"github.com/llir/llvm/ir"
"github.com/llir/llvm/ir/constant"
"github.com/llir/llvm/ir/enum"
"github.com/llir/llvm/ir/types"
)
func main() {
i8 := types.I8
i32 := types.I32
i64 := types.I64
ptrType := types.NewPointer(i8)
m := ir.NewModule()
// %struct.GarbageCollector type definition
garbageCollectorType := types.NewStruct(ptrType, i8, ptrType, i64)
m.NewTypeDef("struct.GarbageCollector", garbageCollectorType)
// gc global
gcGlobal := ir.NewGlobal("gc", garbageCollectorType)
gcGlobal.Linkage = enum.LinkageExternal
gcGlobal.Align = 8
garbageCollectorPtrType := types.NewPointer(garbageCollectorType)
// gc_start
gcStartParam1 := ir.NewParam("param1", garbageCollectorPtrType)
gcStartParam1.Attrs = append(gcStartParam1.Attrs, enum.ParamAttrNoUndef)
gcStartParam2 := ir.NewParam("param2", ptrType)
gcStartParam2.Attrs = append(gcStartParam2.Attrs, enum.ParamAttrNoUndef)
gcStart := m.NewFunc("gc_start", types.Void, gcStartParam1, gcStartParam2)
// gc_stop
gcStopParam1 := ir.NewParam("param1", ptrType)
gcStopParam1.Attrs = append(gcStopParam1.Attrs, enum.ParamAttrNoUndef)
gcStop := m.NewFunc("gc_stop", i64, gcStopParam1)
// gc_malloc
gcMallocParam1 := ir.NewParam("param1", ptrType)
gcMallocParam1.Attrs = append(gcMallocParam1.Attrs, enum.ParamAttrNoUndef)
gcMallocParam2 := ir.NewParam("param2", ptrType)
gcMallocParam2.Attrs = append(gcMallocParam2.Attrs, enum.ParamAttrNoUndef)
gcMalloc := m.NewFunc("gc_malloc", ptrType, gcMallocParam1, gcMallocParam2)
_ = gcStart
_ = gcStop
_ = gcMalloc
// main function
argcParam := ir.NewParam("argc", i32)
argvType := types.NewPointer(types.NewPointer(i8))
argvParam := ir.NewParam("argv", argvType)
main := m.NewFunc("main", i32, argcParam, argvParam)
entry := main.NewBlock("")
localVar := entry.NewAlloca(i32)
entry.NewStore(argcParam, localVar)
entry.NewCall(gcStart, gcGlobal, localVar)
entry.NewCall(gcStop, gcGlobal)
zero := constant.NewInt(i32, 0)
entry.NewRet(zero)
// print LLVM IR module
fmt.Println(m)
}
Output LLVM IR:
%struct.GarbageCollector = type { i8*, i8, i8*, i64 }
declare void @gc_start(%struct.GarbageCollector* noundef %param1, i8* noundef %param2)
declare i64 @gc_stop(i8* noundef %param1)
declare i8* @gc_malloc(i8* noundef %param1, i8* noundef %param2)
define i32 @main(i32 %argc, i8** %argv) {
0:
%1 = alloca i32
store i32 %argc, i32* %1
call void @gc_start(%struct.GarbageCollector* @gc, i32* %1)
%2 = call i64 @gc_stop(%struct.GarbageCollector* @gc)
ret i32 0
}
Cheers, Robin
Based on my test with
clang
I need to generate the following code :I don't see how to generate
structure
,external
,noundef
andptr
. Do we have alternative to these in the current library or are they missing features? I so, could they be added? How could I help?