}
type AuxCall struct {
- // TODO(register args) this information is largely redundant with ../abi information, needs cleanup once new ABI is in place.
Fn *obj.LSym
- results []Param
- reg *regInfo // regInfo for this call // TODO for now nil means ignore
- abiInfo *abi.ABIParamResultInfo // TODO remove fields above redundant with this information.
+ reg *regInfo // regInfo for this call
+ abiInfo *abi.ABIParamResultInfo
}
// Reg returns the regInfo for a given call, combining the derived in/out register masks
return a.abiInfo.InParam(int(which)).Registers
}
+// NameOfResult returns the type of result which (indexed 0, 1, etc).
+func (a *AuxCall) NameOfResult(which int64) *ir.Name {
+ name := a.abiInfo.OutParam(int(which)).Name
+ if name == nil {
+ return nil
+ }
+ return name.(*ir.Name)
+}
+
// TypeOfResult returns the type of result which (indexed 0, 1, etc).
func (a *AuxCall) TypeOfResult(which int64) *types.Type {
return a.abiInfo.OutParam(int(which)).Type
return int64(len(a.abiInfo.InParams()))
}
-// String returns
-// "AuxCall{<fn>(<args>)}" if len(results) == 0;
-// "AuxCall{<fn>(<args>)<results[0]>}" if len(results) == 1;
-// "AuxCall{<fn>(<args>)(<results>)}" otherwise.
+// String returns "AuxCall{<fn>}"
func (a *AuxCall) String() string {
var fn string
if a.Fn == nil {
} else {
fn = fmt.Sprintf("AuxCall{%v", a.Fn)
}
-
- if len(a.results) > 0 { // usual is zero or one; only some RT calls have more than one.
- if len(a.results) == 1 {
- fn += fmt.Sprintf("[%v,%v]", a.results[0].Type, a.results[0].Offset)
- } else {
- s := "("
- for _, result := range a.results {
- fn += fmt.Sprintf("%s[%v,%v]", s, result.Type, result.Offset)
- s = ","
- }
- fn += ")"
- }
- }
+ // TODO how much of the ABI should be printed?
return fn + "}"
}
}
// StaticAuxCall returns an AuxCall for a static call.
-func StaticAuxCall(sym *obj.LSym, results []Param, paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
+func StaticAuxCall(sym *obj.LSym, paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
if paramResultInfo == nil {
panic(fmt.Errorf("Nil paramResultInfo, sym=%v", sym))
}
if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
reg = ®Info{}
}
- return &AuxCall{Fn: sym, results: results, abiInfo: paramResultInfo, reg: reg}
+ return &AuxCall{Fn: sym, abiInfo: paramResultInfo, reg: reg}
}
// InterfaceAuxCall returns an AuxCall for an interface call.
-func InterfaceAuxCall(args []Param, results []Param, paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
+func InterfaceAuxCall(paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
var reg *regInfo
if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
reg = ®Info{}
}
- return &AuxCall{Fn: nil, results: results, abiInfo: paramResultInfo, reg: reg}
+ return &AuxCall{Fn: nil, abiInfo: paramResultInfo, reg: reg}
}
// ClosureAuxCall returns an AuxCall for a closure call.
-func ClosureAuxCall(args []Param, results []Param, paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
+func ClosureAuxCall(paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
var reg *regInfo
if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
reg = ®Info{}
}
- return &AuxCall{Fn: nil, results: results, abiInfo: paramResultInfo, reg: reg}
+ return &AuxCall{Fn: nil, abiInfo: paramResultInfo, reg: reg}
}
func (*AuxCall) CanBeAnSSAAux() {}
// OwnAuxCall returns a function's own AuxCall
-func OwnAuxCall(fn *obj.LSym, args []Param, results []Param, paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
+func OwnAuxCall(fn *obj.LSym, paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
// TODO if this remains identical to ClosureAuxCall above after new ABI is done, should deduplicate.
var reg *regInfo
if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
reg = ®Info{}
}
- return &AuxCall{Fn: fn, results: results, abiInfo: paramResultInfo, reg: reg}
+ return &AuxCall{Fn: fn, abiInfo: paramResultInfo, reg: reg}
}
const (
results[i].Reg = r
}
- s.f.OwnAux = ssa.OwnAuxCall(fn.LSym, args, results, params)
+ s.f.OwnAux = ssa.OwnAuxCall(fn.LSym, params)
// Populate SSAable arguments.
for _, n := range fn.Dcl {
// Generate code to call the function call of the defer, using the
// closure/receiver/args that were stored in argtmps at the point
// of the defer statement.
- argStart := base.Ctxt.FixedFrameSize()
fn := r.n.X
stksize := fn.Type().ArgWidth()
- var ACArgs []ssa.Param
- var ACResults []ssa.Param
+ var ACArgs []*types.Type
+ var ACResults []*types.Type
var callArgs []*ssa.Value
if r.rcvr != nil {
// rcvr in case of OCALLINTER
v := s.load(r.rcvr.Type.Elem(), r.rcvr)
- ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINTPTR], Offset: int32(argStart)})
+ ACArgs = append(ACArgs, types.Types[types.TUINTPTR])
callArgs = append(callArgs, v)
}
for j, argAddrVal := range r.argVals {
f := getParam(r.n, j)
- ACArgs = append(ACArgs, ssa.Param{Type: f.Type, Offset: int32(argStart + abi.FieldOffsetOf(f))})
+ ACArgs = append(ACArgs, f.Type)
var a *ssa.Value
if !TypeOK(f.Type) {
a = s.newValue2(ssa.OpDereference, f.Type, argAddrVal, s.mem())
v := s.load(r.closure.Type.Elem(), r.closure)
s.maybeNilCheckClosure(v, callDefer)
codeptr := s.rawLoad(types.Types[types.TUINTPTR], v)
- aux := ssa.ClosureAuxCall(ACArgs, ACResults, s.f.ABIDefault.ABIAnalyzeTypes(nil, ssa.ACParamsToTypes(ACArgs), ssa.ACParamsToTypes(ACResults)))
+ aux := ssa.ClosureAuxCall(s.f.ABIDefault.ABIAnalyzeTypes(nil, ACArgs, ACResults))
call = s.newValue2A(ssa.OpClosureLECall, aux.LateExpansionResultType(), aux, codeptr, v)
} else {
- aux := ssa.StaticAuxCall(fn.(*ir.Name).Linksym(), ACResults, s.f.ABIDefault.ABIAnalyzeTypes(nil, ssa.ACParamsToTypes(ACArgs), ssa.ACParamsToTypes(ACResults)))
+ aux := ssa.StaticAuxCall(fn.(*ir.Name).Linksym(), s.f.ABIDefault.ABIAnalyzeTypes(nil, ACArgs, ACResults))
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
}
callArgs = append(callArgs, s.mem())
var codeptr *ssa.Value // ptr to target code (if dynamic)
var rcvr *ssa.Value // receiver to set
fn := n.X
- var ACArgs []ssa.Param // AuxCall args
- var ACResults []ssa.Param // AuxCall results
- var callArgs []*ssa.Value // For late-expansion, the args themselves (not stored, args to the call instead).
+ var ACArgs []*types.Type // AuxCall args
+ var ACResults []*types.Type // AuxCall results
+ var callArgs []*ssa.Value // For late-expansion, the args themselves (not stored, args to the call instead).
inRegisters := false
var magicFnNameSym *types.Sym
res := n.X.Type().Results()
if k == callNormal {
for _, p := range params.OutParams() {
- r := p.Registers
- var o int32
- if len(r) == 0 {
- o = p.Offset()
- } else {
- o = p.SpillOffset() + int32(params.SpillAreaOffset())
- }
- ACResults = append(ACResults, ssa.Param{Type: p.Type, Offset: o, Reg: r})
+ ACResults = append(ACResults, p.Type)
}
}
}
// Call runtime.deferprocStack with pointer to _defer record.
- ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINTPTR], Offset: int32(base.Ctxt.FixedFrameSize())})
- aux := ssa.StaticAuxCall(ir.Syms.DeferprocStack, ACResults, s.f.ABIDefault.ABIAnalyzeTypes(nil, ssa.ACParamsToTypes(ACArgs), ssa.ACParamsToTypes(ACResults)))
+ ACArgs = append(ACArgs, types.Types[types.TUINTPTR])
+ aux := ssa.StaticAuxCall(ir.Syms.DeferprocStack, s.f.ABIDefault.ABIAnalyzeTypes(nil, ACArgs, ACResults))
callArgs = append(callArgs, addr, s.mem())
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
call.AddArgs(callArgs...)
// Store arguments to stack, including defer/go arguments and receiver for method calls.
// These are written in SP-offset order.
argStart := base.Ctxt.FixedFrameSize()
- // argExtra is for combining with ABI-derived offsets; argStart is for old ABI0 code (defer, go).
- argExtra := int32(0) // TODO(register args) untangle this mess when fully transition to abiutils, defer/go sanitized.
// Defer/go args.
if k != callNormal {
// Write argsize and closure (args to newproc/deferproc).
argsize := s.constInt32(types.Types[types.TUINT32], int32(stksize))
- ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINT32], Offset: int32(argStart)}) // not argExtra
+ ACArgs = append(ACArgs, types.Types[types.TUINT32]) // not argExtra
callArgs = append(callArgs, argsize)
- ACArgs = append(ACArgs, ssa.Param{Type: types.Types[types.TUINTPTR], Offset: int32(argStart) + int32(types.PtrSize)})
+ ACArgs = append(ACArgs, types.Types[types.TUINTPTR])
callArgs = append(callArgs, closure)
stksize += 2 * int64(types.PtrSize)
argStart += 2 * int64(types.PtrSize)
- argExtra = 2 * int32(types.PtrSize)
}
// Set receiver (for interface calls).
}
for _, p := range params.InParams() { // includes receiver for interface calls
- r := p.Registers
- var o int32
- if len(r) == 0 {
- o = p.Offset()
- } else {
- o = p.SpillOffset() + int32(params.SpillAreaOffset())
- }
- ACArg := ssa.Param{Type: p.Type, Offset: argExtra + o, Reg: r} // o from ABI includes any architecture-dependent offsets.
- ACArgs = append(ACArgs, ACArg)
+ ACArgs = append(ACArgs, p.Type)
}
for i, n := range args {
callArgs = append(callArgs, s.putArg(n, t.Params().Field(i).Type))
// call target
switch {
case k == callDefer:
- aux := ssa.StaticAuxCall(ir.Syms.Deferproc, ACResults, s.f.ABIDefault.ABIAnalyzeTypes(nil, ssa.ACParamsToTypes(ACArgs), ssa.ACParamsToTypes(ACResults))) // TODO paramResultInfo for DeferProc
+ aux := ssa.StaticAuxCall(ir.Syms.Deferproc, s.f.ABIDefault.ABIAnalyzeTypes(nil, ACArgs, ACResults)) // TODO paramResultInfo for DeferProc
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
case k == callGo:
- aux := ssa.StaticAuxCall(ir.Syms.Newproc, ACResults, s.f.ABIDefault.ABIAnalyzeTypes(nil, ssa.ACParamsToTypes(ACArgs), ssa.ACParamsToTypes(ACResults)))
+ aux := ssa.StaticAuxCall(ir.Syms.Newproc, s.f.ABIDefault.ABIAnalyzeTypes(nil, ACArgs, ACResults))
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux) // TODO paramResultInfo for NewProc
case closure != nil:
// rawLoad because loading the code pointer from a
// critical that we not clobber any arguments already
// stored onto the stack.
codeptr = s.rawLoad(types.Types[types.TUINTPTR], closure)
- aux := ssa.ClosureAuxCall(ACArgs, ACResults, callABI.ABIAnalyzeTypes(nil, ssa.ACParamsToTypes(ACArgs), ssa.ACParamsToTypes(ACResults)))
+ aux := ssa.ClosureAuxCall(callABI.ABIAnalyzeTypes(nil, ACArgs, ACResults))
call = s.newValue2A(ssa.OpClosureLECall, aux.LateExpansionResultType(), aux, codeptr, closure)
case codeptr != nil:
// Note that the "receiver" parameter is nil because the actual receiver is the first input parameter.
- aux := ssa.InterfaceAuxCall(ACArgs, ACResults, params)
+ aux := ssa.InterfaceAuxCall(params)
call = s.newValue1A(ssa.OpInterLECall, aux.LateExpansionResultType(), aux, codeptr)
case callee != nil:
- aux := ssa.StaticAuxCall(callTargetLSym(callee, s.curfn.LSym), ACResults, params)
+ aux := ssa.StaticAuxCall(callTargetLSym(callee, s.curfn.LSym), params)
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
default:
s.Fatalf("bad call type %v %v", n.Op(), n)
// Issue call
var call *ssa.Value
- aux := ssa.StaticAuxCall(fn, ACResults, s.f.ABIDefault.ABIAnalyzeTypes(nil, callArgTypes, results))
+ aux := ssa.StaticAuxCall(fn, s.f.ABIDefault.ABIAnalyzeTypes(nil, callArgTypes, results))
callArgs = append(callArgs, s.mem())
call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
call.AddArgs(callArgs...)