// 'config' and analyzes the function to determine how its parameters
// and results will be passed (in registers or on the stack), returning
// an ABIParamResultInfo object that holds the results of the analysis.
-func (config *ABIConfig) ABIAnalyzeFuncType(ft *types.Func) *ABIParamResultInfo {
+func (config *ABIConfig) ABIAnalyzeFuncType(ft *types.Type) *ABIParamResultInfo {
setup()
s := assignState{
stackOffset: config.offsetForLocals,
rTotal: config.regAmounts,
}
result := &ABIParamResultInfo{config: config}
- result.preAllocateParams(ft.Receiver != nil, ft.Params.NumFields(), ft.Results.NumFields())
+ result.preAllocateParams(ft.Recv() != nil, ft.NumParams(), ft.NumResults())
// Receiver
// TODO(register args) ? seems like "struct" and "fields" is not right anymore for describing function parameters
- if ft.Receiver != nil && ft.Receiver.NumFields() != 0 {
- r := ft.Receiver.FieldSlice()[0]
+ if r := ft.Recv(); r != nil {
result.inparams = append(result.inparams,
s.assignParamOrReturn(r.Type, r.Nname, false))
}
// Inputs
- ifsl := ft.Params.FieldSlice()
+ ifsl := ft.Params().FieldSlice()
for _, f := range ifsl {
result.inparams = append(result.inparams,
s.assignParamOrReturn(f.Type, f.Nname, false))
// Outputs
s.rUsed = RegAmounts{}
- ofsl := ft.Results.FieldSlice()
+ ofsl := ft.Results().FieldSlice()
for _, f := range ofsl {
result.outparams = append(result.outparams, s.assignParamOrReturn(f.Type, f.Nname, true))
}
// outputs because their frame location transitions from BOGUS_FUNARG_OFFSET
// to zero to an as-if-AUTO offset that has no use for callers.
func (config *ABIConfig) ABIAnalyze(t *types.Type, setNname bool) *ABIParamResultInfo {
- ft := t.FuncType()
- result := config.ABIAnalyzeFuncType(ft)
+ result := config.ABIAnalyzeFuncType(t)
// Fill in the frame offsets for receiver, inputs, results
k := 0
if t.NumRecvs() != 0 {
- config.updateOffset(result, ft.Receiver.FieldSlice()[0], result.inparams[0], false, setNname)
+ config.updateOffset(result, t.Recv(), result.inparams[0], false, setNname)
k++
}
- for i, f := range ft.Params.FieldSlice() {
+ for i, f := range t.Params().FieldSlice() {
config.updateOffset(result, f, result.inparams[k+i], false, setNname)
}
- for i, f := range ft.Results.FieldSlice() {
+ for i, f := range t.Results().FieldSlice() {
config.updateOffset(result, f, result.outparams[i], true, setNname)
}
return result
ir.InitLSym(fn, false)
types.CalcSize(fn.Type())
a := ssagen.AbiForBodylessFuncStackMap(fn)
- abiInfo := a.ABIAnalyzeFuncType(fn.Type().FuncType()) // abiInfo has spill/home locations for wrapper
+ abiInfo := a.ABIAnalyzeFuncType(fn.Type()) // abiInfo has spill/home locations for wrapper
liveness.WriteFuncMap(fn, abiInfo)
if fn.ABI == obj.ABI0 {
x := ssagen.EmitArgInfo(fn, abiInfo)
// WriteBasicTypes always writes pointer types; any pointer has been stripped off typ already.
func writtenByWriteBasicTypes(typ *types.Type) bool {
if typ.Sym() == nil && typ.Kind() == types.TFUNC {
- f := typ.FuncType()
// func(error) string
- if f.Receiver.NumFields() == 0 &&
- f.Params.NumFields() == 1 && f.Results.NumFields() == 1 &&
- f.Params.FieldType(0) == types.ErrorType &&
- f.Results.FieldType(0) == types.Types[types.TSTRING] {
+ if typ.NumRecvs() == 0 &&
+ typ.NumParams() == 1 && typ.NumResults() == 1 &&
+ typ.Params().FieldType(0) == types.ErrorType &&
+ typ.Results().FieldType(0) == types.Types[types.TSTRING] {
return true
}
}
// synthesizes new (dead) values for the non-live params or the
// non-live pieces of partially live params.
func PopulateABIInRegArgOps(f *Func) {
- pri := f.ABISelf.ABIAnalyzeFuncType(f.Type.FuncType())
+ pri := f.ABISelf.ABIAnalyzeFuncType(f.Type)
// When manufacturing new slots that correspond to splits of
// composite parameters, we want to avoid creating a new sub-slot
// each input param reg will be spilled in the prolog).
func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset func(LocalSlot) int32, rval *FuncDebug) {
- pri := f.ABISelf.ABIAnalyzeFuncType(f.Type.FuncType())
+ pri := f.ABISelf.ABIAnalyzeFuncType(f.Type)
// Look to see if we have any named register-promoted parameters.
// If there are none, bail early and let the caller sort things
//
// (import "a_module" "add" (func (param i32 i32) (result i32)))
abiConfig := AbiForBodylessFuncStackMap(f)
- abiInfo := abiConfig.ABIAnalyzeFuncType(f.Type().FuncType())
+ abiInfo := abiConfig.ABIAnalyzeFuncType(f.Type())
wi.Params = paramsToWasmFields(f, abiInfo, abiInfo.InParams())
wi.Results = resultsToWasmFields(f, abiInfo, abiInfo.OutParams())
}
Embedlineno src.XPos // first use of this type as an embedded type
}
-// ForwardType returns t's extra forward-type-specific fields.
-func (t *Type) ForwardType() *Forward {
+// forwardType returns t's extra forward-type-specific fields.
+func (t *Type) forwardType() *Forward {
t.wantEtype(TFORW)
return t.extra.(*Forward)
}
Argwid int64
}
-// FuncType returns t's extra func-specific fields.
-func (t *Type) FuncType() *Func {
+// funcType returns t's extra func-specific fields.
+func (t *Type) funcType() *Func {
t.wantEtype(TFUNC)
return t.extra.(*Func)
}
Dir ChanDir // channel direction
}
-// ChanType returns t's extra channel-specific fields.
-func (t *Type) ChanType() *Chan {
+// chanType returns t's extra channel-specific fields.
+func (t *Type) chanType() *Chan {
t.wantEtype(TCHAN)
return t.extra.(*Chan)
}
// NewChan returns a new chan Type with direction dir.
func NewChan(elem *Type, dir ChanDir) *Type {
t := newType(TCHAN)
- ct := t.ChanType()
+ ct := t.chanType()
ct.Elem = elem
ct.Dir = dir
if elem.HasShape() {
results := SubstAny(t.Results(), types)
if recvs != t.Recvs() || params != t.Params() || results != t.Results() {
t = t.copy()
- t.FuncType().Receiver = recvs
- t.FuncType().Results = results
- t.FuncType().Params = params
+ t.funcType().Receiver = recvs
+ t.funcType().Results = results
+ t.funcType().Params = params
}
case TSTRUCT:
}
}
-func (t *Type) Recvs() *Type { return t.FuncType().Receiver }
-func (t *Type) Params() *Type { return t.FuncType().Params }
-func (t *Type) Results() *Type { return t.FuncType().Results }
+func (t *Type) Recvs() *Type { return t.funcType().Receiver }
+func (t *Type) Params() *Type { return t.funcType().Params }
+func (t *Type) Results() *Type { return t.funcType().Results }
-func (t *Type) NumRecvs() int { return t.FuncType().Receiver.NumFields() }
-func (t *Type) NumParams() int { return t.FuncType().Params.NumFields() }
-func (t *Type) NumResults() int { return t.FuncType().Results.NumFields() }
+func (t *Type) NumRecvs() int { return t.funcType().Receiver.NumFields() }
+func (t *Type) NumParams() int { return t.funcType().Params.NumFields() }
+func (t *Type) NumResults() int { return t.funcType().Results.NumFields() }
// IsVariadic reports whether function type t is variadic.
func (t *Type) IsVariadic() bool {
func (t *Type) SetUnderlying(underlying *Type) {
if underlying.kind == TFORW {
// This type isn't computed yet; when it is, update n.
- underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t)
+ underlying.forwardType().Copyto = append(underlying.forwardType().Copyto, t)
return
}
- ft := t.ForwardType()
+ ft := t.forwardType()
// TODO(mdempsky): Fix Type rekinding.
t.kind = underlying.kind
}
t := newType(TFUNC)
- ft := t.FuncType()
+ ft := t.funcType()
funargs := func(fields []*Field, funarg Funarg) *Type {
s := NewStruct(fields)