MCPcopy Index your code
hub / github.com/tinygo-org/tinygo / createMapLookup

Method createMapLookup

compiler/map.go:56–116  ·  view source on GitHub ↗

createMapLookup returns the value in a map. It calls a runtime function depending on the map key type to load the map value and its comma-ok value.

(keyType, valueType types.Type, m, key llvm.Value, commaOk bool, pos token.Pos)

Source from the content-addressed store, hash-verified

54// createMapLookup returns the value in a map. It calls a runtime function
55// depending on the map key type to load the map value and its comma-ok value.
56func (b *builder) createMapLookup(keyType, valueType types.Type, m, key llvm.Value, commaOk bool, pos token.Pos) (llvm.Value, error) {
57 llvmValueType := b.getLLVMType(valueType)
58
59 // Allocate the memory for the resulting type. Do not zero this memory: it
60 // will be zeroed by the hashmap get implementation if the key is not
61 // present in the map.
62 mapValueAlloca, mapValueAllocaSize := b.createTemporaryAlloca(llvmValueType, "hashmap.value")
63
64 // We need the map size (with type uintptr) to pass to the hashmap*Get
65 // functions. This is necessary because those *Get functions are valid on
66 // nil maps, and they'll need to zero the value pointer by that number of
67 // bytes.
68 mapValueSize := mapValueAllocaSize
69 if mapValueSize.Type().IntTypeWidth() > b.uintptrType.IntTypeWidth() {
70 mapValueSize = llvm.ConstTrunc(mapValueSize, b.uintptrType)
71 }
72
73 // Do the lookup. How it is done depends on the key type.
74 var commaOkValue llvm.Value
75 origKeyType := keyType
76 keyType = keyType.Underlying()
77 if t, ok := keyType.(*types.Basic); ok && t.Info()&types.IsString != 0 {
78 // key is a string
79 params := []llvm.Value{m, key, mapValueAlloca, mapValueSize}
80 commaOkValue = b.createRuntimeCall("hashmapStringGet", params, "")
81 } else if hashmapIsBinaryKey(keyType) {
82 // key can be compared with runtime.memequal
83 // Store the key in an alloca, in the entry block to avoid dynamic stack
84 // growth.
85 mapKeyAlloca, mapKeySize := b.createTemporaryAlloca(key.Type(), "hashmap.key")
86 b.CreateStore(key, mapKeyAlloca)
87 b.zeroUndefBytes(b.getLLVMType(keyType), mapKeyAlloca)
88 // Fetch the value from the hashmap.
89 params := []llvm.Value{m, mapKeyAlloca, mapValueAlloca, mapValueSize}
90 commaOkValue = b.createRuntimeCall("hashmapBinaryGet", params, "")
91 b.emitLifetimeEnd(mapKeyAlloca, mapKeySize)
92 } else {
93 // Not trivially comparable using memcmp. Make it an interface instead.
94 itfKey := key
95 if _, ok := keyType.(*types.Interface); !ok {
96 // Not already an interface, so convert it to an interface now.
97 itfKey = b.createMakeInterface(key, origKeyType, pos)
98 }
99 params := []llvm.Value{m, itfKey, mapValueAlloca, mapValueSize}
100 commaOkValue = b.createRuntimeCall("hashmapInterfaceGet", params, "")
101 }
102
103 // Load the resulting value from the hashmap. The value is set to the zero
104 // value if the key doesn't exist in the hashmap.
105 mapValue := b.CreateLoad(llvmValueType, mapValueAlloca, "")
106 b.emitLifetimeEnd(mapValueAlloca, mapValueAllocaSize)
107
108 if commaOk {
109 tuple := llvm.Undef(b.ctx.StructType([]llvm.Type{llvmValueType, b.ctx.Int1Type()}, false))
110 tuple = b.CreateInsertValue(tuple, mapValue, 0, "")
111 tuple = b.CreateInsertValue(tuple, commaOkValue, 1, "")
112 return tuple, nil
113 } else {

Callers 1

createExprMethod · 0.95

Calls 9

createTemporaryAllocaMethod · 0.95
createRuntimeCallMethod · 0.95
zeroUndefBytesMethod · 0.95
emitLifetimeEndMethod · 0.95
createMakeInterfaceMethod · 0.95
hashmapIsBinaryKeyFunction · 0.85
getLLVMTypeMethod · 0.80
InfoMethod · 0.80
TypeMethod · 0.45

Tested by

no test coverage detected