Skip to content
This repository was archived by the owner on Dec 14, 2023. It is now read-only.

Commit 5847a5e

Browse files
committed
Merge pull request #116 from axw/ssa
ssa
2 parents 4b5f250 + 002d46b commit 5847a5e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+3694
-5888
lines changed

alg.go

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2013 The llgo Authors.
2+
// Use of this source code is governed by an MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package llgo
6+
7+
import (
8+
"code.google.com/p/go.tools/go/types"
9+
10+
"github.com/axw/gollvm/llvm"
11+
)
12+
13+
type AlgorithmKind int
14+
15+
const (
16+
AlgorithmHash AlgorithmKind = iota
17+
AlgorithmEqual
18+
AlgorithmPrint
19+
AlgorithmCopy
20+
)
21+
22+
// algorithmMap maps types to their runtime algorithms (equality, hash, etc.)
23+
type algorithmMap struct {
24+
module llvm.Module
25+
runtime *runtimeInterface
26+
27+
hashAlgFunctionType,
28+
equalAlgFunctionType,
29+
printAlgFunctionType,
30+
copyAlgFunctionType llvm.Type
31+
}
32+
33+
func newAlgorithmMap(m llvm.Module, runtime *runtimeInterface, target llvm.TargetData) *algorithmMap {
34+
am := &algorithmMap{
35+
module: m,
36+
runtime: runtime,
37+
}
38+
uintptrType := target.IntPtrType()
39+
voidPtrType := llvm.PointerType(llvm.Int8Type(), 0)
40+
boolType := llvm.Int1Type()
41+
params := []llvm.Type{uintptrType, voidPtrType}
42+
am.hashAlgFunctionType = llvm.FunctionType(uintptrType, params, false)
43+
params = []llvm.Type{uintptrType, uintptrType, uintptrType}
44+
am.equalAlgFunctionType = llvm.FunctionType(boolType, params, false)
45+
params = []llvm.Type{uintptrType, voidPtrType}
46+
am.printAlgFunctionType = llvm.FunctionType(llvm.VoidType(), params, false)
47+
params = []llvm.Type{uintptrType, voidPtrType, voidPtrType}
48+
am.copyAlgFunctionType = llvm.FunctionType(llvm.VoidType(), params, false)
49+
return am
50+
}
51+
52+
func (am *algorithmMap) eqalg(t types.Type) llvm.Value {
53+
t = t.Underlying()
54+
if st, ok := t.(*types.Struct); ok && st.NumFields() == 1 {
55+
t = st.Field(0).Type().Underlying()
56+
}
57+
switch t := t.(type) {
58+
case *types.Basic:
59+
switch t.Kind() {
60+
case types.String:
61+
return am.runtime.streqalg.LLVMValue()
62+
case types.Float32:
63+
return am.runtime.f32eqalg.LLVMValue()
64+
case types.Float64:
65+
return am.runtime.f64eqalg.LLVMValue()
66+
case types.Complex64:
67+
return am.runtime.c64eqalg.LLVMValue()
68+
case types.Complex128:
69+
return am.runtime.c128eqalg.LLVMValue()
70+
}
71+
case *types.Struct:
72+
// TODO
73+
}
74+
// TODO(axw) size-specific memequal cases
75+
return am.runtime.memequal.LLVMValue()
76+
}

annotations.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2013 The llgo Authors.
2+
// Use of this source code is governed by an MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package llgo
6+
7+
import (
8+
"code.google.com/p/go.tools/go/types"
9+
goimporter "code.google.com/p/go.tools/importer"
10+
"code.google.com/p/go.tools/ssa"
11+
"go/ast"
12+
"go/token"
13+
)
14+
15+
// processAnnotations takes an *ssa.Package and a
16+
// *importer.PackageInfo, and processes all of the
17+
// llgo source annotations attached to each top-level
18+
// function and global variable.
19+
func (c *compiler) processAnnotations(u *unit, pkginfo *goimporter.PackageInfo) {
20+
members := make(map[types.Object]*LLVMValue, len(u.globals))
21+
for k, v := range u.globals {
22+
members[k.(ssa.Member).Object()] = v
23+
}
24+
applyAttributes := func(attrs []Attribute, idents ...*ast.Ident) {
25+
if len(attrs) == 0 {
26+
return
27+
}
28+
for _, ident := range idents {
29+
if v := members[pkginfo.ObjectOf(ident)]; v != nil {
30+
for _, attr := range attrs {
31+
attr.Apply(v)
32+
}
33+
}
34+
}
35+
}
36+
for _, f := range pkginfo.Files {
37+
for _, decl := range f.Decls {
38+
switch decl := decl.(type) {
39+
case *ast.FuncDecl:
40+
attrs := parseAttributes(decl.Doc)
41+
applyAttributes(attrs, decl.Name)
42+
case *ast.GenDecl:
43+
if decl.Tok != token.VAR {
44+
continue
45+
}
46+
for _, spec := range decl.Specs {
47+
varspec := spec.(*ast.ValueSpec)
48+
attrs := parseAttributes(decl.Doc)
49+
applyAttributes(attrs, varspec.Names...)
50+
}
51+
}
52+
}
53+
}
54+
}

