@@ -30,33 +30,29 @@ func (b *builder) createMakeChan(expr *ssa.MakeChan) llvm.Value {
3030// actual channel send operation during goroutine lowering.
3131func (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