@@ -1,7 +1,7 @@
|
|||||||
; ModuleID = 'main'
|
; ModuleID = 'main'
|
||||||
source_filename = "main"
|
source_filename = "main"
|
||||||
|
|
||||||
@"init$guard" = external global ptr
|
@"init$guard" = global ptr null
|
||||||
|
|
||||||
define void @init() {
|
define void @init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
|||||||
8
cl/_testdata/varinit/in.go
Normal file
8
cl/_testdata/varinit/in.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
var a = 100
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a++
|
||||||
|
_ = a
|
||||||
|
}
|
||||||
28
cl/_testdata/varinit/out.ll
Normal file
28
cl/_testdata/varinit/out.ll
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"init$guard" = global ptr null
|
||||||
|
@a = global ptr null
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -53,6 +53,7 @@ func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) llssa.Global
|
|||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
g := pkg.NewVar(gbl.Name(), gbl.Type())
|
g := pkg.NewVar(gbl.Name(), gbl.Type())
|
||||||
|
g.Init(p.prog.Null(g.Type))
|
||||||
p.glbs[gbl] = g
|
p.glbs[gbl] = g
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,8 +115,8 @@ var a int
|
|||||||
`, `; ModuleID = 'foo'
|
`, `; ModuleID = 'foo'
|
||||||
source_filename = "foo"
|
source_filename = "foo"
|
||||||
|
|
||||||
@"init$guard" = external global ptr
|
@"init$guard" = global ptr null
|
||||||
@a = external global ptr
|
@a = global ptr null
|
||||||
|
|
||||||
define void @init() {
|
define void @init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
@@ -142,7 +142,7 @@ func fn(a int, b float64) int {
|
|||||||
`, `; ModuleID = 'foo'
|
`, `; ModuleID = 'foo'
|
||||||
source_filename = "foo"
|
source_filename = "foo"
|
||||||
|
|
||||||
@"init$guard" = external global ptr
|
@"init$guard" = global ptr null
|
||||||
|
|
||||||
define void @init() {
|
define void @init() {
|
||||||
_llgo_0:
|
_llgo_0:
|
||||||
|
|||||||
@@ -46,11 +46,13 @@ type aGlobal struct {
|
|||||||
|
|
||||||
// A Global is a named Value holding the address of a package-level
|
// A Global is a named Value holding the address of a package-level
|
||||||
// variable.
|
// variable.
|
||||||
//
|
|
||||||
// Pos() returns the position of the ast.ValueSpec.Names[*]
|
|
||||||
// identifier.
|
|
||||||
type Global = *aGlobal
|
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
|
// Function represents the parameters, results, and code of a function
|
||||||
|
|||||||
@@ -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 {
|
func (p Program) BoolVal(v bool) Expr {
|
||||||
t := p.Bool()
|
t := p.Bool()
|
||||||
var bv uint64
|
var bv uint64
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// InitFlags is a set of flags for initializing the LLVM library.
|
||||||
type InitFlags int
|
type InitFlags int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -43,6 +44,7 @@ const (
|
|||||||
InitAll = InitAllTargets | InitAllAsmParsers | InitAllAsmPrinters | InitAllTargetInfos | InitAllTargetMCs
|
InitAll = InitAllTargets | InitAllAsmParsers | InitAllAsmPrinters | InitAllTargetInfos | InitAllTargetMCs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Initialize initializes the LLVM library.
|
||||||
func Initialize(flags InitFlags) {
|
func Initialize(flags InitFlags) {
|
||||||
if flags&InitAllTargetInfos != 0 {
|
if flags&InitAllTargetInfos != 0 {
|
||||||
llvm.InitializeAllTargetInfos()
|
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 {
|
type aProgram struct {
|
||||||
ctx llvm.Context
|
ctx llvm.Context
|
||||||
typs typeutil.Map
|
typs typeutil.Map
|
||||||
@@ -93,8 +94,10 @@ type aProgram struct {
|
|||||||
f64Ty Type
|
f64Ty Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A Program presents a program.
|
||||||
type Program = *aProgram
|
type Program = *aProgram
|
||||||
|
|
||||||
|
// NewProgram creates a new program.
|
||||||
func NewProgram(target *Target) Program {
|
func NewProgram(target *Target) Program {
|
||||||
if target == nil {
|
if target == nil {
|
||||||
target = &Target{}
|
target = &Target{}
|
||||||
@@ -105,12 +108,14 @@ func NewProgram(target *Target) Program {
|
|||||||
return &aProgram{ctx: ctx, target: target, td: td}
|
return &aProgram{ctx: ctx, target: target, td: td}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewPackage creates a new package.
|
||||||
func (p Program) NewPackage(name, pkgPath string) Package {
|
func (p Program) NewPackage(name, pkgPath string) Package {
|
||||||
mod := p.ctx.NewModule(pkgPath)
|
mod := p.ctx.NewModule(pkgPath)
|
||||||
mod.Finalize()
|
mod.Finalize()
|
||||||
return &aPackage{mod, p}
|
return &aPackage{mod, p}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Void returns void type.
|
||||||
func (p Program) Void() Type {
|
func (p Program) Void() Type {
|
||||||
if p.voidTy == nil {
|
if p.voidTy == nil {
|
||||||
p.voidTy = &aType{p.tyVoid(), types.Typ[types.Invalid], vkInvalid}
|
p.voidTy = &aType{p.tyVoid(), types.Typ[types.Invalid], vkInvalid}
|
||||||
@@ -118,6 +123,7 @@ func (p Program) Void() Type {
|
|||||||
return p.voidTy
|
return p.voidTy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bool returns bool type.
|
||||||
func (p Program) Bool() Type {
|
func (p Program) Bool() Type {
|
||||||
if p.boolTy == nil {
|
if p.boolTy == nil {
|
||||||
p.boolTy = p.llvmType(types.Typ[types.Bool])
|
p.boolTy = p.llvmType(types.Typ[types.Bool])
|
||||||
@@ -125,6 +131,7 @@ func (p Program) Bool() Type {
|
|||||||
return p.boolTy
|
return p.boolTy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Int returns int type.
|
||||||
func (p Program) Int() Type {
|
func (p Program) Int() Type {
|
||||||
if p.intTy == nil {
|
if p.intTy == nil {
|
||||||
p.intTy = p.llvmType(types.Typ[types.Int])
|
p.intTy = p.llvmType(types.Typ[types.Int])
|
||||||
@@ -132,6 +139,7 @@ func (p Program) Int() Type {
|
|||||||
return p.intTy
|
return p.intTy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Float64 returns float64 type.
|
||||||
func (p Program) Float64() Type {
|
func (p Program) Float64() Type {
|
||||||
if p.f64Ty == nil {
|
if p.f64Ty == nil {
|
||||||
p.f64Ty = p.llvmType(types.Typ[types.Float64])
|
p.f64Ty = p.llvmType(types.Typ[types.Float64])
|
||||||
@@ -160,18 +168,21 @@ func (p Package) NewConst(name string, val constant.Value) NamedConst {
|
|||||||
return &aNamedConst{}
|
return &aNamedConst{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewVar creates a new global variable.
|
||||||
func (p Package) NewVar(name string, typ types.Type) Global {
|
func (p Package) NewVar(name string, typ types.Type) Global {
|
||||||
t := p.prog.llvmType(typ)
|
t := p.prog.llvmType(typ)
|
||||||
gbl := llvm.AddGlobal(p.mod, t.ll, name)
|
gbl := llvm.AddGlobal(p.mod, t.ll, name)
|
||||||
return &aGlobal{Expr{gbl, t}}
|
return &aGlobal{Expr{gbl, t}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewFunc creates a new function.
|
||||||
func (p Package) NewFunc(name string, sig *types.Signature) Function {
|
func (p Package) NewFunc(name string, sig *types.Signature) Function {
|
||||||
t := p.prog.llvmSignature(sig)
|
t := p.prog.llvmSignature(sig)
|
||||||
fn := llvm.AddFunction(p.mod, name, t.ll)
|
fn := llvm.AddFunction(p.mod, name, t.ll)
|
||||||
return newFunction(fn, t, p.prog)
|
return newFunction(fn, t, p.prog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of the package.
|
||||||
func (p Package) String() string {
|
func (p Package) String() string {
|
||||||
return p.mod.String()
|
return p.mod.String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,11 +37,15 @@ func assertPkg(t *testing.T, p Package, expected string) {
|
|||||||
func TestVar(t *testing.T) {
|
func TestVar(t *testing.T) {
|
||||||
prog := NewProgram(nil)
|
prog := NewProgram(nil)
|
||||||
pkg := prog.NewPackage("bar", "foo/bar")
|
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'
|
assertPkg(t, pkg, `; ModuleID = 'foo/bar'
|
||||||
source_filename = "foo/bar"
|
source_filename = "foo/bar"
|
||||||
|
|
||||||
@a = external global i64
|
@a = global i64 100
|
||||||
|
@b = global i64 @a
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user