attribute.go

+3-8
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ func parseAttribute(line string) Attribute {
7575
type linkageAttribute llvm.Linkage
7676

7777
func (a linkageAttribute) Apply(v Value) {
78-
global := v.(*LLVMValue).pointer.value
79-
global.SetLinkage(llvm.Linkage(a))
78+
v.LLVMValue().SetLinkage(llvm.Linkage(a))
8079
}
8180

8281
func parseLinkageAttribute(value string) linkageAttribute {
@@ -124,7 +123,6 @@ type nameAttribute string
124123
func (a nameAttribute) Apply(v Value) {
125124
if _, isfunc := v.Type().(*types.Signature); isfunc {
126125
fn := v.LLVMValue()
127-
fn = llvm.ConstExtractValue(fn, []uint32{0})
128126
name := string(a)
129127
curr := fn.GlobalParent().NamedFunction(name)
130128
if !curr.IsNil() && curr != fn {
@@ -136,8 +134,7 @@ func (a nameAttribute) Apply(v Value) {
136134
}
137135
fn.SetName(name)
138136
} else {
139-
global := v.(*LLVMValue).pointer.value
140-
global.SetName(string(a))
137+
v.LLVMValue().SetName(string(a))
141138
}
142139
}
143140

@@ -164,7 +161,6 @@ type llvmAttribute llvm.Attribute
164161
func (a llvmAttribute) Apply(v Value) {
165162
if _, isfunc := v.Type().(*types.Signature); isfunc {
166163
fn := v.LLVMValue()
167-
fn = llvm.ConstExtractValue(fn, []uint32{0})
168164
fn.AddFunctionAttr(llvm.Attribute(a))
169165
} else {
170166
v.LLVMValue().AddAttribute(llvm.Attribute(a))
@@ -174,6 +170,5 @@ func (a llvmAttribute) Apply(v Value) {
174170
type tlsAttribute struct{}
175171

176172
func (tlsAttribute) Apply(v Value) {
177-
global := v.(*LLVMValue).pointer.value
178-
global.SetThreadLocal(true)
173+
v.LLVMValue().SetThreadLocal(true)
179174
}

build/context.go

+11-4
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,28 @@ import (
1111
"strings"
1212
)
1313

14-
// Context returns a new go/build.Context with GOOS and GOARCH
14+
type Context struct {
15+
build.Context
16+
17+
// LLVM triple
18+
Triple string
19+
}
20+
21+
// ContextFromTriple returns a new go/build.Context with GOOS and GOARCH
1522
// configured from the given triple.
16-
func Context(triple string) (*build.Context, error) {
23+
func ContextFromTriple(triple string) (*Context, error) {
1724
goos, goarch, err := parseTriple(triple)
1825
if err != nil {
1926
return nil, err
2027
}
21-
ctx := build.Default
28+
ctx := &Context{Context: build.Default, Triple: triple}
2229
ctx.GOOS = goos
2330
ctx.GOARCH = goarch
2431
ctx.BuildTags = append(ctx.BuildTags, "llgo")
2532
if triple == "pnacl" {
2633
ctx.BuildTags = append(ctx.BuildTags, "pnacl")
2734
}
28-
return &ctx, nil
35+
return ctx, nil
2936
}
3037

3138
func parseTriple(triple string) (goos string, goarch string, err error) {

builder.go

-46
This file was deleted.

builtins.go

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright 2011 The llgo Authors.
2+
// Use of this source code is governed by an MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package llgo
6+
7+
import (
8+
"code.google.com/p/go.tools/go/types"
9+
"github.com/axw/gollvm/llvm"
10+
)
11+
12+
func (c *compiler) callCap(arg *LLVMValue) *LLVMValue {
13+
var v llvm.Value
14+
switch typ := arg.Type().Underlying().(type) {
15+
case *types.Array:
16+
v = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false)
17+
case *types.Pointer:
18+
atyp := typ.Elem().Underlying().(*types.Array)
19+
v = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false)
20+
case *types.Slice:
21+
v = c.builder.CreateExtractValue(arg.LLVMValue(), 2, "")
22+
case *types.Chan:
23+
f := c.runtime.chancap.LLVMValue()
24+
v = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "")
25+
}
26+
return c.NewValue(v, types.Typ[types.Int])
27+
}
28+
29+
func (c *compiler) callLen(arg *LLVMValue) *LLVMValue {
30+
var lenvalue llvm.Value
31+
switch typ := arg.Type().Underlying().(type) {
32+
case *types.Array:
33+
lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false)
34+
case *types.Pointer:
35+
atyp := typ.Elem().Underlying().(*types.Array)
36+
lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false)
37+
case *types.Slice:
38+
lenvalue = c.builder.CreateExtractValue(arg.LLVMValue(), 1, "")
39+
case *types.Map:
40+
f := c.runtime.maplen.LLVMValue()
41+
lenvalue = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "")
42+
case *types.Basic:
43+
if isString(typ) {
44+
lenvalue = c.builder.CreateExtractValue(arg.LLVMValue(), 1, "")
45+
}
46+
case *types.Chan:
47+
f := c.runtime.chanlen.LLVMValue()
48+
lenvalue = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "")
49+
}
50+
return c.NewValue(lenvalue, types.Typ[types.Int])
51+
}
52+
53+
// callAppend takes two slices of the same type, and yields
54+
// the result of appending the second to the first.
55+
func (c *compiler) callAppend(a, b *LLVMValue) *LLVMValue {
56+
f := c.runtime.sliceappend.LLVMValue()
57+
i8slice := f.Type().ElementType().ReturnType()
58+
lla := a.LLVMValue()
59+
llaType := lla.Type()
60+
runtimeType := c.types.ToRuntime(a.Type())
61+
args := []llvm.Value{
62+
c.builder.CreatePtrToInt(runtimeType, c.target.IntPtrType(), ""),
63+
c.coerceSlice(lla, i8slice),
64+
c.coerceSlice(b.LLVMValue(), i8slice),
65+
}
66+
result := c.builder.CreateCall(f, args, "")
67+
return c.NewValue(c.coerceSlice(result, llaType), a.Type())
68+
}
69+
70+
// callCopy takes two slices a and b of the same type, and
71+
// yields the result of calling "copy(a, b)".
72+
func (c *compiler) callCopy(dest, source *LLVMValue) *LLVMValue {
73+
runtimeTyp := c.types.ToRuntime(dest.Type())
74+
runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
75+
slicecopy := c.runtime.slicecopy.value
76+
i8slice := slicecopy.Type().ElementType().ParamTypes()[1]
77+
args := []llvm.Value{
78+
runtimeTyp,
79+
c.coerceSlice(dest.LLVMValue(), i8slice),
80+
c.coerceSlice(source.LLVMValue(), i8slice),
81+
}
82+
result := c.builder.CreateCall(slicecopy, args, "")
83+
return c.NewValue(result, types.Typ[types.Int])
84+
}
85+
86+
// callDelete implements delete(m, k)
87+
func (c *compiler) callDelete(m_, k_ *LLVMValue) {
88+
f := c.runtime.mapdelete.LLVMValue()
89+
dyntyp := c.types.ToRuntime(m_.Type())
90+
dyntyp = c.builder.CreatePtrToInt(dyntyp, c.target.IntPtrType(), "")
91+
m := m_.LLVMValue()
92+
k := k_.LLVMValue()
93+
stackptr := c.stacksave()
94+
pk := c.builder.CreateAlloca(k.Type(), "")
95+
c.builder.CreateStore(k, pk)
96+
pk = c.builder.CreatePtrToInt(pk, c.target.IntPtrType(), "")
97+
c.builder.CreateCall(f, []llvm.Value{dyntyp, m, pk}, "")
98+
c.stackrestore(stackptr)
99+
}

0 commit comments

Comments
 (0)