From 005665aee6288551ddfeb75349808e238709288a Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Thu, 23 Aug 2018 23:12:27 +0200 Subject: [PATCH] Move hashmap creation to runtime --- compiler.go | 41 +++++------------------------------------ src/runtime/hashmap.go | 12 ++++++++++++ 2 files changed, 17 insertions(+), 36 deletions(-) diff --git a/compiler.go b/compiler.go index 6d4024ac..259bd15c 100644 --- a/compiler.go +++ b/compiler.go @@ -1529,44 +1529,13 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) { switch keyType := mapType.Key().Underlying().(type) { case *types.Basic: if keyType.Kind() == types.String { - // Create hashmap - llvmType := c.mod.GetTypeByName("runtime.hashmap") - size := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(llvmType), false) - buf := c.builder.CreateCall(c.allocFunc, []llvm.Value{size}, "") - buf = c.builder.CreateBitCast(buf, llvm.PointerType(llvmType, 0), "") - - // Set keySize keySize := c.targetData.TypeAllocSize(llvmKeyType) - keyIndices := []llvm.Value{ - llvm.ConstInt(llvm.Int32Type(), 0, false), - llvm.ConstInt(llvm.Int32Type(), 3, false), // keySize uint8 - } - keySizePtr := c.builder.CreateGEP(buf, keyIndices, "hashmap.keySize") - c.builder.CreateStore(llvm.ConstInt(llvm.Int8Type(), keySize, false), keySizePtr) - - // Set valueSize valueSize := c.targetData.TypeAllocSize(llvmValueType) - valueIndices := []llvm.Value{ - llvm.ConstInt(llvm.Int32Type(), 0, false), - llvm.ConstInt(llvm.Int32Type(), 4, false), // valueSize uint8 - } - valueSizePtr := c.builder.CreateGEP(buf, valueIndices, "hashmap.valueSize") - c.builder.CreateStore(llvm.ConstInt(llvm.Int8Type(), valueSize, false), valueSizePtr) - - // Create initial bucket - bucketType := c.mod.GetTypeByName("runtime.hashmapBucket") - bucketSize := c.targetData.TypeAllocSize(bucketType) + keySize*8 + valueSize*8 - bucketSizeValue := llvm.ConstInt(c.uintptrType, bucketSize, false) - bucket := c.builder.CreateCall(c.allocFunc, []llvm.Value{bucketSizeValue}, "") - - // Set initial bucket - bucketIndices := []llvm.Value{ - llvm.ConstInt(llvm.Int32Type(), 0, false), - llvm.ConstInt(llvm.Int32Type(), 1, false), // buckets unsafe.Pointer - } - bucketsElementPtr := c.builder.CreateGEP(buf, bucketIndices, "hashmap.buckets") - c.builder.CreateStore(bucket, bucketsElementPtr) - return buf, nil + hashmapMake := c.mod.NamedFunction("runtime.hashmapMake") + llvmKeySize := llvm.ConstInt(llvm.Int8Type(), keySize, false) + llvmValueSize := llvm.ConstInt(llvm.Int8Type(), valueSize, false) + hashmap := c.builder.CreateCall(hashmapMake, []llvm.Value{llvmKeySize, llvmValueSize}, "") + return hashmap, nil } else { return llvm.Value{}, errors.New("todo: map key type: " + keyType.String()) } diff --git a/src/runtime/hashmap.go b/src/runtime/hashmap.go index ce8b356e..74eb9c70 100644 --- a/src/runtime/hashmap.go +++ b/src/runtime/hashmap.go @@ -42,6 +42,18 @@ func stringhash(s *string) uint32 { return result } +// Create a new hashmap with the given keySize and valueSize. +func hashmapMake(keySize, valueSize uint8) *hashmap { + bucketBufSize := unsafe.Sizeof(hashmapBucket{}) + uintptr(keySize)*8 + uintptr(valueSize)*8 + bucket := alloc(bucketBufSize) + return &hashmap{ + buckets: bucket, + keySize: keySize, + valueSize: valueSize, + bucketBits: 0, + } +} + // Set a specified key to a given value. Grow the map if necessary. func hashmapSet(m *hashmap, key string, value unsafe.Pointer) { hash := stringhash(&key)