compiler: move *ssa.Next lowering for maps to compiler/map.go
This moves it to the most logical place, as a preparation to fixing a bug in the next commit.
Этот коммит содержится в:
родитель
1903cf23c9
коммит
449bfe04f3
2 изменённых файлов: 21 добавлений и 14 удалений
|
@ -1792,20 +1792,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
|
|||
if expr.IsString {
|
||||
return b.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil
|
||||
} else { // map
|
||||
llvmKeyType := b.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Key())
|
||||
llvmValueType := b.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Elem())
|
||||
|
||||
mapKeyAlloca, mapKeyPtr, mapKeySize := b.createTemporaryAlloca(llvmKeyType, "range.key")
|
||||
mapValueAlloca, mapValuePtr, mapValueSize := b.createTemporaryAlloca(llvmValueType, "range.value")
|
||||
ok := b.createRuntimeCall("hashmapNext", []llvm.Value{llvmRangeVal, it, mapKeyPtr, mapValuePtr}, "range.next")
|
||||
|
||||
tuple := llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.Int1Type(), llvmKeyType, llvmValueType}, false))
|
||||
tuple = b.CreateInsertValue(tuple, ok, 0, "")
|
||||
tuple = b.CreateInsertValue(tuple, b.CreateLoad(mapKeyAlloca, ""), 1, "")
|
||||
tuple = b.CreateInsertValue(tuple, b.CreateLoad(mapValueAlloca, ""), 2, "")
|
||||
b.emitLifetimeEnd(mapKeyPtr, mapKeySize)
|
||||
b.emitLifetimeEnd(mapValuePtr, mapValueSize)
|
||||
return tuple, nil
|
||||
return b.createMapIteratorNext(rangeVal, llvmRangeVal, it), nil
|
||||
}
|
||||
case *ssa.Phi:
|
||||
phi := b.CreatePHI(b.getLLVMType(expr.Type()), "")
|
||||
|
|
|
@ -167,6 +167,26 @@ func (b *builder) createMapDelete(keyType types.Type, m, key llvm.Value, pos tok
|
|||
}
|
||||
}
|
||||
|
||||
// createMapIteratorNext lowers the *ssa.Next instruction for iterating over a
|
||||
// map. It returns a tuple of {bool, key, value} with the result of the
|
||||
// iteration.
|
||||
func (b *builder) createMapIteratorNext(rangeVal ssa.Value, llvmRangeVal, it llvm.Value) llvm.Value {
|
||||
llvmKeyType := b.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Key())
|
||||
llvmValueType := b.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Elem())
|
||||
|
||||
mapKeyAlloca, mapKeyPtr, mapKeySize := b.createTemporaryAlloca(llvmKeyType, "range.key")
|
||||
mapValueAlloca, mapValuePtr, mapValueSize := b.createTemporaryAlloca(llvmValueType, "range.value")
|
||||
ok := b.createRuntimeCall("hashmapNext", []llvm.Value{llvmRangeVal, it, mapKeyPtr, mapValuePtr}, "range.next")
|
||||
|
||||
tuple := llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.Int1Type(), llvmKeyType, llvmValueType}, false))
|
||||
tuple = b.CreateInsertValue(tuple, ok, 0, "")
|
||||
tuple = b.CreateInsertValue(tuple, b.CreateLoad(mapKeyAlloca, ""), 1, "")
|
||||
tuple = b.CreateInsertValue(tuple, b.CreateLoad(mapValueAlloca, ""), 2, "")
|
||||
b.emitLifetimeEnd(mapKeyPtr, mapKeySize)
|
||||
b.emitLifetimeEnd(mapValuePtr, mapValueSize)
|
||||
return tuple
|
||||
}
|
||||
|
||||
// Returns true if this key type does not contain strings, interfaces etc., so
|
||||
// can be compared with runtime.memequal.
|
||||
func hashmapIsBinaryKey(keyType types.Type) bool {
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче