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 {
|
if expr.IsString {
|
||||||
return b.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil
|
return b.createRuntimeCall("stringNext", []llvm.Value{llvmRangeVal, it}, "range.next"), nil
|
||||||
} else { // map
|
} else { // map
|
||||||
llvmKeyType := b.getLLVMType(rangeVal.Type().Underlying().(*types.Map).Key())
|
return b.createMapIteratorNext(rangeVal, llvmRangeVal, it), nil
|
||||||
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
|
|
||||||
}
|
}
|
||||||
case *ssa.Phi:
|
case *ssa.Phi:
|
||||||
phi := b.CreatePHI(b.getLLVMType(expr.Type()), "")
|
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
|
// Returns true if this key type does not contain strings, interfaces etc., so
|
||||||
// can be compared with runtime.memequal.
|
// can be compared with runtime.memequal.
|
||||||
func hashmapIsBinaryKey(keyType types.Type) bool {
|
func hashmapIsBinaryKey(keyType types.Type) bool {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче