From 14cbc1555d9a085602340452a8d1a9a2d7443880 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sun, 29 Apr 2018 00:48:42 +0200 Subject: [PATCH] compiler: Use zeroinitializer instead of memset --- tgo.go | 60 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/tgo.go b/tgo.go index 785afab1..568d0a4f 100644 --- a/tgo.go +++ b/tgo.go @@ -54,7 +54,6 @@ type Compiler struct { printbyteFunc llvm.Value printspaceFunc llvm.Value printnlFunc llvm.Value - memsetIntrinsic llvm.Value itfTypeNumbers map[types.Type]uint64 itfTypes []types.Type initFuncs []llvm.Value @@ -132,16 +131,6 @@ func NewCompiler(pkgName, triple string) (*Compiler, error) { printnlType := llvm.FunctionType(llvm.VoidType(), nil, false) c.printnlFunc = llvm.AddFunction(c.mod, "runtime.printnl", printnlType) - // Intrinsic functions - memsetType := llvm.FunctionType( - llvm.VoidType(), []llvm.Type{ - llvm.PointerType(llvm.Int8Type(), 0), - llvm.Int8Type(), - llvm.Int32Type(), - llvm.Int1Type(), - }, false) - c.memsetIntrinsic = llvm.AddFunction(c.mod, "llvm.memset.p0i8.i32", memsetType) - return c, nil } @@ -292,6 +281,39 @@ func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) { } } +func (c *Compiler) getZeroValue(typ llvm.Type) (llvm.Value, error) { + switch typ.TypeKind() { + case llvm.ArrayTypeKind: + subTyp := typ.ElementType() + vals := make([]llvm.Value, typ.ArrayLength()) + for i := range vals { + val, err := c.getZeroValue(subTyp) + if err != nil { + return llvm.Value{}, err + } + vals[i] = val + } + return llvm.ConstArray(subTyp, vals), nil + case llvm.IntegerTypeKind: + return llvm.ConstInt(typ, 0, false), nil + case llvm.PointerTypeKind: + return llvm.ConstPointerNull(typ), nil + case llvm.StructTypeKind: + types := typ.StructElementTypes() + vals := make([]llvm.Value, len(types)) + for i, subTyp := range types { + val, err := c.getZeroValue(subTyp) + if err != nil { + return llvm.Value{}, err + } + vals[i] = val + } + return llvm.ConstStruct(vals, false), nil + default: + return llvm.Value{}, errors.New("todo: LLVM zero initializer") + } +} + func (c *Compiler) getInterfaceType(typ types.Type) llvm.Value { if _, ok := c.itfTypeNumbers[typ]; !ok { num := uint64(len(c.itfTypes)) @@ -686,20 +708,14 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { } else { buf = c.builder.CreateAlloca(typ, expr.Comment) } - width := c.targetData.TypeAllocSize(typ) if err != nil { return llvm.Value{}, err } - llvmWidth := llvm.ConstInt(llvm.Int32Type(), width, false) - bufBytes := c.builder.CreateBitCast(buf, llvm.PointerType(llvm.Int8Type(), 0), "") - c.builder.CreateCall( - c.memsetIntrinsic, - []llvm.Value{ - bufBytes, - llvm.ConstInt(llvm.Int8Type(), 0, false), // value to set (zero) - llvmWidth, // size to zero - llvm.ConstInt(llvm.Int1Type(), 0, false), // volatile - }, "") + zero, err := c.getZeroValue(typ) + if err != nil { + return llvm.Value{}, err + } + c.builder.CreateStore(zero, buf) // zero-initialize var return buf, nil case *ssa.BinOp: return c.parseBinOp(frame, expr)