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

Commit

Permalink
Merge pull request #116 from axw/ssa
Browse files Browse the repository at this point in the history
ssa
  • Loading branch information
axw committed Jan 6, 2014
2 parents 4b5f250 + 002d46b commit 5847a5e
Show file tree
Hide file tree
Showing 76 changed files with 3,694 additions and 5,888 deletions.
76 changes: 76 additions & 0 deletions alg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright 2013 The llgo Authors.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package llgo

import (
"code.google.com/p/go.tools/go/types"

"github.com/axw/gollvm/llvm"
)

type AlgorithmKind int

const (
AlgorithmHash AlgorithmKind = iota
AlgorithmEqual
AlgorithmPrint
AlgorithmCopy
)

// algorithmMap maps types to their runtime algorithms (equality, hash, etc.)
type algorithmMap struct {
module llvm.Module
runtime *runtimeInterface

hashAlgFunctionType,
equalAlgFunctionType,
printAlgFunctionType,
copyAlgFunctionType llvm.Type
}

func newAlgorithmMap(m llvm.Module, runtime *runtimeInterface, target llvm.TargetData) *algorithmMap {
am := &algorithmMap{
module: m,
runtime: runtime,
}
uintptrType := target.IntPtrType()
voidPtrType := llvm.PointerType(llvm.Int8Type(), 0)
boolType := llvm.Int1Type()
params := []llvm.Type{uintptrType, voidPtrType}
am.hashAlgFunctionType = llvm.FunctionType(uintptrType, params, false)
params = []llvm.Type{uintptrType, uintptrType, uintptrType}
am.equalAlgFunctionType = llvm.FunctionType(boolType, params, false)
params = []llvm.Type{uintptrType, voidPtrType}
am.printAlgFunctionType = llvm.FunctionType(llvm.VoidType(), params, false)
params = []llvm.Type{uintptrType, voidPtrType, voidPtrType}
am.copyAlgFunctionType = llvm.FunctionType(llvm.VoidType(), params, false)
return am
}

func (am *algorithmMap) eqalg(t types.Type) llvm.Value {
t = t.Underlying()
if st, ok := t.(*types.Struct); ok && st.NumFields() == 1 {
t = st.Field(0).Type().Underlying()
}
switch t := t.(type) {
case *types.Basic:
switch t.Kind() {
case types.String:
return am.runtime.streqalg.LLVMValue()
case types.Float32:
return am.runtime.f32eqalg.LLVMValue()
case types.Float64:
return am.runtime.f64eqalg.LLVMValue()
case types.Complex64:
return am.runtime.c64eqalg.LLVMValue()
case types.Complex128:
return am.runtime.c128eqalg.LLVMValue()
}
case *types.Struct:
// TODO
}
// TODO(axw) size-specific memequal cases
return am.runtime.memequal.LLVMValue()
}
54 changes: 54 additions & 0 deletions annotations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2013 The llgo Authors.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package llgo

import (
"code.google.com/p/go.tools/go/types"
goimporter "code.google.com/p/go.tools/importer"
"code.google.com/p/go.tools/ssa"
"go/ast"
"go/token"
)

