From 358e18b9de6b53b7b77752562d39be7acb7bb347 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sat, 20 Apr 2024 23:57:55 +0800 Subject: [PATCH 1/2] cl: _testdata/varinit --- cl/_testdata/varinit/in.go | 8 ++++++++ cl/_testdata/varinit/out.ll | 28 ++++++++++++++++++++++++++++ ssa/package.go | 13 ++++++++++++- 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 cl/_testdata/varinit/in.go create mode 100644 cl/_testdata/varinit/out.ll diff --git a/cl/_testdata/varinit/in.go b/cl/_testdata/varinit/in.go new file mode 100644 index 00000000..e3834d49 --- /dev/null +++ b/cl/_testdata/varinit/in.go @@ -0,0 +1,8 @@ +package main + +var a = 100 + +func main() { + a++ + _ = a +} diff --git a/cl/_testdata/varinit/out.ll b/cl/_testdata/varinit/out.ll new file mode 100644 index 00000000..4cb4f47f --- /dev/null +++ b/cl/_testdata/varinit/out.ll @@ -0,0 +1,28 @@ +; ModuleID = 'main' +source_filename = "main" + +@"init$guard" = external global ptr +@a = external global ptr + +define void @init() { +_llgo_0: + %0 = load i1, ptr @"init$guard", align 1 + br i1 %0, label %_llgo_2, label %_llgo_1 + +_llgo_1: ; preds = %_llgo_0 + store i1 true, ptr @"init$guard", align 1 + store i64 100, ptr @a, align 4 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +define void @main() { +_llgo_0: + %0 = load i64, ptr @a, align 4 + %1 = add i64 %0, 1 + store i64 %1, ptr @a, align 4 + %2 = load i64, ptr @a, align 4 + ret void +} diff --git a/ssa/package.go b/ssa/package.go index 3ba7dc3a..592df3a3 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -26,6 +26,7 @@ import ( // ----------------------------------------------------------------------------- +// InitFlags is a set of flags for initializing the LLVM library. type InitFlags int const ( @@ -43,6 +44,7 @@ const ( InitAll = InitAllTargets | InitAllAsmParsers | InitAllAsmPrinters | InitAllTargetInfos | InitAllTargetMCs ) +// Initialize initializes the LLVM library. func Initialize(flags InitFlags) { if flags&InitAllTargetInfos != 0 { llvm.InitializeAllTargetInfos() @@ -69,7 +71,6 @@ func Initialize(flags InitFlags) { // ----------------------------------------------------------------------------- -// A Program is a partial or complete Go program converted to SSA form. type aProgram struct { ctx llvm.Context typs typeutil.Map @@ -93,8 +94,10 @@ type aProgram struct { f64Ty Type } +// A Program presents a program. type Program = *aProgram +// NewProgram creates a new program. func NewProgram(target *Target) Program { if target == nil { target = &Target{} @@ -105,12 +108,14 @@ func NewProgram(target *Target) Program { return &aProgram{ctx: ctx, target: target, td: td} } +// NewPackage creates a new package. func (p Program) NewPackage(name, pkgPath string) Package { mod := p.ctx.NewModule(pkgPath) mod.Finalize() return &aPackage{mod, p} } +// Void returns void type. func (p Program) Void() Type { if p.voidTy == nil { p.voidTy = &aType{p.tyVoid(), types.Typ[types.Invalid], vkInvalid} @@ -118,6 +123,7 @@ func (p Program) Void() Type { return p.voidTy } +// Bool returns bool type. func (p Program) Bool() Type { if p.boolTy == nil { p.boolTy = p.llvmType(types.Typ[types.Bool]) @@ -125,6 +131,7 @@ func (p Program) Bool() Type { return p.boolTy } +// Int returns int type. func (p Program) Int() Type { if p.intTy == nil { p.intTy = p.llvmType(types.Typ[types.Int]) @@ -132,6 +139,7 @@ func (p Program) Int() Type { return p.intTy } +// Float64 returns float64 type. func (p Program) Float64() Type { if p.f64Ty == nil { p.f64Ty = p.llvmType(types.Typ[types.Float64]) @@ -160,18 +168,21 @@ func (p Package) NewConst(name string, val constant.Value) NamedConst { return &aNamedConst{} } +// NewVar creates a new global variable. func (p Package) NewVar(name string, typ types.Type) Global { t := p.prog.llvmType(typ) gbl := llvm.AddGlobal(p.mod, t.ll, name) return &aGlobal{Expr{gbl, t}} } +// NewFunc creates a new function. func (p Package) NewFunc(name string, sig *types.Signature) Function { t := p.prog.llvmSignature(sig) fn := llvm.AddFunction(p.mod, name, t.ll) return newFunction(fn, t, p.prog) } +// String returns a string representation of the package. func (p Package) String() string { return p.mod.String() } From 8f31e4a6d37a6dd96a8003c37005442f3793b9d9 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sun, 21 Apr 2024 00:22:39 +0800 Subject: [PATCH 2/2] global var init --- cl/_testdata/fncall/out.ll | 2 +- cl/_testdata/varinit/out.ll | 4 ++-- cl/compile.go | 1 + cl/compile_test.go | 6 +++--- ssa/decl.go | 8 +++++--- ssa/expr.go | 4 ++++ ssa/ssa_test.go | 8 ++++++-- 7 files changed, 22 insertions(+), 11 deletions(-) diff --git a/cl/_testdata/fncall/out.ll b/cl/_testdata/fncall/out.ll index 3f09abcd..6fa9a5b7 100644 --- a/cl/_testdata/fncall/out.ll +++ b/cl/_testdata/fncall/out.ll @@ -1,7 +1,7 @@ ; ModuleID = 'main' source_filename = "main" -@"init$guard" = external global ptr +@"init$guard" = global ptr null define void @init() { _llgo_0: diff --git a/cl/_testdata/varinit/out.ll b/cl/_testdata/varinit/out.ll index 4cb4f47f..aa7eaef4 100644 --- a/cl/_testdata/varinit/out.ll +++ b/cl/_testdata/varinit/out.ll @@ -1,8 +1,8 @@ ; ModuleID = 'main' source_filename = "main" -@"init$guard" = external global ptr -@a = external global ptr +@"init$guard" = global ptr null +@a = global ptr null define void @init() { _llgo_0: diff --git a/cl/compile.go b/cl/compile.go index bcffef30..eaf12345 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -53,6 +53,7 @@ func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) llssa.Global return g } g := pkg.NewVar(gbl.Name(), gbl.Type()) + g.Init(p.prog.Null(g.Type)) p.glbs[gbl] = g return g } diff --git a/cl/compile_test.go b/cl/compile_test.go index 54e9023e..d4810cd8 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -115,8 +115,8 @@ var a int `, `; ModuleID = 'foo' source_filename = "foo" -@"init$guard" = external global ptr -@a = external global ptr +@"init$guard" = global ptr null +@a = global ptr null define void @init() { _llgo_0: @@ -142,7 +142,7 @@ func fn(a int, b float64) int { `, `; ModuleID = 'foo' source_filename = "foo" -@"init$guard" = external global ptr +@"init$guard" = global ptr null define void @init() { _llgo_0: diff --git a/ssa/decl.go b/ssa/decl.go index 477afc30..878789f8 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -46,11 +46,13 @@ type aGlobal struct { // A Global is a named Value holding the address of a package-level // variable. -// -// Pos() returns the position of the ast.ValueSpec.Names[*] -// identifier. type Global = *aGlobal +// Init initializes the global variable with the given value. +func (g Global) Init(v Expr) { + g.impl.SetInitializer(v.impl) +} + // ----------------------------------------------------------------------------- // Function represents the parameters, results, and code of a function diff --git a/ssa/expr.go b/ssa/expr.go index e13821ad..67609313 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -43,6 +43,10 @@ func llvmValues(vals []Expr) []llvm.Value { // ----------------------------------------------------------------------------- +func (p Program) Null(t Type) Expr { + return Expr{llvm.ConstNull(t.ll), t} +} + func (p Program) BoolVal(v bool) Expr { t := p.Bool() var bv uint64 diff --git a/ssa/ssa_test.go b/ssa/ssa_test.go index 98f01bf0..3fe9f1cf 100644 --- a/ssa/ssa_test.go +++ b/ssa/ssa_test.go @@ -37,11 +37,15 @@ func assertPkg(t *testing.T, p Package, expected string) { func TestVar(t *testing.T) { prog := NewProgram(nil) pkg := prog.NewPackage("bar", "foo/bar") - pkg.NewVar("a", types.Typ[types.Int]) + a := pkg.NewVar("a", types.Typ[types.Int]) + a.Init(prog.Val(100)) + b := pkg.NewVar("b", types.Typ[types.Int]) + b.Init(a.Expr) assertPkg(t, pkg, `; ModuleID = 'foo/bar' source_filename = "foo/bar" -@a = external global i64 +@a = global i64 100 +@b = global i64 @a `) }