runtime: MakeMap
This commit is contained in:
10
cl/_testrt/map/in.go
Normal file
10
cl/_testrt/map/in.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a := map[int]int{23: 100, 7: 29}
|
||||||
|
c.Printf(c.Str("Hello %d\n"), a[23])
|
||||||
|
}
|
||||||
0
cl/_testrt/map/out.ll
Normal file
0
cl/_testrt/map/out.ll
Normal file
@@ -390,6 +390,12 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
case *ssa.FieldAddr:
|
case *ssa.FieldAddr:
|
||||||
x := p.compileValue(b, v.X)
|
x := p.compileValue(b, v.X)
|
||||||
ret = b.FieldAddr(x, v.Field)
|
ret = b.FieldAddr(x, v.Field)
|
||||||
|
case *ssa.Alloc:
|
||||||
|
t := v.Type().(*types.Pointer)
|
||||||
|
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ret = b.Alloc(t, v.Heap)
|
||||||
case *ssa.IndexAddr:
|
case *ssa.IndexAddr:
|
||||||
vx := v.X
|
vx := v.X
|
||||||
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs index
|
if _, ok := p.isVArgs(vx); ok { // varargs: this is a varargs index
|
||||||
@@ -415,12 +421,13 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue
|
|||||||
max = p.compileValue(b, v.Max)
|
max = p.compileValue(b, v.Max)
|
||||||
}
|
}
|
||||||
ret = b.Slice(x, low, high, max)
|
ret = b.Slice(x, low, high, max)
|
||||||
case *ssa.Alloc:
|
case *ssa.MakeMap:
|
||||||
t := v.Type().(*types.Pointer)
|
var nReserve llssa.Expr
|
||||||
if p.checkVArgs(v, t) { // varargs: this is a varargs allocation
|
t := v.Type()
|
||||||
return
|
if v.Reserve != nil {
|
||||||
|
nReserve = p.compileValue(b, v.Reserve)
|
||||||
}
|
}
|
||||||
ret = b.Alloc(t, v.Heap)
|
ret = b.MakeMap(p.prog.Type(t), nReserve)
|
||||||
case *ssa.MakeInterface:
|
case *ssa.MakeInterface:
|
||||||
const (
|
const (
|
||||||
delayExpr = true // varargs: don't need to convert an expr to any
|
delayExpr = true // varargs: don't need to convert an expr to any
|
||||||
@@ -481,6 +488,7 @@ func (p *context) compileInstr(b llssa.Builder, instr ssa.Instruction) {
|
|||||||
thenb := fn.Block(succs[0].Index)
|
thenb := fn.Block(succs[0].Index)
|
||||||
elseb := fn.Block(succs[1].Index)
|
elseb := fn.Block(succs[1].Index)
|
||||||
b.If(cond, thenb, elseb)
|
b.If(cond, thenb, elseb)
|
||||||
|
case *ssa.MapUpdate:
|
||||||
case *ssa.Panic:
|
case *ssa.Panic:
|
||||||
arg := p.compileValue(b, v.X).Do()
|
arg := p.compileValue(b, v.X).Do()
|
||||||
b.Panic(arg)
|
b.Panic(arg)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func testCompile(t *testing.T, src, expected string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestrt(t *testing.T) {
|
func TestFromTestrt(t *testing.T) {
|
||||||
cltest.FromDir(t, "", "./_testrt", true)
|
cltest.FromDir(t, "map", "./_testrt", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestdata(t *testing.T) {
|
func TestFromTestdata(t *testing.T) {
|
||||||
|
|||||||
14
internal/abi/map.go
Normal file
14
internal/abi/map.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package abi
|
||||||
|
|
||||||
|
// Map constants common to several packages
|
||||||
|
// runtime/runtime-gdb.py:MapTypePrinter contains its own copy
|
||||||
|
const (
|
||||||
|
MapBucketCountBits = 3 // log2 of number of elements in a bucket.
|
||||||
|
MapBucketCount = 1 << MapBucketCountBits
|
||||||
|
MapMaxKeyBytes = 128 // Must fit in a uint8.
|
||||||
|
MapMaxElemBytes = 128 // Must fit in a uint8.
|
||||||
|
)
|
||||||
@@ -35,6 +35,9 @@ func AllocaCStr(s string) *int8
|
|||||||
//go:linkname Unreachable llgo.unreachable
|
//go:linkname Unreachable llgo.unreachable
|
||||||
func Unreachable()
|
func Unreachable()
|
||||||
|
|
||||||
|
//go:linkname Rand C.rand
|
||||||
|
func Rand() C.int
|
||||||
|
|
||||||
//go:linkname Malloc C.malloc
|
//go:linkname Malloc C.malloc
|
||||||
func Malloc(size uintptr) unsafe.Pointer
|
func Malloc(size uintptr) unsafe.Pointer
|
||||||
|
|
||||||
|
|||||||
1726
internal/runtime/map.go
Normal file
1726
internal/runtime/map.go
Normal file
File diff suppressed because it is too large
Load Diff
39
internal/runtime/stubs.go
Normal file
39
internal/runtime/stubs.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func fastrand() uint32 {
|
||||||
|
return uint32(c.Rand())
|
||||||
|
/* TODO(xsw):
|
||||||
|
|
||||||
|
mp := getg().m
|
||||||
|
// Implement wyrand: https://github.com/wangyi-fudan/wyhash
|
||||||
|
// Only the platform that math.Mul64 can be lowered
|
||||||
|
// by the compiler should be in this list.
|
||||||
|
if goarch.IsAmd64|goarch.IsArm64|goarch.IsPpc64|
|
||||||
|
goarch.IsPpc64le|goarch.IsMips64|goarch.IsMips64le|
|
||||||
|
goarch.IsS390x|goarch.IsRiscv64|goarch.IsLoong64 == 1 {
|
||||||
|
mp.fastrand += 0xa0761d6478bd642f
|
||||||
|
hi, lo := math.Mul64(mp.fastrand, mp.fastrand^0xe7037ed1a0b428db)
|
||||||
|
return uint32(hi ^ lo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement xorshift64+: 2 32-bit xorshift sequences added together.
|
||||||
|
// Shift triplet [17,7,16] was calculated as indicated in Marsaglia's
|
||||||
|
// Xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
|
||||||
|
// This generator passes the SmallCrush suite, part of TestU01 framework:
|
||||||
|
// http://simul.iro.umontreal.ca/testu01/tu01.html
|
||||||
|
t := (*[2]uint32)(unsafe.Pointer(&mp.fastrand))
|
||||||
|
s1, s0 := t[0], t[1]
|
||||||
|
s1 ^= s1 << 17
|
||||||
|
s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16
|
||||||
|
t[0], t[1] = s0, s1
|
||||||
|
return s0 + s1
|
||||||
|
*/
|
||||||
|
}
|
||||||
@@ -16,3 +16,21 @@ import (
|
|||||||
type _type = abi.Type
|
type _type = abi.Type
|
||||||
|
|
||||||
type interfacetype = abi.InterfaceType
|
type interfacetype = abi.InterfaceType
|
||||||
|
|
||||||
|
type maptype = abi.MapType
|
||||||
|
|
||||||
|
/*
|
||||||
|
type arraytype = abi.ArrayType
|
||||||
|
|
||||||
|
type chantype = abi.ChanType
|
||||||
|
|
||||||
|
type slicetype = abi.SliceType
|
||||||
|
|
||||||
|
type functype = abi.FuncType
|
||||||
|
|
||||||
|
type ptrtype = abi.PtrType
|
||||||
|
|
||||||
|
type name = abi.Name
|
||||||
|
|
||||||
|
type structtype = abi.StructType
|
||||||
|
*/
|
||||||
|
|||||||
25
internal/runtime/z_map.go
Normal file
25
internal/runtime/z_map.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
// Map represents a Go map.
|
||||||
|
type Map = hmap
|
||||||
|
|
||||||
|
// MakeSmallMap creates a new small map.
|
||||||
|
func MakeSmallMap() *Map {
|
||||||
|
return makemap_small()
|
||||||
|
}
|
||||||
27
ssa/expr.go
27
ssa/expr.go
@@ -35,6 +35,8 @@ type Expr struct {
|
|||||||
Type
|
Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Nil Expr // Zero value is a nil Expr
|
||||||
|
|
||||||
// IsNil checks if the expression is nil or not.
|
// IsNil checks if the expression is nil or not.
|
||||||
func (v Expr) IsNil() bool {
|
func (v Expr) IsNil() bool {
|
||||||
return v.Type == nil
|
return v.Type == nil
|
||||||
@@ -477,6 +479,31 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// The MakeMap instruction creates a new hash-table-based map object
|
||||||
|
// and yields a value of kind map.
|
||||||
|
//
|
||||||
|
// t is a (possibly named) *types.Map.
|
||||||
|
//
|
||||||
|
// Pos() returns the ast.CallExpr.Lparen, if created by make(map), or
|
||||||
|
// the ast.CompositeLit.Lbrack if created by a literal.
|
||||||
|
//
|
||||||
|
// Example printed form:
|
||||||
|
//
|
||||||
|
// t1 = make map[string]int t0
|
||||||
|
// t1 = make StringIntMap t0
|
||||||
|
func (b Builder) MakeMap(t Type, nReserve Expr) (ret Expr) {
|
||||||
|
if debugInstr {
|
||||||
|
log.Printf("MakeMap %v, %v\n", t, nReserve.impl)
|
||||||
|
}
|
||||||
|
pkg := b.fn.pkg
|
||||||
|
ret.Type = t
|
||||||
|
ret.impl = b.InlineCall(pkg.rtFunc("MakeSmallMap")).impl
|
||||||
|
// TODO(xsw): nReserve
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// The Alloc instruction reserves space for a variable of the given type,
|
// The Alloc instruction reserves space for a variable of the given type,
|
||||||
// zero-initializes it, and yields its address.
|
// zero-initializes it, and yields its address.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ type aProgram struct {
|
|||||||
rtStringTy llvm.Type
|
rtStringTy llvm.Type
|
||||||
rtIfaceTy llvm.Type
|
rtIfaceTy llvm.Type
|
||||||
rtSliceTy llvm.Type
|
rtSliceTy llvm.Type
|
||||||
|
rtMapTy llvm.Type
|
||||||
|
|
||||||
anyTy Type
|
anyTy Type
|
||||||
voidTy Type
|
voidTy Type
|
||||||
@@ -184,6 +185,13 @@ func (p Program) rtIface() llvm.Type {
|
|||||||
return p.rtIfaceTy
|
return p.rtIfaceTy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Program) rtMap() llvm.Type {
|
||||||
|
if p.rtMapTy.IsNil() {
|
||||||
|
p.rtMapTy = p.rtType("Map").ll
|
||||||
|
}
|
||||||
|
return p.rtMapTy
|
||||||
|
}
|
||||||
|
|
||||||
func (p Program) rtSlice() llvm.Type {
|
func (p Program) rtSlice() llvm.Type {
|
||||||
if p.rtSliceTy.IsNil() {
|
if p.rtSliceTy.IsNil() {
|
||||||
p.rtSliceTy = p.rtType("Slice").ll
|
p.rtSliceTy = p.rtType("Slice").ll
|
||||||
|
|||||||
@@ -126,4 +126,20 @@ func (b Builder) If(cond Expr, thenb, elseb BasicBlock) {
|
|||||||
b.impl.CreateCondBr(cond.impl, thenb.impl, elseb.impl)
|
b.impl.CreateCondBr(cond.impl, thenb.impl, elseb.impl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The MapUpdate instruction updates the association of Map[Key] to
|
||||||
|
// Value.
|
||||||
|
//
|
||||||
|
// Pos() returns the ast.KeyValueExpr.Colon or ast.IndexExpr.Lbrack,
|
||||||
|
// if explicit in the source.
|
||||||
|
//
|
||||||
|
// Example printed form:
|
||||||
|
//
|
||||||
|
// t0[t1] = t2
|
||||||
|
func (b Builder) MapUpdate(m, k, v Expr) {
|
||||||
|
if debugInstr {
|
||||||
|
log.Printf("MapUpdate %v[%v] = %v\n", m.impl, k.impl, v.impl)
|
||||||
|
}
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -256,6 +256,7 @@ func (p Program) toLLVMType(typ types.Type) Type {
|
|||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
return &aType{p.rtSlice(), typ, vkInvalid}
|
return &aType{p.rtSlice(), typ, vkInvalid}
|
||||||
case *types.Map:
|
case *types.Map:
|
||||||
|
return &aType{p.rtMap(), typ, vkInvalid}
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
return p.toLLVMStruct(t)
|
return p.toLLVMStruct(t)
|
||||||
case *types.Named:
|
case *types.Named:
|
||||||
|
|||||||
Reference in New Issue
Block a user