Skip to content

Commit 857ecff

Browse files
authored
Merge branch 'tinygo-org:dev' into fix-cdc-large-packet
2 parents d88bdfd + 888d0c0 commit 857ecff

37 files changed

Lines changed: 3037 additions & 405 deletions

GNUmakefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -387,9 +387,7 @@ TEST_PACKAGES_FAST = \
387387

388388
# archive/zip requires os.ReadAt, which is not yet supported on windows
389389
# bytes requires mmap
390-
# compress/flate appears to hang on wasi; on all targets Go 1.27's new
391-
# compress/flate.indexTokens returns a ~262KB struct by value which crashes
392-
# LLVM's X86 instruction selector during LTO codegen
390+
# compress/flate appears to hang on wasi
393391
# crypto/aes needs reflect.Type.Method(), not yet implemented
394392
# crypto/des fails on wasi, needs panic()/recover()
395393
# crypto/hmac fails on wasi, it exits with a "slice out of range" panic
@@ -411,6 +409,7 @@ TEST_PACKAGES_FAST = \
411409
# Additional standard library packages that pass tests on individual platforms
412410
TEST_PACKAGES_LINUX := \
413411
archive/zip \
412+
compress/flate \
414413
context \
415414
crypto/aes \
416415
crypto/des \
@@ -438,6 +437,7 @@ TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
438437

439438
# os/user requires t.Skip() support
440439
TEST_PACKAGES_WINDOWS := \
440+
compress/flate \
441441
crypto/des \
442442
crypto/hmac \
443443
image \

compiler/calls.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ const (
3535

3636
// Whether this is a readonly parameter (for example, a string pointer).
3737
paramIsReadonly
38+
39+
// Whether this parameter is passed through backing storage.
40+
paramIsIndirect
3841
)
3942

