From 9f2bcfe5e316424ebf8b1cd2cb38ad1ff98d7887 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 25 Aug 2018 02:58:00 +0200 Subject: [PATCH] Implement global interface variable constant --- compiler.go | 31 ++++++++++++++++++++++++++++++- interpreter.go | 7 +++++++ passes.go | 4 ++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/compiler.go b/compiler.go index f7eed444..637bb82c 100644 --- a/compiler.go +++ b/compiler.go @@ -748,6 +748,18 @@ func (c *Compiler) getInterpretedValue(value Value) (llvm.Value, error) { ptr := llvm.ConstInBoundsGEP(value.Global.llvmGlobal, []llvm.Value{zero}) return ptr, nil + case *InterfaceValue: + itfTypeNum, ok := c.ir.TypeNum(value.Type) + if !ok { + panic("interface number is unknown") + } + fields := []llvm.Value{ + llvm.ConstInt(llvm.Int32Type(), uint64(itfTypeNum), false), + llvm.Undef(c.i8ptrType), + } + itf := llvm.ConstNamedStruct(c.mod.GetTypeByName("interface"), fields) + return itf, nil + case *MapValue: // Create initial bucket. firstBucketGlobal, keySize, valueSize, err := c.initMapNewBucket(value.Type) @@ -1929,14 +1941,31 @@ func (c *Compiler) parseConst(expr *ssa.Const) (llvm.Value, error) { } else { return llvm.Value{}, errors.New("todo: unknown constant: " + typ.String()) } + case *types.Interface: + if expr.Value != nil { + return llvm.Value{}, errors.New("non-nil interface constant") + } + itfTypeNum, ok := c.ir.TypeNum(expr.Type()) + if !ok { + panic("interface number is unknown") + } + fields := []llvm.Value{ + llvm.ConstInt(llvm.Int32Type(), uint64(itfTypeNum), false), + llvm.Undef(c.i8ptrType), + } + itf := llvm.ConstNamedStruct(c.mod.GetTypeByName("interface"), fields) + return itf, nil case *types.Pointer: + if expr.Value != nil { + return llvm.Value{}, errors.New("non-nil pointer constant") + } llvmType, err := c.getLLVMType(typ) if err != nil { return llvm.Value{}, err } return llvm.ConstPointerNull(llvmType), nil default: - return llvm.Value{}, errors.New("todo: unknown constant: " + typ.String()) + return llvm.Value{}, errors.New("todo: unknown constant: " + expr.String()) } } diff --git a/interpreter.go b/interpreter.go index f7c618f0..f7638d9e 100644 --- a/interpreter.go +++ b/interpreter.go @@ -224,6 +224,8 @@ func (p *Program) getZeroValue(t types.Type) (Value, error) { return &ArrayValue{typ.Elem(), elems}, nil case *types.Basic: return &ZeroBasicValue{typ}, nil + case *types.Interface: + return &InterfaceValue{typ}, nil case *types.Pointer: return &PointerValue{nil}, nil case *types.Struct: @@ -259,6 +261,11 @@ type PointerValue struct { Elem *Value } +type InterfaceValue struct { + Type *types.Interface + //Elem Value +} + type PointerBitCastValue struct { Type types.Type Elem Value diff --git a/passes.go b/passes.go index e81748ae..5ab4b751 100644 --- a/passes.go +++ b/passes.go @@ -90,8 +90,8 @@ func (p *Program) AnalyseCallgraph() { // Find all types that are put in an interface. func (p *Program) AnalyseInterfaceConversions() { // Clear, if AnalyseTypes has been called before. - p.typesWithMethods = make(map[string]*InterfaceType) - p.typesWithoutMethods = make(map[string]int) + p.typesWithoutMethods = map[string]int{"interface{}": 0} + p.typesWithMethods = map[string]*InterfaceType{} for _, f := range p.Functions { for _, block := range f.fn.Blocks {