Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
...
  • 2 commits
  • 13 files changed
  • 0 commit comments
  • 1 contributor
Showing with 283 additions and 211 deletions.
  1. +3 −1 compiler.go
  2. +9 −9 decl.go
  3. +3 −5 expr.go
  4. +1 −1 len.go
  5. +3 −3 literals.go
  6. +0 −4 llgo/testdata/interface.go
  7. +213 −0 llvmtypes.go
  8. +1 −1 new.go
  9. +2 −2 slice.go
  10. +2 −3 stmt.go
  11. +23 −158 types/types.go
  12. +1 −1 types/universe.go
  13. +22 −23 value.go
View
4 compiler.go
@@ -53,6 +53,7 @@ type compiler struct {
filescope *ast.Scope
scope *ast.Scope
pkgmap map[*ast.Object]string
+ types *TypeMap
}
func (c *compiler) LookupObj(name string) *ast.Object {
@@ -122,7 +123,7 @@ func (c *compiler) Resolve(obj *ast.Object) Value {
module := c.module.Module
t := obj.Type.(types.Type)
name := c.pkgmap[obj] + "." + obj.Name
- g := llvm.AddGlobal(module, t.LLVMType(), name)
+ g := llvm.AddGlobal(module, c.types.ToLLVM(t), name)
g.SetLinkage(llvm.AvailableExternallyLinkage)
obj.Data = c.NewLLVMValue(g, t)
}
@@ -176,6 +177,7 @@ func Compile(fset *token.FileSet, pkg *ast.Package) (m *Module, err error) {
compiler.fileset = fset
compiler.pkg = pkg
compiler.initfuncs = make([]Value, 0)
+ compiler.types = NewTypeMap()
// Create a Builder, for building LLVM instructions.
compiler.builder = llvm.GlobalContext().NewBuilder()
View
18 decl.go
@@ -72,7 +72,7 @@ func (c *compiler) VisitFuncProtoDecl(f *ast.FuncDecl) Value {
pkgname := c.pkgmap[f.Name.Obj]
fn_name = pkgname + "." + fn_name
}
- llvm_fn_type := fn_type.LLVMType().ElementType()
+ llvm_fn_type := c.types.ToLLVM(fn_type).ElementType()
fn := llvm.AddFunction(c.module.Module, fn_name, llvm_fn_type)
if exported {
fn.SetLinkage(llvm.ExternalLinkage)
@@ -108,7 +108,7 @@ func (c *compiler) VisitFuncDecl(f *ast.FuncDecl) Value {
recv_obj := fn_type.Recv
recv_type := recv_obj.Type.(types.Type)
stack_value := c.builder.CreateAlloca(
- recv_type.LLVMType(), recv_obj.Name)
+ c.types.ToLLVM(recv_type), recv_obj.Name)
c.builder.CreateStore(param_0, stack_value)
value := c.NewLLVMValue(stack_value, &types.Pointer{Base: recv_type})
value.indirect = true
@@ -124,7 +124,7 @@ func (c *compiler) VisitFuncDecl(f *ast.FuncDecl) Value {
}
param_value := llvm_fn.Param(param_i)
- stack_value := c.builder.CreateAlloca(param_type.LLVMType(), name)
+ stack_value := c.builder.CreateAlloca(c.types.ToLLVM(param_type), name)
c.builder.CreateStore(param_value, stack_value)
value := c.NewLLVMValue(stack_value,
&types.Pointer{Base: param_type})
@@ -169,7 +169,7 @@ func (c *compiler) createGlobal(e ast.Expr,
t types.Type,
name string) (g *LLVMValue) {
if e == nil {
- gv := llvm.AddGlobal(c.module.Module, t.LLVMType(), name)
+ gv := llvm.AddGlobal(c.module.Module, c.types.ToLLVM(t), name)
g = c.NewLLVMValue(gv, &types.Pointer{Base: t})
g.indirect = !isArray(t)
return g
@@ -179,7 +179,7 @@ func (c *compiler) createGlobal(e ast.Expr,
defer c.builder.SetInsertPointAtEnd(block)
}
fn_type := new(types.Func)
- llvm_fn_type := fn_type.LLVMType().ElementType()
+ llvm_fn_type := c.types.ToLLVM(fn_type).ElementType()
fn := llvm.AddFunction(c.module.Module, "", llvm_fn_type)
entry := llvm.AddBasicBlock(fn, "entry")
c.builder.SetInsertPointAtEnd(entry)
@@ -211,15 +211,15 @@ func (c *compiler) createGlobal(e ast.Expr,
// Set the initialiser. If it's a non-const value, then
// we'll have to do the assignment in a global constructor
// function.
- gv := llvm.AddGlobal(c.module.Module, t.LLVMType(), name)
+ gv := llvm.AddGlobal(c.module.Module, c.types.ToLLVM(t), name)
g = c.NewLLVMValue(gv, &types.Pointer{Base: t})
g.indirect = !isArray(t)
if isconst {
// Initialiser is constant; discard function and return
// global now.
gv.SetInitializer(init_.LLVMValue())
} else {
- gv.SetInitializer(llvm.ConstNull(t.LLVMType()))
+ gv.SetInitializer(llvm.ConstNull(c.types.ToLLVM(t)))
c.builder.CreateStore(init_.LLVMValue(), gv)
}
@@ -296,11 +296,11 @@ func (c *compiler) VisitValueSpec(valspec *ast.ValueSpec, isconst bool) {
// declared inside a function.
var llvm_init llvm.Value
stack_value := c.builder.CreateAlloca(
- value_type.LLVMType(), name)
+ c.types.ToLLVM(value_type), name)
if init_ == nil {
// If no initialiser was specified, set it to the
// zero value.
- llvm_init = llvm.ConstNull(value_type.LLVMType())
+ llvm_init = llvm.ConstNull(c.types.ToLLVM(value_type))
} else {
llvm_init = init_.Convert(value_type).LLVMValue()
}
View
8 expr.go
@@ -291,16 +291,14 @@ func (c *compiler) VisitSelectorExpr(expr *ast.SelectorExpr) Value {
struct_value := lhs.LLVMValue()
receiver_value := c.builder.CreateStructGEP(struct_value, 0, "")
fn_value := c.builder.CreateStructGEP(struct_value, i+1, "")
- receiver_type := &types.Pointer{Base: types.Int8}
method_type := c.ObjGetType(iface.Methods[i]).(*types.Func)
- method_type.Recv = ast.NewObj(ast.Var, "")
- method_type.Recv.Type = receiver_type
method := c.NewLLVMValue(
c.builder.CreateBitCast(
c.builder.CreateLoad(fn_value, ""),
- method_type.LLVMType(), ""), method_type)
+ c.types.ToLLVM(method_type), ""), method_type)
method.receiver = c.NewLLVMValue(
- c.builder.CreateLoad(receiver_value, ""), receiver_type)
+ c.builder.CreateLoad(receiver_value, ""),
+ method_type.Recv.Type.(types.Type))
return method
}
}
View
2 len.go
@@ -73,7 +73,7 @@ func (c *compiler) VisitLen(expr *ast.CallExpr) Value {
return c.NewConstValue(token.INT, v)
case *types.Struct:
- sz := llvm.SizeOf(typ.LLVMType())
+ sz := llvm.SizeOf(c.types.ToLLVM(typ))
// FIXME
// SizeOf returns a Constant, but not a ConstantInt, so we
// can't call ZExtValue on it. Not sure how best to tackle
View
6 literals.go
@@ -35,7 +35,7 @@ func (c *compiler) VisitBasicLit(lit *ast.BasicLit) Value {
func (c *compiler) VisitFuncLit(lit *ast.FuncLit) Value {
fn_type := c.VisitFuncType(lit.Type)
- fn := llvm.AddFunction(c.module.Module, "", fn_type.LLVMType())
+ fn := llvm.AddFunction(c.module.Module, "", c.types.ToLLVM(fn_type))
fn.SetFunctionCallConv(llvm.FastCallConv)
defer c.builder.SetInsertPointAtEnd(c.builder.GetInsertBlock())
@@ -98,13 +98,13 @@ func (c *compiler) VisitCompositeLit(lit *ast.CompositeLit) Value {
llvm_values := make([]llvm.Value, len(values))
for i, value := range values {
if value == nil {
- llvm_values[i] = llvm.ConstNull(elttype.LLVMType())
+ llvm_values[i] = llvm.ConstNull(c.types.ToLLVM(elttype))
} else {
llvm_values[i] = value.Convert(elttype).LLVMValue()
}
}
return c.NewLLVMValue(
- llvm.ConstArray(elttype.LLVMType(), llvm_values), typ)
+ llvm.ConstArray(c.types.ToLLVM(elttype), llvm_values), typ)
}
}
panic(fmt.Sprint("Unhandled type kind: ", typ))
View
4 llgo/testdata/interface.go
@@ -16,10 +16,6 @@ func (m MagicNumber) Number() int {
return 3
}
-//func test(n Numbered) {
-// n.Number()
-//}
-
func main() {
var b Beast
var m MagicNumber
View
213 llvmtypes.go
@@ -0,0 +1,213 @@
+/*
+Copyright (c) 2011, 2012 Andrew Wilkins <axwalk@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package llgo
+
+import (
+ "fmt"
+ "github.com/axw/gollvm/llvm"
+ "github.com/axw/llgo/types"
+ "go/ast"
+)
+
+type TypeMap struct {
+ types map[types.Type]llvm.Type
+}
+
+func NewTypeMap() *TypeMap {
+ tm := &TypeMap{}
+ tm.types = make(map[types.Type]llvm.Type)
+ return tm
+}
+
+func (tm *TypeMap) ToLLVM(t types.Type) llvm.Type {
+ lt, ok := tm.types[t]
+ if !ok {
+ lt = tm.makeLLVMType(t)
+ tm.types[t] = lt
+ }
+ return lt
+}
+
+func (tm *TypeMap) makeLLVMType(t types.Type) llvm.Type {
+ switch t := t.(type) {
+ case *types.Bad:
+ return tm.badLLVMType(t)
+ case *types.Basic:
+ return tm.basicLLVMType(t)
+ case *types.Array:
+ return tm.arrayLLVMType(t)
+ case *types.Slice:
+ return tm.sliceLLVMType(t)
+ case *types.Struct:
+ return tm.structLLVMType(t)
+ case *types.Pointer:
+ return tm.pointerLLVMType(t)
+ case *types.Func:
+ return tm.funcLLVMType(t)
+ case *types.Interface:
+ return tm.interfaceLLVMType(t)
+ case *types.Map:
+ return tm.mapLLVMType(t)
+ case *types.Chan:
+ return tm.chanLLVMType(t)
+ case *types.Name:
+ return tm.nameLLVMType(t)
+ }
+ panic("unreachable")
+}
+
+func (tm *TypeMap) badLLVMType(b *types.Bad) llvm.Type {
+ return llvm.Type{nil}
+}
+
+func (tm *TypeMap) basicLLVMType(b *types.Basic) llvm.Type {
+ switch b.Kind {
+ case types.BoolKind:
+ return llvm.Int1Type()
+ case types.ByteKind, types.Int8Kind, types.Uint8Kind:
+ return llvm.Int8Type()
+ case types.Int16Kind, types.Uint16Kind:
+ return llvm.Int16Type()
+ case types.UintptrKind, types.Int32Kind, types.Uint32Kind:
+ return llvm.Int32Type()
+ case types.Int64Kind, types.Uint64Kind:
+ return llvm.Int64Type()
+ case types.Float32Kind:
+ return llvm.FloatType()
+ case types.Float64Kind:
+ return llvm.DoubleType()
+ //case Complex64: TODO
+ //case Complex128:
+ //case UntypedInt:
+ //case UntypedFloat:
+ //case UntypedComplex:
+ case types.StringKind:
+ i8ptr := llvm.PointerType(llvm.Int8Type(), 0)
+ elements := []llvm.Type{i8ptr, llvm.Int32Type()}
+ return llvm.StructType(elements, false)
+ case types.RuneKind:
+ return tm.basicLLVMType(types.Int.Underlying.(*types.Basic))
+ }
+ panic(fmt.Sprint("unhandled kind: ", b.Kind))
+}
+
+func (tm *TypeMap) arrayLLVMType(a *types.Array) llvm.Type {
+ return llvm.ArrayType(tm.ToLLVM(a.Elt), int(a.Len))
+}
+
+func (tm *TypeMap) sliceLLVMType(s *types.Slice) llvm.Type {
+ elements := []llvm.Type{
+ llvm.PointerType(tm.ToLLVM(s.Elt), 0),
+ llvm.Int32Type(),
+ llvm.Int32Type(),
+ }
+ return llvm.StructType(elements, false)
+}
+
+func (tm *TypeMap) structLLVMType(s *types.Struct) llvm.Type {
+ // Types may be circular, so we need to first create an empty
+ // struct type, then fill in its body after visiting its
+ // members.
+ typ, ok := tm.types[s]
+ if !ok {
+ typ = llvm.GlobalContext().StructCreateNamed("")
+ tm.types[s] = typ
+ elements := make([]llvm.Type, len(s.Fields))
+ for i, f := range s.Fields {
+ ft := f.Type.(types.Type)
+ elements[i] = tm.ToLLVM(ft)
+ }
+ typ.StructSetBody(elements, false)
+ }
+ return typ
+}
+
+func (tm *TypeMap) pointerLLVMType(p *types.Pointer) llvm.Type {
+ return llvm.PointerType(tm.ToLLVM(p.Base), 0)
+}
+
+func (tm *TypeMap) funcLLVMType(f *types.Func) llvm.Type {
+ param_types := make([]llvm.Type, 0)
+
+ // Add receiver parameter.
+ if f.Recv != nil {
+ recv_type := f.Recv.Type.(types.Type)
+ param_types = append(param_types, tm.ToLLVM(recv_type))
+ }
+
+ for i, param := range f.Params {
+ param_type := param.Type.(types.Type)
+ if f.IsVariadic && i == len(f.Params)-1 {
+ param_type = &types.Slice{Elt: param_type}
+ }
+ param_types = append(param_types, tm.ToLLVM(param_type))
+ }
+
+ var return_type llvm.Type
+ switch len(f.Results) {
+ case 0:
+ return_type = llvm.VoidType()
+ case 1:
+ return_type = tm.ToLLVM(f.Results[0].Type.(types.Type))
+ default:
+ elements := make([]llvm.Type, len(f.Results))
+ for i, result := range f.Results {
+ elements[i] = tm.ToLLVM(result.Type.(types.Type))
+ }
+ return_type = llvm.StructType(elements, false)
+ }
+
+ fn_type := llvm.FunctionType(return_type, param_types, false)
+ return llvm.PointerType(fn_type, 0)
+}
+
+func (tm *TypeMap) interfaceLLVMType(i *types.Interface) llvm.Type {
+ ptr_type := llvm.PointerType(llvm.Int8Type(), 0)
+ elements := make([]llvm.Type, 1+len(i.Methods))
+ elements[0] = ptr_type // value
+ for n, m := range i.Methods {
+ // Add an opaque pointer parameter to the function for the
+ // struct pointer.
+ fntype := m.Type.(*types.Func)
+ receiver_type := &types.Pointer{Base: types.Int8}
+ fntype.Recv = ast.NewObj(ast.Var, "")
+ fntype.Recv.Type = receiver_type
+ fnptr := types.Pointer{Base: fntype}
+ elements[n+1] = tm.ToLLVM(&fnptr)
+ }
+ return llvm.StructType(elements, false)
+}
+
+func (tm *TypeMap) mapLLVMType(m *types.Map) llvm.Type {
+ return llvm.Type{nil} // TODO
+}
+
+func (tm *TypeMap) chanLLVMType(c *types.Chan) llvm.Type {
+ return llvm.Type{nil} // TODO
+}
+
+func (tm *TypeMap) nameLLVMType(n *types.Name) llvm.Type {
+ return tm.ToLLVM(n.Underlying)
+}
+
+// vim: set ft=go :
View
2 new.go
@@ -33,7 +33,7 @@ func (c *compiler) VisitNew(expr *ast.CallExpr) Value {
panic("Expecting only one argument to new")
}
typ := c.GetType(expr.Args[0])
- llvm_typ := typ.LLVMType()
+ llvm_typ := c.types.ToLLVM(typ)
mem := c.builder.CreateMalloc(llvm_typ, "")
c.builder.CreateStore(llvm.ConstNull(llvm_typ), mem)
return c.NewLLVMValue(mem, &types.Pointer{Base: typ})
View
4 slice.go
@@ -30,15 +30,15 @@ import (
func (c *compiler) makeSlice(v []llvm.Value, elttyp types.Type) llvm.Value {
n := llvm.ConstInt(llvm.Int32Type(), uint64(len(v)), false)
- mem := c.builder.CreateArrayMalloc(elttyp.LLVMType(), n, "")
+ mem := c.builder.CreateArrayMalloc(c.types.ToLLVM(elttyp), n, "")
for i, value := range v {
indices := []llvm.Value{
llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}
ep := c.builder.CreateGEP(mem, indices, "")
c.builder.CreateStore(value, ep)
}
slicetyp := types.Slice{Elt: elttyp}
- struct_ := c.builder.CreateAlloca(slicetyp.LLVMType(), "")
+ struct_ := c.builder.CreateAlloca(c.types.ToLLVM(&slicetyp), "")
c.builder.CreateStore(mem, c.builder.CreateStructGEP(struct_, 0, ""))
c.builder.CreateStore(n, c.builder.CreateStructGEP(struct_, 1, ""))
c.builder.CreateStore(n, c.builder.CreateStructGEP(struct_, 2, ""))
View
5 stmt.go
@@ -128,8 +128,7 @@ func (c *compiler) VisitAssignStmt(stmt *ast.AssignStmt) {
} else {
ptr, _ := (obj.Data).(Value)
value = value.Convert(types.Deref(ptr.Type()))
- c.builder.CreateStore(
- value.LLVMValue(), ptr.LLVMValue())
+ c.builder.CreateStore(value.LLVMValue(), ptr.LLVMValue())
}
}
default:
@@ -250,7 +249,7 @@ func (c *compiler) VisitGoStmt(stmt *ast.GoStmt) {
fn_type := types.Deref(fn.Type()).(*types.Func)
for _, param := range fn_type.Params {
typ := param.Type.(types.Type)
- param_types = append(param_types, typ.LLVMType())
+ param_types = append(param_types, c.types.ToLLVM(typ))
}
args_struct_type = llvm.StructType(param_types, false)
args_mem = c.builder.CreateAlloca(args_struct_type, "")
View
181 types/types.go
@@ -12,7 +12,6 @@ package types
import (
"fmt"
- "github.com/axw/gollvm/llvm"
"go/ast"
"sort"
)
@@ -46,25 +45,29 @@ const (
// All types implement the Type interface.
type Type interface {
- LLVMType() llvm.Type
+ isType()
String() string
}
+// All concrete types embed ImplementsType which
+// ensures that all types implement the Type interface.
+type ImplementsType struct{}
+
+func (t *ImplementsType) isType() {}
+
// A Bad type is a non-nil placeholder type when we don't know a type.
type Bad struct {
+ ImplementsType
Msg string // for better error reporting/debugging
}
func (b *Bad) String() string {
return fmt.Sprint("Bad(", b.Msg, ")")
}
-func (b *Bad) LLVMType() llvm.Type {
- return llvm.Type{nil}
-}
-
// A Basic represents a (unnamed) basic type.
type Basic struct {
+ ImplementsType
Kind BasicTypeKind
// TODO(gri) need a field specifying the exact basic type
}
@@ -73,39 +76,9 @@ func (b *Basic) String() string {
return fmt.Sprint("Basic(", b.Kind, ")")
}
-func (b *Basic) LLVMType() llvm.Type {
- switch b.Kind {
- case BoolKind:
- return llvm.Int1Type()
- case ByteKind, Int8Kind, Uint8Kind:
- return llvm.Int8Type()
- case Int16Kind, Uint16Kind:
- return llvm.Int16Type()
- case UintptrKind, Int32Kind, Uint32Kind:
- return llvm.Int32Type()
- case Int64Kind, Uint64Kind:
- return llvm.Int64Type()
- case Float32Kind:
- return llvm.FloatType()
- case Float64Kind:
- return llvm.DoubleType()
- //case Complex64: TODO
- //case Complex128:
- //case UntypedInt:
- //case UntypedFloat:
- //case UntypedComplex:
- case StringKind:
- i8ptr := llvm.PointerType(llvm.Int8Type(), 0)
- elements := []llvm.Type{i8ptr, llvm.Int32Type()}
- return llvm.StructType(elements, false)
- case RuneKind:
- return Int.LLVMType()
- }
- panic(fmt.Sprint("unhandled kind: ", b.Kind))
-}
-
// An Array represents an array type [Len]Elt.
type Array struct {
+ ImplementsType
Len uint64
Elt Type
}
@@ -114,34 +87,22 @@ func (a *Array) String() string {
return fmt.Sprint("Array(", a.Len, ", ", a.Elt, ")")
}
-func (a *Array) LLVMType() llvm.Type {
- return llvm.ArrayType(a.Elt.LLVMType(), int(a.Len))
-}
-
// A Slice represents a slice type []Elt.
type Slice struct {
+ ImplementsType
Elt Type
}
-func (s *Slice) LLVMType() llvm.Type {
- elements := []llvm.Type{
- llvm.PointerType(s.Elt.LLVMType(), 0),
- llvm.Int32Type(),
- llvm.Int32Type(),
- }
- return llvm.StructType(elements, false)
-}
-
func (s *Slice) String() string {
return fmt.Sprint("Slice(", s.Elt, ")")
}
// A Struct represents a struct type struct{...}.
// Anonymous fields are represented by objects with empty names.
type Struct struct {
+ ImplementsType
Fields ObjList // struct fields; or nil
Tags []string // corresponding tags; or nil
- typ llvm.Type
// TODO(gri) This type needs some rethinking:
// - at the moment anonymous fields are marked with "" object names,
// and their names have to be reconstructed
@@ -152,36 +113,20 @@ func (s *Struct) String() string {
return fmt.Sprint("Struct(", s.Fields, ", ", s.Tags, ")")
}
-func (s *Struct) LLVMType() llvm.Type {
- if s.typ.IsNil() {
- s.typ = llvm.GlobalContext().StructCreateNamed("")
- elements := make([]llvm.Type, len(s.Fields))
- for i, f := range s.Fields {
- ft := f.Type.(Type)
- elements[i] = ft.LLVMType()
- }
- //return llvm.StructType(elements, false)
- s.typ.StructSetBody(elements, false)
- }
- return s.typ
-}
-
// A Pointer represents a pointer type *Base.
type Pointer struct {
+ ImplementsType
Base Type
}
func (p *Pointer) String() string {
return fmt.Sprint("Pointer(", p.Base, ")")
}
-func (p *Pointer) LLVMType() llvm.Type {
- return llvm.PointerType(p.Base.LLVMType(), 0)
-}
-
// A Func represents a function type func(...) (...).
// Unnamed parameters are represented by objects with empty names.
type Func struct {
+ ImplementsType
Recv *ast.Object // nil if not a method
Params ObjList // (incoming) parameters from left to right; or nil
Results ObjList // (outgoing) results from left to right; or nil
@@ -193,102 +138,29 @@ func (f *Func) String() string {
f.Params, f.Results, f.IsVariadic)
}
-func (f *Func) LLVMType() llvm.Type {
- param_types := make([]llvm.Type, 0)
-
- // Add receiver parameter.
- if f.Recv != nil {
- recv_type := f.Recv.Type.(Type)
- param_types = append(param_types, recv_type.LLVMType())
- }
-
- for i, param := range f.Params {
- param_type := param.Type.(Type)
- if f.IsVariadic && i == len(f.Params)-1 {
- param_type = &Slice{Elt: param_type}
- }
- param_types = append(param_types, param_type.LLVMType())
- }
-
- var return_type llvm.Type
- switch len(f.Results) {
- case 0:
- return_type = llvm.VoidType()
- case 1:
- return_type = (f.Results[0].Type.(Type)).LLVMType()
- default:
- elements := make([]llvm.Type, len(f.Results))
- for i, result := range f.Results {
- elements[i] = result.Type.(Type).LLVMType()
- }
- return_type = llvm.StructType(elements, false)
- }
-
- fn_type := llvm.FunctionType(return_type, param_types, false)
- return llvm.PointerType(fn_type, 0)
-
- /*
- if fn_name == "init" {
- // Make init functions anonymous
- fn_name = ""
- } else if f.Recv != nil {
- return_type := llvm.VoidType() //fn_type.ReturnType() TODO
- param_types := make([]llvm.Type, 0) //fn_type.ParamTypes()
- isvararg := fn_type.IsVariadic
-
- // Add receiver as the first parameter type.
- recv_type := c.GetType(f.Recv.List[0].Type)
- if recv_type != nil {
- param_types = append(param_types, recv_type.LLVMType())
- }
-
- for _, param := range fn_type.Params {
- param_type := param.Type.(Type)
- param_types = append(param_types, param_type.LLVMType())
- }
-
- fn_type = llvm.FunctionType(return_type, param_types, isvararg)
- }
-
- return fn_type
- */
-}
-
// An Interface represents an interface type interface{...}.
type Interface struct {
+ ImplementsType
Methods ObjList // interface methods sorted by name; or nil
}
func (i *Interface) String() string {
return fmt.Sprint("Interface(", i.Methods, ")")
}
-func (i *Interface) LLVMType() llvm.Type {
- ptr_type := llvm.PointerType(llvm.Int8Type(), 0)
- elements := make([]llvm.Type, 1+len(i.Methods))
- elements[0] = ptr_type // value
- for n, m := range i.Methods {
- fnptr := Pointer{Base: m.Type.(Type)}
- elements[n+1] = fnptr.LLVMType()
- }
- return llvm.StructType(elements, false)
-}
-
// A Map represents a map type map[Key]Elt.
type Map struct {
+ ImplementsType
Key, Elt Type
}
func (m *Map) String() string {
return fmt.Sprint("Map(", m.Key, ", ", m.Elt, ")")
}
-func (m *Map) LLVMType() llvm.Type {
- return llvm.Type{nil} // TODO
-}
-
// A Chan represents a channel type chan Elt, <-chan Elt, or chan<-Elt.
type Chan struct {
+ ImplementsType
Dir ast.ChanDir
Elt Type
}
@@ -297,33 +169,26 @@ func (c *Chan) String() string {
return fmt.Sprint("Chan(", c.Dir, ", ", c.Elt, ")")
}
-func (c *Chan) LLVMType() llvm.Type {
- return llvm.Type{nil} // TODO
-}
-
// A Name represents a named type as declared in a type declaration.
type Name struct {
+ ImplementsType
Underlying Type // nil if not fully declared
Obj *ast.Object // corresponding declared object
Methods ObjList
// TODO(gri) need to remember fields and methods.
- visited bool
}
func (n *Name) String() string {
- if !n.visited {
- n.visited = true
- res := fmt.Sprint("Name(", n.Obj.Name, ", ", n.Underlying, ")")
- n.visited = false
+ u := n.Underlying
+ if u != nil {
+ n.Underlying = nil
+ res := fmt.Sprint("Name(", n.Obj.Name, ", ", u, ")")
+ n.Underlying = u
return res
}
return fmt.Sprint("Name(", n.Obj.Name, ", ...)")
}
-func (n *Name) LLVMType() llvm.Type {
- return n.Underlying.LLVMType()
-}
-
// typ must be a pointer type; Deref returns the pointer's base type.
func Deref(typ Type) Type {
return typ.(*Pointer).Base
View
2 types/universe.go
@@ -111,7 +111,7 @@ func init() {
nil_ := defConst("nil")
nil_.Data = &Const{}
- nil_.Type = &Basic{NilKind}
+ nil_.Type = &Basic{Kind: NilKind}
defFun("append")
defFun("cap")
View
45 value.go
@@ -89,9 +89,9 @@ func (c *compiler) NewConstValue(tok token.Token, lit string) ConstValue {
case token.IMAG:
typ = &types.Basic{Kind: types.UntypedComplexKind}
case token.CHAR:
- typ = &types.Basic{Kind: types.Int32Kind} // rune
+ typ = types.Rune.Underlying.(*types.Basic)
case token.STRING:
- typ = &types.Basic{Kind: types.StringKind}
+ typ = types.String.Underlying.(*types.Basic)
}
return ConstValue{*types.MakeConst(tok, lit), c, typ}
}
@@ -175,22 +175,22 @@ func (lhs *LLVMValue) BinaryOp(op token.Token, rhs_ Value) Value {
result = b.CreateSub(lhs.value, rhs.value, "")
case token.NEQ:
result = b.CreateICmp(llvm.IntNE, lhs.value, rhs.value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.EQL:
result = b.CreateICmp(llvm.IntEQ, lhs.value, rhs.value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.LSS:
result = b.CreateICmp(llvm.IntULT, lhs.value, rhs.value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.LEQ: // TODO signed/unsigned
result = b.CreateICmp(llvm.IntULE, lhs.value, rhs.value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.LAND:
result = b.CreateAnd(lhs.value, rhs.value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.LOR:
result = b.CreateOr(lhs.value, rhs.value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
default:
panic(fmt.Sprint("Unimplemented operator: ", op))
}
@@ -225,22 +225,22 @@ func (lhs *LLVMValue) BinaryOp(op token.Token, rhs_ Value) Value {
result = b.CreateSub(lhs.value, rhs_value, "")
case token.NEQ:
result = b.CreateICmp(llvm.IntNE, lhs.value, rhs_value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.EQL:
result = b.CreateICmp(llvm.IntEQ, lhs.value, rhs_value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.LSS:
result = b.CreateICmp(llvm.IntULT, lhs.value, rhs_value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.LEQ: // TODO signed/unsigned
result = b.CreateICmp(llvm.IntULE, lhs.value, rhs_value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.LAND:
result = b.CreateAnd(lhs.value, rhs_value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.LOR:
result = b.CreateOr(lhs.value, rhs_value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
default:
panic(fmt.Sprint("Unimplemented operator: ", op))
}
@@ -305,8 +305,7 @@ func (v *LLVMValue) Convert(typ types.Type) Value {
// value or pointer receivers.
iface_elements := make([]llvm.Value, 1+len(interface_.Methods))
-
- iface_struct_type := interface_.LLVMType()
+ iface_struct_type := v.compiler.types.ToLLVM(interface_)
element_types := iface_struct_type.StructElementTypes()
for i, _ := range iface_elements {
iface_elements[i] = llvm.ConstNull(element_types[i])
@@ -318,7 +317,7 @@ func (v *LLVMValue) Convert(typ types.Type) Value {
if isptr {
ptr = v.LLVMValue()
} else {
- ptr = builder.CreateMalloc(srctyp.LLVMType(), "")
+ ptr = builder.CreateMalloc(v.compiler.types.ToLLVM(srctyp), "")
}
ptr = builder.CreateBitCast(ptr, element_types[0], "")
iface_struct = builder.CreateInsertValue(iface_struct, ptr, 0, "")
@@ -428,19 +427,19 @@ func (lhs ConstValue) BinaryOp(op token.Token, rhs_ Value) Value {
result = b.CreateSub(lhs_value, rhs.value, "")
case token.NEQ:
result = b.CreateICmp(llvm.IntNE, lhs_value, rhs.value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.EQL:
result = b.CreateICmp(llvm.IntEQ, lhs_value, rhs.value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.LSS:
result = b.CreateICmp(llvm.IntULT, lhs_value, rhs.value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.LAND:
result = b.CreateAnd(lhs_value, rhs.value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
case token.LOR:
result = b.CreateOr(lhs_value, rhs.value, "")
- return lhs.compiler.NewLLVMValue(result, &types.Basic{types.BoolKind})
+ return lhs.compiler.NewLLVMValue(result, types.Bool)
default:
panic(fmt.Sprint("Unimplemented operator: ", op))
}
@@ -470,7 +469,7 @@ func (v ConstValue) Convert(typ types.Type) Value {
} else {
// Special case for 'nil'
if v.typ.Kind == types.NilKind {
- zero := llvm.ConstNull(typ.LLVMType())
+ zero := llvm.ConstNull(compiler.types.ToLLVM(typ))
return compiler.NewLLVMValue(zero, typ)
}
panic("unhandled conversion")

No commit comments for this range

Something went wrong with that request. Please try again.