// processAnnotations takes an *ssa.Package and a
// *importer.PackageInfo, and processes all of the
// llgo source annotations attached to each top-level
// function and global variable.
func (c *compiler) processAnnotations(u *unit, pkginfo *goimporter.PackageInfo) {
members := make(map[types.Object]*LLVMValue, len(u.globals))
for k, v := range u.globals {
members[k.(ssa.Member).Object()] = v
}
applyAttributes := func(attrs []Attribute, idents ...*ast.Ident) {
if len(attrs) == 0 {
return
}
for _, ident := range idents {
if v := members[pkginfo.ObjectOf(ident)]; v != nil {
for _, attr := range attrs {
attr.Apply(v)
}
}
}
}
for _, f := range pkginfo.Files {
for _, decl := range f.Decls {
switch decl := decl.(type) {
case *ast.FuncDecl:
attrs := parseAttributes(decl.Doc)
applyAttributes(attrs, decl.Name)
case *ast.GenDecl:
if decl.Tok != token.VAR {
continue
}
for _, spec := range decl.Specs {
varspec := spec.(*ast.ValueSpec)
attrs := parseAttributes(decl.Doc)
applyAttributes(attrs, varspec.Names...)
}
}
}
}
}
11 changes: 3 additions & 8 deletions attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ func parseAttribute(line string) Attribute {
type linkageAttribute llvm.Linkage

func (a linkageAttribute) Apply(v Value) {
global := v.(*LLVMValue).pointer.value
global.SetLinkage(llvm.Linkage(a))
v.LLVMValue().SetLinkage(llvm.Linkage(a))
}

func parseLinkageAttribute(value string) linkageAttribute {
Expand Down Expand Up @@ -124,7 +123,6 @@ type nameAttribute string
func (a nameAttribute) Apply(v Value) {
if _, isfunc := v.Type().(*types.Signature); isfunc {
fn := v.LLVMValue()
fn = llvm.ConstExtractValue(fn, []uint32{0})
name := string(a)
curr := fn.GlobalParent().NamedFunction(name)
if !curr.IsNil() && curr != fn {
Expand All @@ -136,8 +134,7 @@ func (a nameAttribute) Apply(v Value) {
}
fn.SetName(name)
} else {
global := v.(*LLVMValue).pointer.value
global.SetName(string(a))
v.LLVMValue().SetName(string(a))
}
}

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

func (tlsAttribute) Apply(v Value) {
global := v.(*LLVMValue).pointer.value
global.SetThreadLocal(true)
v.LLVMValue().SetThreadLocal(true)
}
15 changes: 11 additions & 4 deletions build/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,28 @@ import (
"strings"
)

// Context returns a new go/build.Context with GOOS and GOARCH
type Context struct {
build.Context

// LLVM triple
Triple string
}

// ContextFromTriple returns a new go/build.Context with GOOS and GOARCH
// configured from the given triple.
func Context(triple string) (*build.Context, error) {
func ContextFromTriple(triple string) (*Context, error) {
goos, goarch, err := parseTriple(triple)
if err != nil {
return nil, err
}
ctx := build.Default
ctx := &Context{Context: build.Default, Triple: triple}
ctx.GOOS = goos
ctx.GOARCH = goarch
ctx.BuildTags = append(ctx.BuildTags, "llgo")
if triple == "pnacl" {
ctx.BuildTags = append(ctx.BuildTags, "pnacl")
}
return &ctx, nil
return ctx, nil
}

func parseTriple(triple string) (goos string, goarch string, err error) {
Expand Down
46 changes: 0 additions & 46 deletions builder.go

This file was deleted.

99 changes: 99 additions & 0 deletions builtins.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright 2011 The llgo Authors.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package llgo

import (
"code.google.com/p/go.tools/go/types"
"github.com/axw/gollvm/llvm"
)

func (c *compiler) callCap(arg *LLVMValue) *LLVMValue {
var v llvm.Value
switch typ := arg.Type().Underlying().(type) {
case *types.Array:
v = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false)
case *types.Pointer:
atyp := typ.Elem().Underlying().(*types.Array)
v = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false)
case *types.Slice:
v = c.builder.CreateExtractValue(arg.LLVMValue(), 2, "")
case *types.Chan:
f := c.runtime.chancap.LLVMValue()
v = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "")
}
return c.NewValue(v, types.Typ[types.Int])
}

func (c *compiler) callLen(arg *LLVMValue) *LLVMValue {
var lenvalue llvm.Value
switch typ := arg.Type().Underlying().(type) {
case *types.Array:
lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false)
case *types.Pointer:
atyp := typ.Elem().Underlying().(*types.Array)
lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false)
case *types.Slice:
lenvalue = c.builder.CreateExtractValue(arg.LLVMValue(), 1, "")
case *types.Map:
f := c.runtime.maplen.LLVMValue()
lenvalue = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "")
case *types.Basic:
if isString(typ) {
lenvalue = c.builder.CreateExtractValue(arg.LLVMValue(), 1, "")
}
case *types.Chan:
f := c.runtime.chanlen.LLVMValue()
lenvalue = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "")
}
return c.NewValue(lenvalue, types.Typ[types.Int])
}

// callAppend takes two slices of the same type, and yields
// the result of appending the second to the first.
func (c *compiler) callAppend(a, b *LLVMValue) *LLVMValue {
f := c.runtime.sliceappend.LLVMValue()
i8slice := f.Type().ElementType().ReturnType()
lla := a.LLVMValue()
llaType := lla.Type()
runtimeType := c.types.ToRuntime(a.Type())
args := []llvm.Value{
c.builder.CreatePtrToInt(runtimeType, c.target.IntPtrType(), ""),
c.coerceSlice(lla, i8slice),
c.coerceSlice(b.LLVMValue(), i8slice),
}
result := c.builder.CreateCall(f, args, "")
return c.NewValue(c.coerceSlice(result, llaType), a.Type())
}

// callCopy takes two slices a and b of the same type, and
// yields the result of calling "copy(a, b)".
func (c *compiler) callCopy(dest, source *LLVMValue) *LLVMValue {
runtimeTyp := c.types.ToRuntime(dest.Type())
runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
slicecopy := c.runtime.slicecopy.value
i8slice := slicecopy.Type().ElementType().ParamTypes()[1]
args := []llvm.Value{
runtimeTyp,
c.coerceSlice(dest.LLVMValue(), i8slice),
c.coerceSlice(source.LLVMValue(), i8slice),
}
result := c.builder.CreateCall(slicecopy, args, "")
return c.NewValue(result, types.Typ[types.Int])
}

// callDelete implements delete(m, k)
func (c *compiler) callDelete(m_, k_ *LLVMValue) {
f := c.runtime.mapdelete.LLVMValue()
dyntyp := c.types.ToRuntime(m_.Type())
dyntyp = c.builder.CreatePtrToInt(dyntyp, c.target.IntPtrType(), "")
m := m_.LLVMValue()
k := k_.LLVMValue()
stackptr := c.stacksave()
pk := c.builder.CreateAlloca(k.Type(), "")
c.builder.CreateStore(k, pk)
pk = c.builder.CreatePtrToInt(pk, c.target.IntPtrType(), "")
c.builder.CreateCall(f, []llvm.Value{dyntyp, m, pk}, "")
c.stackrestore(stackptr)
}
Loading

0 comments on commit 5847a5e

Please sign in to comment.