compiler: improve error locations in goroutine lowering

Этот коммит содержится в:
Ayke van Laethem 2019-12-21 14:56:48 +01:00 коммит произвёл Ron Evans
родитель 072f8c354e
коммит 74e32acf33

Просмотреть файл

@ -104,7 +104,6 @@ package compiler
// scheduler, which runs in the background scheduling all coroutines. // scheduler, which runs in the background scheduling all coroutines.
import ( import (
"errors"
"fmt" "fmt"
"strings" "strings"
@ -283,7 +282,7 @@ func (c *Compiler) markAsyncFunctions() (needsScheduler bool, err error) {
if use.IsConstant() && use.Opcode() == llvm.PtrToInt { if use.IsConstant() && use.Opcode() == llvm.PtrToInt {
for _, call := range getUses(use) { for _, call := range getUses(use) {
if call.IsACallInst().IsNil() || call.CalledValue().Name() != "runtime.makeGoroutine" { if call.IsACallInst().IsNil() || call.CalledValue().Name() != "runtime.makeGoroutine" {
return false, errors.New("async function " + f.Name() + " incorrectly used in ptrtoint, expected runtime.makeGoroutine") return false, errorAt(call, "async function incorrectly used in ptrtoint, expected runtime.makeGoroutine")
} }
} }
// This is a go statement. Do not mark the parent as async, as // This is a go statement. Do not mark the parent as async, as
@ -303,12 +302,19 @@ func (c *Compiler) markAsyncFunctions() (needsScheduler bool, err error) {
// Not a call instruction. Maybe a store to a global? In any // Not a call instruction. Maybe a store to a global? In any
// case, this requires support for async calls across function // case, this requires support for async calls across function
// pointers which is not yet supported. // pointers which is not yet supported.
return false, errors.New("async function " + f.Name() + " used as function pointer") at := use
if use.IsAInstruction().IsNil() {
// The use might not be an instruction (for example, in the
// case of a const bitcast). Fall back to reporting the
// location of the function instead.
at = f
}
return false, errorAt(at, "async function "+f.Name()+" used as function pointer")
} }
parent := use.InstructionParent().Parent() parent := use.InstructionParent().Parent()
for i := 0; i < use.OperandsCount()-1; i++ { for i := 0; i < use.OperandsCount()-1; i++ {
if use.Operand(i) == f { if use.Operand(i) == f {
return false, errors.New("async function " + f.Name() + " used as function pointer in " + parent.Name()) return false, errorAt(use, "async function "+f.Name()+" used as function pointer")
} }
} }
worklist = append(worklist, parent) worklist = append(worklist, parent)
@ -906,12 +912,12 @@ func (c *Compiler) lowerMakeGoroutineCalls(sched bool) error {
origFunc := ptrtointIn.Operand(0) origFunc := ptrtointIn.Operand(0)
uses := getUses(goroutine) uses := getUses(goroutine)
if len(uses) != 1 || uses[0].IsAIntToPtrInst().IsNil() { if len(uses) != 1 || uses[0].IsAIntToPtrInst().IsNil() {
return errors.New("expected exactly 1 inttoptr use of runtime.makeGoroutine") return errorAt(makeGoroutine, "expected exactly 1 inttoptr use of runtime.makeGoroutine")
} }
inttoptrOut := uses[0] inttoptrOut := uses[0]
uses = getUses(inttoptrOut) uses = getUses(inttoptrOut)
if len(uses) != 1 || uses[0].IsACallInst().IsNil() { if len(uses) != 1 || uses[0].IsACallInst().IsNil() {
return errors.New("expected exactly 1 call use of runtime.makeGoroutine bitcast") return errorAt(inttoptrOut, "expected exactly 1 call use of runtime.makeGoroutine bitcast")
} }
realCall := uses[0] realCall := uses[0]