4043
// createRuntimeCallCommon creates a runtime call. Use createRuntimeCall or
@@ -102,6 +105,18 @@ func (b *builder) createInvoke(fnType llvm.Type, fn llvm.Value, args []llvm.Valu
102105
// Expand an argument type to a list that can be used in a function call
103106
// parameter list.
104107
func (c *compilerContext) expandFormalParamType(t llvm.Type, name string, goType types.Type) []paramInfo {
108+
if c.isIndirectAggregate(t) {
109+
return []paramInfo{{
110+
llvmType: c.dataPtrType,
111+
name: name,
112+
elemSize: c.targetData.TypeAllocSize(t),
113+
flags: paramIsGoParam | paramIsReadonly | paramIsIndirect,
114+
}}
115+
}
116+
return c.expandDirectFormalParamType(t, name, goType)
117+
}
118+
119+
func (c *compilerContext) expandDirectFormalParamType(t llvm.Type, name string, goType types.Type) []paramInfo {
105120
switch t.TypeKind() {
106121
case llvm.StructTypeKind:
107122
fieldInfos := c.flattenAggregateType(t, name, goType)
@@ -115,6 +130,38 @@ func (c *compilerContext) expandFormalParamType(t llvm.Type, name string, goType
115130
return []paramInfo{c.getParamInfo(t, name, goType)}
116131
}
117132

133+
func (c *compilerContext) storedParamType(t llvm.Type, exported bool) llvm.Type {
134+
if c.isIndirectParam(t, exported) {
135+
return c.dataPtrType
136+
}
137+
return t
138+
}
139+
140+
func (c *compilerContext) isIndirectParam(t llvm.Type, exported bool) bool {
141+
return !exported && c.isIndirectAggregate(t)
142+
}
143+
144+
func (b *builder) appendStoredValueTypes(valueTypes []llvm.Type, values []ssa.Value, exported bool) []llvm.Type {
145+
for _, value := range values {
146+
valueTypes = append(valueTypes, b.storedParamType(b.getLLVMType(value.Type()), exported))
147+
}
148+
return valueTypes
149+
}
150+
151+
func (b *builder) appendStoredParamTypes(valueTypes []llvm.Type, params []*types.Var, exported bool) []llvm.Type {
152+
for _, param := range params {
153+
valueTypes = append(valueTypes, b.storedParamType(b.getLLVMType(param.Type()), exported))
154+
}
155+
return valueTypes
156+
}
157+
158+
func (b *builder) prependIndirectResult(sig *types.Signature, exported bool, params []llvm.Value, name string) []llvm.Value {
159+
if resultType, indirect := b.hasIndirectResult(sig); !exported && indirect {
160+
return append([]llvm.Value{b.createIndirectStorage(resultType, name)}, params...)
161+
}
162+
return params
163+
}
164+
118165
// expandFormalParamOffsets returns a list of offsets from the start of an
119166
// object of type t after it would have been split up by expandFormalParam. This
120167
// is useful for debug information, where it is necessary to know the offset

compiler/channel.go

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -30,33 +30,29 @@ func (b *builder) createMakeChan(expr *ssa.MakeChan) llvm.Value {
3030
// actual channel send operation during goroutine lowering.
3131
func (b *builder) createChanSend(instr *ssa.Send) {
3232
ch := b.getValue(instr.Chan, getPos(instr))
33-
chanValue := b.getValue(instr.X, getPos(instr))
3433

3534
// store value-to-send
3635
valueType := b.getLLVMType(instr.X.Type())
3736
isZeroSize := b.targetData.TypeAllocSize(valueType) == 0
38-
var valueAlloca, valueAllocaSize llvm.Value
37+
var storage valueStorage
3938
if isZeroSize {
40-
valueAlloca = llvm.ConstNull(b.dataPtrType)
39+
storage.ptr = llvm.ConstNull(b.dataPtrType)
4140
} else {
42-
valueAlloca, valueAllocaSize = b.createTemporaryAlloca(valueType, "chan.value")
43-
b.CreateStore(chanValue, valueAlloca)
41+
storage = b.getValueStorage(instr.X, "chan.value")
4442
}
4543

4644
// Allocate buffer for the channel operation.
4745
channelOp := b.getLLVMRuntimeType("channelOp")
4846
channelOpAlloca, channelOpAllocaSize := b.createTemporaryAlloca(channelOp, "chan.op")
4947

5048
// Do the send.
51-
b.createRuntimeInvoke("chanSend", []llvm.Value{ch, valueAlloca, channelOpAlloca}, "")
49+
b.createRuntimeInvoke("chanSend", []llvm.Value{ch, storage.ptr, channelOpAlloca}, "")
5250

5351
// End the lifetime of the allocas.
5452
// This also works around a bug in CoroSplit, at least in LLVM 8:
5553
// https://bugs.llvm.org/show_bug.cgi?id=41742
5654
b.emitLifetimeEnd(channelOpAlloca, channelOpAllocaSize)
57-
if !isZeroSize {
58-
b.emitLifetimeEnd(valueAlloca, valueAllocaSize)
59-
}
55+
b.endValueStorage(storage)
6056
}
6157

6258
// createChanRecv emits a pseudo chan receive operation. It is lowered to the
@@ -66,37 +62,17 @@ func (b *builder) createChanRecv(unop *ssa.UnOp) llvm.Value {
6662
ch := b.getValue(unop.X, getPos(unop))
6763

6864
// Allocate memory to receive into.
69-
isZeroSize := b.targetData.TypeAllocSize(valueType) == 0
70-
var valueAlloca, valueAllocaSize llvm.Value
71-
if isZeroSize {
72-
valueAlloca = llvm.ConstNull(b.dataPtrType)
73-
} else {
74-
valueAlloca, valueAllocaSize = b.createTemporaryAlloca(valueType, "chan.value")
75-
}
65+
result := b.createRuntimeValueResult(valueType, unop.CommaOk, true, "chan")
7666

7767
// Allocate buffer for the channel operation.
7868
channelOp := b.getLLVMRuntimeType("channelOp")
7969
channelOpAlloca, channelOpAllocaSize := b.createTemporaryAlloca(channelOp, "chan.op")
8070

8171
// Do the receive.
82-
commaOk := b.createRuntimeCall("chanRecv", []llvm.Value{ch, valueAlloca, channelOpAlloca}, "")
83-
var received llvm.Value
84-
if isZeroSize {
85-
received = llvm.ConstNull(valueType)
86-
} else {
87-
received = b.CreateLoad(valueType, valueAlloca, "chan.received")
88-
b.emitLifetimeEnd(valueAlloca, valueAllocaSize)
89-
}
72+
commaOk := b.createRuntimeCall("chanRecv", []llvm.Value{ch, result.valuePtr, channelOpAlloca}, "")
73+
received := result.finish(b, commaOk, "chan.received")
9074
b.emitLifetimeEnd(channelOpAlloca, channelOpAllocaSize)
91-
92-
if unop.CommaOk {
93-
tuple := llvm.Undef(b.ctx.StructType([]llvm.Type{valueType, b.ctx.Int1Type()}, false))
94-
tuple = b.CreateInsertValue(tuple, received, 0, "")
95-
tuple = b.CreateInsertValue(tuple, commaOk, 1, "")
96-
return tuple
97-
} else {
98-
return received
99-
}
75+
return received
10076
}
10177

10278
// createChanClose closes the given channel.
@@ -170,9 +146,7 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
170146
case types.SendOnly:
171147
// Store this value in an alloca and put a pointer to this alloca
172148
// in the send state.
173-
sendValue := b.getValue(state.Send, state.Pos)
174-
alloca := llvmutil.CreateEntryBlockAlloca(b.Builder, sendValue.Type(), "select.send.value")
175-
b.CreateStore(sendValue, alloca)
149+
alloca := b.getSelectSendStorage(state.Send)
176150
selectState = b.CreateInsertValue(selectState, alloca, 1, "")
177151
default:
178152
panic("unreachable")
@@ -280,7 +254,17 @@ func (b *builder) getChanSelectResult(expr *ssa.Extract) llvm.Value {
280254
// receive can proceed at a time) so we'll get that alloca, bitcast
281255
// it to the correct type, and dereference it.
282256
recvbuf := b.selectRecvBuf[expr.Tuple.(*ssa.Select)]
283-
typ := b.getLLVMType(expr.Type())
284-
return b.CreateLoad(typ, recvbuf, "")
257+
return b.loadFromStorage(recvbuf, expr.Type(), "select.received")
258+
}
259+
}
260+
261+
func (b *builder) getSelectSendStorage(value ssa.Value) llvm.Value {
262+
typ := b.getLLVMType(value.Type())
263+
if b.isIndirectAggregate(typ) {
264+
return b.getValuePointer(value)
285265
}
266+
llvmValue := b.getValue(value, getPos(value))
267+
ptr := llvmutil.CreateEntryBlockAlloca(b.Builder, typ, "select.send.value")
268+
b.CreateStore(llvmValue, ptr)
269+
return ptr
286270
}

0 commit comments

Comments
 (0)