// references and writes symabis information to w.
//
// The symabis format is documented at
-// cmd/compile/internal/gc.readSymABIs.
+// cmd/compile/internal/ssagen.ReadSymABIs.
func (p *Parser) symDefRef(w io.Writer, word string, operands [][]lex.Token) {
switch word {
case "TEXT":
if (*Flag.Shared || *Flag.Dynlink || *Flag.LinkShared) && !Ctxt.Arch.InFamily(sys.AMD64, sys.ARM, sys.ARM64, sys.I386, sys.PPC64, sys.RISCV64, sys.S390X) {
log.Fatalf("%s/%s does not support -shared", objabi.GOOS, objabi.GOARCH)
}
- parseSpectre(Flag.Spectre) // left as string for recordFlags
+ parseSpectre(Flag.Spectre) // left as string for RecordFlags
Ctxt.Flag_shared = Ctxt.Flag_dynlink || Ctxt.Flag_shared
Ctxt.Flag_optimize = Flag.N == 0
lasterror.syntax = pos
} else {
// only one of multiple equal non-syntax errors per line
- // (flusherrors shows only one of them, so we filter them
+ // (FlushErrors shows only one of them, so we filter them
// here as best as we can (they may not appear in order)
// so that we don't count them here and exit early, and
// then have nothing to show for.)
nword := (nbit + wordBits - 1) / wordBits
size := int64(nword) * int64(count)
if int64(int32(size*4)) != size*4 {
- base.Fatalf("bvbulkalloc too big: nbit=%d count=%d nword=%d size=%d", nbit, count, nword, size)
+ base.Fatalf("NewBulk too big: nbit=%d count=%d nword=%d size=%d", nbit, count, nword, size)
}
return Bulk{
words: make([]uint32, size),
}
}
-// addr evaluates an addressable expression n and returns an EscHole
+// addr evaluates an addressable expression n and returns a hole
// that represents storing into the represented location.
func (e *escape) addr(n ir.Node) hole {
if n == nil || ir.IsBlank(n) {
return s
}
-// parseLeaks parses a binary string representing an EscLeaks.
+// parseLeaks parses a binary string representing a leaks
func parseLeaks(s string) leaks {
var l leaks
if !strings.HasPrefix(s, "esc:") {
func prepareFunc(fn *ir.Func) {
// Set up the function's LSym early to avoid data races with the assemblers.
// Do this before walk, as walk needs the LSym to set attributes/relocations
- // (e.g. in markTypeUsedInInterface).
+ // (e.g. in MarkTypeUsedInInterface).
ssagen.InitLSym(fn, true)
// Calculate parameter offsets.
log.Fatalf("compiler not built with support for -t")
}
- // Enable inlining (after recordFlags, to avoid recording the rewritten -l). For now:
+ // Enable inlining (after RecordFlags, to avoid recording the rewritten -l). For now:
// default: inlining on. (Flag.LowerL == 1)
// -l: inlining off (Flag.LowerL == 0)
// -l=2, -l=3: inlining on again, with extra debugging (Flag.LowerL > 1)
typecheck.Target = new(ir.Package)
typecheck.NeedITab = func(t, iface *types.Type) { reflectdata.ITabAddr(t, iface) }
- typecheck.NeedRuntimeType = reflectdata.NeedRuntimeType // TODO(rsc): typenamesym for lock?
+ typecheck.NeedRuntimeType = reflectdata.NeedRuntimeType // TODO(rsc): TypeSym for lock?
base.AutogeneratedPos = makePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
escape.Funcs(typecheck.Target.Decls)
// Collect information for go:nowritebarrierrec
- // checking. This must happen before transformclosure.
+ // checking. This must happen before transforming closures during Walk
// We'll do the final check after write barriers are
// inserted.
if base.Flag.CompilingRuntime {
}
// Prepare for SSA compilation.
- // This must be before peekitabs, because peekitabs
+ // This must be before CompileITabs, because CompileITabs
// can trigger function compilation.
typecheck.InitRuntime()
ssagen.InitConfig()
reflectdata.WriteBasicTypes()
dumpembeds()
- // Calls to dumpsignats can generate functions,
+ // Calls to WriteRuntimeTypes can generate functions,
// like method wrappers and hash and equality routines.
// Compile any generated functions, process any new resulting types, repeat.
// This can't loop forever, because there is no way to generate an infinite
//
// The inlining facility makes 2 passes: first caninl determines which
// functions are suitable for inlining, and for those that are it
-// saves a copy of the body. Then inlcalls walks each function body to
+// saves a copy of the body. Then InlineCalls walks each function body to
// expand calls to inlinable functions.
//
// The Debug.l flag controls the aggressiveness. Note that main() swaps level 0 and 1,
// fn and ->nbody will already have been typechecked.
func CanInline(fn *ir.Func) {
if fn.Nname == nil {
- base.Fatalf("caninl no nname %+v", fn)
+ base.Fatalf("CanInline no nname %+v", fn)
}
var reason string // reason, if any, that the function was not inlined
}
if fn.Typecheck() == 0 {
- base.Fatalf("caninl on non-typechecked function %v", fn)
+ base.Fatalf("CanInline on non-typechecked function %v", fn)
}
n := fn.Nname
return
}
if n.Op() != ir.ONAME || n.Class != ir.PFUNC {
- base.Fatalf("inlFlood: unexpected %v, %v, %v", n, n.Op(), n.Class)
+ base.Fatalf("Inline_Flood: unexpected %v, %v, %v", n, n.Op(), n.Class)
}
fn := n.Func
if fn == nil {
- base.Fatalf("inlFlood: missing Func on %v", n)
+ base.Fatalf("Inline_Flood: missing Func on %v", n)
}
if fn.Inl == nil {
return
ft := types.FloatForComplex(t)
return ConstOverflow(constant.Real(v), ft) || ConstOverflow(constant.Imag(v), ft)
}
- base.Fatalf("doesoverflow: %v, %v", v, t)
+ base.Fatalf("ConstOverflow: %v, %v", v, t)
panic("unreachable")
}
Exit Nodes
// ONAME nodes for all params/locals for this func/closure, does NOT
- // include closurevars until transformclosure runs.
+ // include closurevars until transforming closures during walk.
// Names must be listed PPARAMs, PPARAMOUTs, then PAUTOs,
// with PPARAMs and PPARAMOUTs in order corresponding to the function signature.
// However, as anonymous or blank PPARAMs are not actually declared,
HasBreak bool
// TODO(rsc): Instead of recording here, replace with a block?
- Compiled Nodes // compiled form, after walkswitch
+ Compiled Nodes // compiled form, after walkSwitch
}
func NewSelectStmt(pos src.XPos, cases []*CommClause) *SelectStmt {
HasBreak bool
// TODO(rsc): Instead of recording here, replace with a block?
- Compiled Nodes // compiled form, after walkswitch
+ Compiled Nodes // compiled form, after walkSwitch
}
func NewSwitchStmt(pos src.XPos, tag Node, cases []*CaseClause) *SwitchStmt {
m.index = newIndex
}
-// add adds bv to the set and returns its index in m.extractUniqe.
+// add adds bv to the set and returns its index in m.extractUnique.
// The caller must not modify bv after this.
func (m *bvecSet) add(bv bitvec.BitVec) int {
if len(m.uniq)*4 >= len(m.index) {
func (lv *liveness) emit() (argsSym, liveSym *obj.LSym) {
// Size args bitmaps to be just large enough to hold the largest pointer.
// First, find the largest Xoffset node we care about.
- // (Nodes without pointers aren't in lv.vars; see livenessShouldTrack.)
+ // (Nodes without pointers aren't in lv.vars; see ShouldTrack.)
var maxArgNode *ir.Name
for _, n := range lv.vars {
switch n.Class {
if types.IsDotAlias(s) {
// throw away top-level name left over
// from previous import . "x"
- // We'll report errors after type checking in checkDotImports.
+ // We'll report errors after type checking in CheckDotImports.
s.Def = nil
continue
}
if base.SyntaxErrors() != 0 {
base.ErrorExit()
}
- // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
+ // Always run CheckDclstack here, even when debug_dclstack is not set, as a sanity measure.
types.CheckDclstack()
}
}
} else {
f.Shortname = name
- name = ir.BlankNode.Sym() // filled in by typecheckfunc
+ name = ir.BlankNode.Sym() // filled in by tcFunc
}
f.Nname = ir.NewNameAt(p.pos(fun.Name), name)
if s == nil {
} else if s.Op() == ir.OBLOCK && len(s.(*ir.BlockStmt).List) > 0 {
// Inline non-empty block.
- // Empty blocks must be preserved for checkreturn.
+ // Empty blocks must be preserved for CheckReturn.
nodes = append(nodes, s.(*ir.BlockStmt).List...)
} else {
nodes = append(nodes, s)
fn := ir.NewFunc(p.pos(expr))
fn.SetIsHiddenClosure(ir.CurFunc != nil)
- fn.Nname = ir.NewNameAt(p.pos(expr), ir.BlankNode.Sym()) // filled in by typecheckclosure
+ fn.Nname = ir.NewNameAt(p.pos(expr), ir.BlankNode.Sym()) // filled in by tcClosure
fn.Nname.Func = fn
fn.Nname.Ntype = xtype
fn.Nname.Defn = fn
func (pp *Progs) SetText(fn *ir.Func) {
if pp.Text != nil {
- base.Fatalf("Progs.settext called twice")
+ base.Fatalf("Progs.SetText called twice")
}
ptxt := pp.Prog(obj.ATEXT)
pp.Text = ptxt
fns = append(fns, fn.Linksym())
}
if typecheck.InitTodoFunc.Dcl != nil {
- // We only generate temps using initTodo if there
+ // We only generate temps using InitTodoFunc if there
// are package-scope initialization statements, so
// something's weird if we get here.
- base.Fatalf("initTodo still has declarations")
+ base.Fatalf("InitTodoFunc still has declarations")
}
typecheck.InitTodoFunc = nil
// eqtab must be evaluated before eqdata, and shortcircuiting is required.
func EqInterface(s, t ir.Node) (eqtab *ir.BinaryExpr, eqdata *ir.CallExpr) {
if !types.Identical(s.Type(), t.Type()) {
- base.Fatalf("eqinterface %v %v", s.Type(), t.Type())
+ base.Fatalf("EqInterface %v %v", s.Type(), t.Type())
}
// func ifaceeq(tab *uintptr, x, y unsafe.Pointer) (ret bool)
// func efaceeq(typ *uintptr, x, y unsafe.Pointer) (ret bool)
// symbols of each method in
// the itab, sorted by byte offset;
- // filled in by peekitabs
+ // filled in by CompileITabs
entries []*obj.LSym
}
}
// If we are compiling the runtime package, there are two runtime packages around
- // -- localpkg and Runtimepkg. We don't want to produce import path symbols for
+ // -- localpkg and Pkgs.Runtime. We don't want to produce import path symbols for
// both of them, so just produce one for localpkg.
if base.Ctxt.Pkgpath == "runtime" && p == ir.Pkgs.Runtime {
return
func TypeSym(t *types.Type) *types.Sym {
if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
- base.Fatalf("typenamesym %v", t)
+ base.Fatalf("TypeSym %v", t)
}
if t.Kind() == types.TFUNC && t.Recv() != nil {
base.Fatalf("misuse of method type: %v", t)
func ITabAddr(t, itype *types.Type) *ir.AddrExpr {
if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() || !itype.IsInterface() || itype.IsEmptyInterface() {
- base.Fatalf("itabname(%v, %v)", t, itype)
+ base.Fatalf("ITabAddr(%v, %v)", t, itype)
}
s := ir.Pkgs.Itab.Lookup(t.ShortString() + "," + itype.ShortString())
if s.Def == nil {
func writeType(t *types.Type) *obj.LSym {
t = formalType(t)
if t.IsUntyped() {
- base.Fatalf("dtypesym %v", t)
+ base.Fatalf("writeType %v", t)
}
s := types.TypeSym(t)
}
// ITabSym uses the information gathered in
-// peekitabs to de-virtualize interface methods.
+// CompileITabs to de-virtualize interface methods.
// Since this is called by the SSA backend, it shouldn't
// generate additional Nodes, Syms, etc.
func ITabSym(it *obj.LSym, offset int64) *obj.LSym {
}
func WriteRuntimeTypes() {
- // Process signatset. Use a loop, as dtypesym adds
+ // Process signatset. Use a loop, as writeType adds
// entries to signatset while it is being processed.
signats := make([]typeAndStr, len(signatslice))
for len(signatslice) > 0 {
}
switch t.Kind() {
default:
- base.Fatalf("GCProg.emit: unexpected type %v", t)
+ base.Fatalf("gcProg.emit: unexpected type %v", t)
case types.TSTRING:
p.w.Ptr(offset / int64(types.PtrSize))
case types.TINTER:
- // Note: the first word isn't a pointer. See comment in plive.go:onebitwalktype1.
+ // Note: the first word isn't a pointer. See comment in typebits.Set
p.w.Ptr(offset/int64(types.PtrSize) + 1)
case types.TSLICE:
case types.TARRAY:
if t.NumElem() == 0 {
// should have been handled by haspointers check above
- base.Fatalf("GCProg.emit: empty array")
+ base.Fatalf("gcProg.emit: empty array")
}
// Flatten array-of-array-of-array to just a big array by multiplying counts.
// makes calls to helpers to create ABI wrappers if needed.
func selectLSym(f *ir.Func, hasBody bool) {
if f.LSym != nil {
- base.FatalfAt(f.Pos(), "Func.initLSym called twice on %v", f)
+ base.FatalfAt(f.Pos(), "InitLSym called twice on %v", f)
}
if nam := f.Nname; !ir.IsBlank(nam) {
}
// newNowritebarrierrecChecker creates a nowritebarrierrecChecker. It
-// must be called before transformclosure and walk.
+// must be called before walk
func newNowritebarrierrecChecker() *nowritebarrierrecChecker {
c := &nowritebarrierrecChecker{
extraCalls: make(map[*ir.Func][]nowritebarrierrecCall),
// Find all systemstack calls and record their targets. In
// general, flow analysis can't see into systemstack, but it's
// important to handle it for this check, so we model it
- // directly. This has to happen before transformclosure since
+ // directly. This has to happen before transforming closures in walk since
// it's a lot harder to work out the argument after.
for _, n := range typecheck.Target.Decls {
if n.Op() != ir.ODCLFUNC {
if n, ok := v.Aux.(*ir.Name); ok {
switch n.Class {
case ir.PPARAM, ir.PPARAMOUT:
- // Don't modify nodfp; it is a global.
+ // Don't modify RegFP; it is a global.
if n != ir.RegFP {
n.SetUsed(true)
}
// Currently doesn't really work because (*p)[:len(*p)] appears here as:
// tmp = len(*p)
// (*p)[:tmp]
- //if j != nil && (j.Op == OLEN && samesafeexpr(j.Left, n.Left)) {
+ //if j != nil && (j.Op == OLEN && SameSafeExpr(j.Left, n.Left)) {
// j = nil
//}
- //if k != nil && (k.Op == OCAP && samesafeexpr(k.Left, n.Left)) {
+ //if k != nil && (k.Op == OCAP && SameSafeExpr(k.Left, n.Left)) {
// k = nil
//}
if i == nil {
// in the generated code.
if p.IsStmt() != src.PosIsStmt {
p = p.WithNotStmt()
- // Calls use the pos attached to v, but copy the statement mark from SSAGenState
+ // Calls use the pos attached to v, but copy the statement mark from State
}
s.SetPos(p)
} else {
if n.Type().IsEmptyInterface() {
f = ".type"
}
- c := e.SplitSlot(&name, f, 0, u) // see comment in plive.go:onebitwalktype1.
+ c := e.SplitSlot(&name, f, 0, u) // see comment in typebits.Set
d := e.SplitSlot(&name, ".data", u.Size(), t)
return c, d
}
// Neither n nor a is modified.
func InitAddr(n *ir.Name, noff int64, a *ir.Name, aoff int64) {
if n.Op() != ir.ONAME {
- base.Fatalf("addrsym n op %v", n.Op())
+ base.Fatalf("InitAddr n op %v", n.Op())
}
if n.Sym() == nil {
- base.Fatalf("addrsym nil n sym")
+ base.Fatalf("InitAddr nil n sym")
}
if a.Op() != ir.ONAME {
- base.Fatalf("addrsym a op %v", a.Op())
+ base.Fatalf("InitAddr a op %v", a.Op())
}
s := n.Linksym()
s.WriteAddr(base.Ctxt, noff, types.PtrSize, a.Linksym(), aoff)
// Neither n nor f is modified.
func InitFunc(n *ir.Name, noff int64, f *ir.Name) {
if n.Op() != ir.ONAME {
- base.Fatalf("pfuncsym n op %v", n.Op())
+ base.Fatalf("InitFunc n op %v", n.Op())
}
if n.Sym() == nil {
- base.Fatalf("pfuncsym nil n sym")
+ base.Fatalf("InitFunc nil n sym")
}
if f.Class != ir.PFUNC {
- base.Fatalf("pfuncsym class not PFUNC %d", f.Class)
+ base.Fatalf("InitFunc class not PFUNC %d", f.Class)
}
s := n.Linksym()
s.WriteAddr(base.Ctxt, noff, types.PtrSize, FuncLinksym(f), 0)
func InitSlice(n *ir.Name, noff int64, arr *ir.Name, lencap int64) {
s := n.Linksym()
if arr.Op() != ir.ONAME {
- base.Fatalf("slicesym non-name arr %v", arr)
+ base.Fatalf("InitSlice non-name arr %v", arr)
}
s.WriteAddr(base.Ctxt, noff, types.PtrSize, arr.Linksym(), 0)
s.WriteInt(base.Ctxt, noff+types.SliceLenOffset, types.PtrSize, lencap)
func InitSliceBytes(nam *ir.Name, off int64, s string) {
if nam.Op() != ir.ONAME {
- base.Fatalf("slicebytes %v", nam)
+ base.Fatalf("InitSliceBytes %v", nam)
}
InitSlice(nam, off, slicedata(nam.Pos(), s), int64(len(s)))
}
// except for the types package, which is protected separately.
// Reusing funcsymsmu to also cover this package lookup
// avoids a general, broader, expensive package lookup mutex.
- // Note makefuncsym also does package look-up of func sym names,
+ // Note NeedFuncSym also does package look-up of func sym names,
// but that it is only called serially, from the front end.
funcsymsmu.Lock()
sf, existed := s.Pkg.LookupOK(ir.FuncSymName(s))
// Don't export s·f when compiling for dynamic linking.
// When dynamically linking, the necessary function
- // symbols will be created explicitly with makefuncsym.
- // See the makefuncsym comment for details.
+ // symbols will be created explicitly with NeedFuncSym.
+ // See the NeedFuncSym comment for details.
if !base.Ctxt.Flag_dynlink && !existed {
funcsyms = append(funcsyms, s)
}
// Neither n nor c is modified.
func InitConst(n *ir.Name, noff int64, c ir.Node, wid int) {
if n.Op() != ir.ONAME {
- base.Fatalf("litsym n op %v", n.Op())
+ base.Fatalf("InitConst n op %v", n.Op())
}
if n.Sym() == nil {
- base.Fatalf("litsym nil n sym")
+ base.Fatalf("InitConst nil n sym")
}
if c.Op() == ir.ONIL {
return
}
if c.Op() != ir.OLITERAL {
- base.Fatalf("litsym c op %v", c.Op())
+ base.Fatalf("InitConst c op %v", c.Op())
}
s := n.Linksym()
switch u := c.Val(); u.Kind() {
s.WriteInt(base.Ctxt, noff+int64(types.PtrSize), types.PtrSize, int64(len(i)))
default:
- base.Fatalf("litsym unhandled OLITERAL %v", c)
+ base.Fatalf("InitConst unhandled OLITERAL %v", c)
}
}
// These are not guaranteed to match only string and []byte -
// maybe the local package has redefined one of those words.
// But it's the best we can do now during the noder.
- // The stricter check happens later, in initEmbed calling embedKind.
+ // The stricter check happens later, in WriteEmbed calling embedKind.
if typ.Sym() != nil && typ.Sym().Name == "string" && typ.Sym().Pkg == types.LocalPkg {
return embedString
}
// StaticName returns a name backed by a (writable) static data symbol.
// Use readonlystaticname for read-only node.
func StaticName(t *types.Type) *ir.Name {
- // Don't use lookupN; it interns the resulting string, but these are all unique.
+ // Don't use LookupNum; it interns the resulting string, but these are all unique.
n := typecheck.NewName(typecheck.Lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen)))
statuniqgen++
typecheck.Declare(n, ir.PEXTERN)
emptyResString := emptyRes.String()
// Walk the results and make sure the offsets assigned match
- // up with those assiged by dowidth. This checks to make sure that
+ // up with those assiged by CalcSize. This checks to make sure that
// when we have no available registers the ABI assignment degenerates
// back to the original ABI0.
return
}
// Address-taken local of type A, which will insure that the
- // compiler's dtypesym() routine will create a method wrapper.
+ // compiler's writeType() routine will create a method wrapper.
var a, b A
a.next = x
a.prev = &b
// on future calls with the same type t.
func Set(t *types.Type, off int64, bv bitvec.BitVec) {
if t.Align > 0 && off&int64(t.Align-1) != 0 {
- base.Fatalf("onebitwalktype1: invalid initial alignment: type %v has alignment %d, but offset is %v", t, t.Align, off)
+ base.Fatalf("typebits.Set: invalid initial alignment: type %v has alignment %d, but offset is %v", t, t.Align, off)
}
if !t.HasPointers() {
// Note: this case ensures that pointers to go:notinheap types
switch t.Kind() {
case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP:
if off&int64(types.PtrSize-1) != 0 {
- base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
+ base.Fatalf("typebits.Set: invalid alignment, %v", t)
}
bv.Set(int32(off / int64(types.PtrSize))) // pointer
case types.TSTRING:
// struct { byte *str; intgo len; }
if off&int64(types.PtrSize-1) != 0 {
- base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
+ base.Fatalf("typebits.Set: invalid alignment, %v", t)
}
bv.Set(int32(off / int64(types.PtrSize))) //pointer in first slot
// or, when isnilinter(t)==true:
// struct { Type *type; void *data; }
if off&int64(types.PtrSize-1) != 0 {
- base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
+ base.Fatalf("typebits.Set: invalid alignment, %v", t)
}
// The first word of an interface is a pointer, but we don't
// treat it as such.
case types.TSLICE:
// struct { byte *array; uintgo len; uintgo cap; }
if off&int64(types.PtrSize-1) != 0 {
- base.Fatalf("onebitwalktype1: invalid TARRAY alignment, %v", t)
+ base.Fatalf("typebits.Set: invalid TARRAY alignment, %v", t)
}
bv.Set(int32(off / int64(types.PtrSize))) // pointer in first slot (BitsPointer)
}
default:
- base.Fatalf("onebitwalktype1: unexpected type, %v", t)
+ base.Fatalf("typebits.Set: unexpected type, %v", t)
}
}
return OrigConst(n, constant.MakeInt64(v))
}
-// defaultlit on both nodes simultaneously;
+// DefaultLit on both nodes simultaneously;
// if they're both ideal going in they better
// get the same type going out.
// force means must assign concrete (non-ideal) type.
s := n.Sym()
- // kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later.
+ // kludgy: TypecheckAllowed means we're past parsing. Eg reflectdata.methodWrapper may declare out of package names later.
if !inimport && !TypecheckAllowed && s.Pkg != types.LocalPkg {
base.ErrorfAt(n.Pos(), "cannot declare name %v", s)
}
return types.NewField(src.NoXPos, nil, types.FakeRecvType())
}
-var funcStack []funcStackEnt // stack of previous values of Curfn/dclcontext
+var funcStack []funcStackEnt // stack of previous values of ir.CurFunc/DeclContext
type funcStackEnt struct {
curfn *ir.Func
// make a new Node off the books
func TempAt(pos src.XPos, curfn *ir.Func, t *types.Type) *ir.Name {
if curfn == nil {
- base.Fatalf("no curfn for tempAt")
+ base.Fatalf("no curfn for TempAt")
}
if curfn.Op() == ir.OCLOSURE {
- ir.Dump("tempAt", curfn)
- base.Fatalf("adding tempAt to wrong closure function")
+ ir.Dump("TempAt", curfn)
+ base.Fatalf("adding TempAt to wrong closure function")
}
if t == nil {
- base.Fatalf("tempAt called with nil type")
+ base.Fatalf("TempAt called with nil type")
}
if t.Kind() == types.TFUNC && t.Recv() != nil {
base.Fatalf("misuse of method type: %v", t)
return l, r, nil
}
- // no defaultlit for left
+ // no DefaultLit for left
// the outer context gives the type
t = l.Type()
if (l.Type() == types.UntypedFloat || l.Type() == types.UntypedComplex) && r.Op() == ir.OLITERAL {
// n.Left = tcCompLit(n.Left)
func tcCompLit(n *ir.CompLitExpr) (res ir.Node) {
if base.EnableTrace && base.Flag.LowerT {
- defer tracePrint("typecheckcomplit", n)(&res)
+ defer tracePrint("tcCompLit", n)(&res)
}
lno := base.Pos
}
if l.Op() == ir.OTYPE {
n.SetOTYPE(types.NewPtr(l.Type()))
- // Ensure l.Type gets dowidth'd for the backend. Issue 20174.
+ // Ensure l.Type gets CalcSize'd for the backend. Issue 20174.
types.CheckSize(l.Type())
return n
}
return t
}
-// Lazy typechecking of imported bodies. For local functions, caninl will set ->typecheck
+// Lazy typechecking of imported bodies. For local functions, CanInline will set ->typecheck
// because they're a copy of an already checked body.
func ImportedBody(fn *ir.Func) {
lno := ir.SetPos(fn.Nname)
ImportBody(fn)
- // typecheckinl is only for imported functions;
+ // Stmts(fn.Inl.Body) below is only for imported functions;
// their bodies may refer to unsafe as long as the package
// was marked safe during import (which was checked then).
- // the ->inl of a local function has been typechecked before caninl copied it.
+ // the ->inl of a local function has been typechecked before CanInline copied it.
pkg := fnpkg(fn.Nname)
if pkg == types.LocalPkg || pkg == nil {
- return // typecheckinl on local function
+ return // ImportedBody on local function
}
if base.Flag.LowerM > 2 || base.Debug.Export != 0 {
Stmts(fn.Inl.Body)
ir.CurFunc = savefn
- // During expandInline (which imports fn.Func.Inl.Body),
- // declarations are added to fn.Func.Dcl by funcHdr(). Move them
+ // During ImportBody (which imports fn.Func.Inl.Body),
+ // declarations are added to fn.Func.Dcl by funcBody(). Move them
// to fn.Func.Inl.Dcl for consistency with how local functions
- // behave. (Append because typecheckinl may be called multiple
+ // behave. (Append because ImportedBody may be called multiple
// times.)
fn.Inl.Dcl = append(fn.Inl.Dcl, fn.Dcl...)
fn.Dcl = nil
fn.SetClosureCalled(top&ctxCallee != 0)
// Do not typecheck fn twice, otherwise, we will end up pushing
- // fn to Target.Decls multiple times, causing initLSym called twice.
+ // fn to Target.Decls multiple times, causing InitLSym called twice.
// See #30709
if fn.Typecheck() == 1 {
clo.SetType(fn.Type())
// type check function definition
// To be called by typecheck, not directly.
-// (Call typecheckFunc instead.)
+// (Call typecheck.Func instead.)
func tcFunc(n *ir.Func) {
if base.EnableTrace && base.Flag.LowerT {
- defer tracePrint("typecheckfunc", n)(nil)
+ defer tracePrint("tcFunc", n)(nil)
}
n.Nname = AssignExpr(n.Nname).(*ir.Name)
// and offset where that identifier's declaration can be read.
DeclImporter = map[*types.Sym]iimporterAndOffset{}
- // inlineImporter is like declImporter, but for inline bodies
+ // inlineImporter is like DeclImporter, but for inline bodies
// for function and method symbols.
inlineImporter = map[*types.Sym]iimporterAndOffset{}
)
recv := r.param()
mtyp := r.signature(recv)
- // methodSym already marked m.Sym as a function.
+ // MethodSym already marked m.Sym as a function.
m := ir.NewNameAt(mpos, ir.MethodSym(recv.Type, msym))
m.Class = ir.PFUNC
m.SetType(mtyp)
}
t := RangeExprType(n.X.Type())
- // delicate little dance. see typecheckas2
+ // delicate little dance. see tcAssignList
if n.Key != nil && !ir.DeclaredBy(n.Key, n) {
n.Key = AssignExpr(n.Key)
}
// fill in the var's type.
func tcAssign(n *ir.AssignStmt) {
if base.EnableTrace && base.Flag.LowerT {
- defer tracePrint("typecheckas", n)(nil)
+ defer tracePrint("tcAssign", n)(nil)
}
if n.Y == nil {
func tcAssignList(n *ir.AssignListStmt) {
if base.EnableTrace && base.Flag.LowerT {
- defer tracePrint("typecheckas2", n)(nil)
+ defer tracePrint("tcAssignList", n)(nil)
}
assign(n, n.Lhs, n.Rhs)
func assign(stmt ir.Node, lhs, rhs []ir.Node) {
// delicate little dance.
// the definition of lhs may refer to this assignment
- // as its definition, in which case it will call typecheckas.
+ // as its definition, in which case it will call tcAssign.
// in that case, do not call typecheck back, or it will cycle.
// if the variable has a type (ntype) then typechecking
// will not look at defn, so it is okay (and desirable,
// main typecheck has completed.
// The argument to OADDR needs to be typechecked because &x[i] takes
// the address of x if x is an array, but not if x is a slice.
- // Note: outervalue doesn't work correctly until n is typechecked.
+ // Note: OuterValue doesn't work correctly until n is typechecked.
n = typecheck(n, ctxExpr)
if x := ir.OuterValue(n); x.Op() == ir.ONAME {
x.Name().SetAddrtaken(true)
var missing, have *types.Field
var ptr int
if implements(src, dst, &missing, &have, &ptr) {
- // Call itabname so that (src, dst)
+ // Call NeedITab/ITabAddr so that (src, dst)
// gets added to itabs early, which allows
// us to de-virtualize calls through this
- // type/interface pair later. See peekitabs in reflect.go
+ // type/interface pair later. See CompileITabs in reflect.go
if types.IsDirectIface(src) && !dst.IsEmptyInterface() {
NeedITab(src, dst)
}
}
}
- // 6. rule about untyped constants - already converted by defaultlit.
+ // 6. rule about untyped constants - already converted by DefaultLit.
// 7. Any typed value can be assigned to the blank identifier.
if dst.Kind() == types.TBLANK {
var slist []symlink
// Code to help generate trampoline functions for methods on embedded
-// types. These are approx the same as the corresponding adddot
+// types. These are approx the same as the corresponding AddImplicitDots
// routines except that they expect to be called with unique tasks and
// they return the actual methods.
func LookupRuntime(name string) *ir.Name {
s := ir.Pkgs.Runtime.Lookup(name)
if s == nil || s.Def == nil {
- base.Fatalf("syslook: can't find runtime.%s", name)
+ base.Fatalf("LookupRuntime: can't find runtime.%s", name)
}
return ir.AsNode(s.Def).(*ir.Name)
}
n.Class = old.Class
n.SetType(types.SubstAny(old.Type(), &types_))
if len(types_) > 0 {
- base.Fatalf("substArgTypes: too many argument types")
+ base.Fatalf("SubstArgTypes: too many argument types")
}
return n
}
}
// indexlit implements typechecking of untyped values as
-// array/slice indexes. It is almost equivalent to defaultlit
+// array/slice indexes. It is almost equivalent to DefaultLit
// but also accepts untyped numeric values representable as
// value of type int (see also checkmake for comparison).
// The result of indexlit MUST be assigned back to n, e.g.
// If we're outside of function context, then this call will
// be executed during the generated init function. However,
// init.go hasn't yet created it. Instead, associate the
- // temporary variables with initTodo for now, and init.go
+ // temporary variables with InitTodoFunc for now, and init.go
// will reassociate them later when it's appropriate.
static := ir.CurFunc == nil
if static {
return false
}
- // Do range checks for constants before defaultlit
+ // Do range checks for constants before DefaultLit
// to avoid redundant "constant NNN overflows int" errors.
if n.Op() == ir.OLITERAL {
v := toint(n.Val())
}
}
- // defaultlit is necessary for non-constants too: n might be 1.1<<k.
+ // DefaultLit is necessary for non-constants too: n might be 1.1<<k.
// TODO(gri) The length argument requirements for (array/slice) make
// are the same as for index expressions. Factor the code better;
// for instance, indexlit might be called here and incorporate some
return ret, nil
}
- base.Fatalf("algtype: unexpected type %v", t)
+ base.Fatalf("AlgType: unexpected type %v", t)
return 0, nil
}
// by padding.
func IsPaddedField(t *Type, i int) bool {
if !t.IsStruct() {
- base.Fatalf("ispaddedfield called non-struct %v", t)
+ base.Fatalf("IsPaddedField called non-struct %v", t)
}
end := t.Width
if i+1 < t.NumFields() {
}
if strings.HasPrefix(s.Name, ".anon") {
- // originally an unnamed or _ name (see subr.go: structargs)
+ // originally an unnamed or _ name (see subr.go: NewFuncParams)
return nil
}
var MaxWidth int64
// CalcSizeDisabled indicates whether it is safe
-// to calculate Types' widths and alignments. See dowidth.
+// to calculate Types' widths and alignments. See CalcSize.
var CalcSizeDisabled bool
// machine size and rounding alignment is dictated around
m.Offset = int64(i) * int64(PtrSize)
}
- // Access fields directly to avoid recursively calling dowidth
+ // Access fields directly to avoid recursively calling CalcSize
// within Type.Fields().
t.Extra.(*Interface).Fields.Set(methods)
}
f.Offset = o
if f.Nname != nil {
// addrescapes has similar code to update these offsets.
- // Usually addrescapes runs after widstruct,
+ // Usually addrescapes runs after calcStructOffset,
// in which case we could drop this,
// but function closure functions are the exception.
// NOTE(rsc): This comment may be stale.
}
// CalcSize calculates and stores the size and alignment for t.
-// If sizeCalculationDisabled is set, and the size/alignment
+// If CalcSizeDisabled is set, and the size/alignment
// have not already been calculated, it calls Fatal.
// This is used to prevent data races in the back end.
func CalcSize(t *Type) {
- // Calling dowidth when typecheck tracing enabled is not safe.
+ // Calling CalcSize when typecheck tracing enabled is not safe.
// See issue #33658.
if base.EnableTrace && SkipSizeForTracing {
return
}
if PtrSize == 0 {
-
// Assume this is a test.
return
}
return
}
- // defer checkwidth calls until after we're done
+ // defer CheckSize calls until after we're done
DeferCheckSize()
lno := base.Pos
case TFUNC, TCHAN, TMAP, TSTRING:
break
- // simtype == 0 during bootstrap
+ // SimType == 0 during bootstrap
default:
if SimType[t.Kind()] != 0 {
et = SimType[t.Kind()]
var w int64
switch et {
default:
- base.Fatalf("dowidth: unknown type: %v", t)
+ base.Fatalf("CalcSize: unknown type: %v", t)
// compiler-specific stuff
case TINT8, TUINT8, TBOOL:
case TANY:
// not a real type; should be replaced before use.
- base.Fatalf("dowidth any")
+ base.Fatalf("CalcSize any")
case TSTRING:
if StringSize == 0 {
- base.Fatalf("early dowidth string")
+ base.Fatalf("early CalcSize string")
}
w = StringSize
t.Align = uint8(PtrSize)
case TSTRUCT:
if t.IsFuncArgStruct() {
- base.Fatalf("dowidth fn struct %v", t)
+ base.Fatalf("CalcSize fn struct %v", t)
}
w = calcStructOffset(t, t, 0, 1)
s.Width = calcStructOffset(s, s, 0, 1) // sets align
}
-// when a type's width should be known, we call checkwidth
+// when a type's width should be known, we call CheckSize
// to compute it. during a declaration like
//
// type T *struct { next T }
// until after T has been initialized to be a pointer to that struct.
// similarly, during import processing structs may be used
// before their definition. in those situations, calling
-// defercheckwidth() stops width calculations until
-// resumecheckwidth() is called, at which point all the
-// checkwidths that were deferred are executed.
-// dowidth should only be called when the type's size
-// is needed immediately. checkwidth makes sure the
+// DeferCheckSize() stops width calculations until
+// ResumeCheckSize() is called, at which point all the
+// CalcSizes that were deferred are executed.
+// CalcSize should only be called when the type's size
+// is needed immediately. CheckSize makes sure the
// size is evaluated eventually.
var deferredTypeStack []*Type
// function arg structs should not be checked
// outside of the enclosing function.
if t.IsFuncArgStruct() {
- base.Fatalf("checkwidth %v", t)
+ base.Fatalf("CheckSize %v", t)
}
if defercalc == 0 {
case TINTER:
// struct { Itab *tab; void *data; } or
// struct { Type *type; void *data; }
- // Note: see comment in plive.go:onebitwalktype1.
+ // Note: see comment in typebits.Set
return 2 * int64(PtrSize)
case TSLICE:
return lastPtrField.Offset + PtrDataSize(lastPtrField.Type)
default:
- base.Fatalf("typeptrdata: unexpected type, %v", t)
+ base.Fatalf("PtrDataSize: unexpected type, %v", t)
return 0
}
}
// Types stores pointers to predeclared named types.
//
// It also stores pointers to several special types:
-// - Types[TANY] is the placeholder "any" type recognized by substArgTypes.
+// - Types[TANY] is the placeholder "any" type recognized by SubstArgTypes.
// - Types[TBLANK] represents the blank variable's type.
// - Types[TNIL] represents the predeclared "nil" value's type.
// - Types[TUNSAFEPTR] is package unsafe's Pointer type.
case TANY:
if len(*types) == 0 {
- base.Fatalf("substArgTypes: not enough argument types")
+ base.Fatalf("SubstArgTypes: not enough argument types")
}
t = (*types)[0]
*types = (*types)[1:]
nsrc := n.Args[0]
- // walkexprlistsafe will leave OINDEX (s[n]) alone if both s
+ // walkExprListSafe will leave OINDEX (s[n]) alone if both s
// and n are name or literal, but those may index the slice we're
// modifying here. Fix explicitly.
- // Using cheapexpr also makes sure that the evaluation
+ // Using cheapExpr also makes sure that the evaluation
// of all arguments (and especially any panics) happen
// before we begin to modify the slice in a visible way.
ls := n.Args[1:]
// n = arr[:l]
i := typecheck.IndexConst(r)
if i < 0 {
- base.Fatalf("walkexpr: invalid index %v", r)
+ base.Fatalf("walkExpr: invalid index %v", r)
}
// cap is constrained to [0,2^31) or [0,2^63) depending on whether
//
// clos = &struct{F uintptr; R T}{T.M·f, x}
//
- // Like walkclosure above.
+ // Like walkClosure above.
if n.X.Type().IsInterface() {
// Trigger panic for method on nil interface now.
// Should only arrive here with large memory or
// a struct/array containing a non-memory field/element.
// Small memory is handled inline, and single non-memory
- // is handled by walkcompare.
+ // is handled by walkCompare.
switch a, _ := types.AlgType(t); a {
case types.AMEM:
n := typecheck.LookupRuntime("memequal")
}))
return n, false
}
- base.Fatalf("eqfor %v", t)
+ base.Fatalf("eqFor %v", t)
return nil, false
}
}
func walkCheckPtrArithmetic(n *ir.ConvExpr, init *ir.Nodes) ir.Node {
- // Calling cheapexpr(n, init) below leads to a recursive call to
- // walkexpr, which leads us back here again. Use n.Checkptr to
+ // Calling cheapExpr(n, init) below leads to a recursive call to
+ // walkExpr, which leads us back here again. Use n.Checkptr to
// prevent infinite loops.
if n.CheckPtr() {
return n
// not okay to use n->ninit when walking n,
// because we might replace n with some other node
// and would lose the init list.
- base.Fatalf("walkexpr init == &n->ninit")
+ base.Fatalf("walkExpr init == &n->ninit")
}
if len(n.Init()) != 0 {
switch n.Op() {
default:
ir.Dump("walk", n)
- base.Fatalf("walkexpr: switch 1 unknown op %+v", n.Op())
+ base.Fatalf("walkExpr: switch 1 unknown op %+v", n.Op())
panic("unreachable")
case ir.ONONAME, ir.OGETG:
// TODO(mdempsky): Just return n; see discussion on CL 38655.
// Perhaps refactor to use Node.mayBeShared for these instead.
// If these return early, make sure to still call
- // stringsym for constant strings.
+ // StringSym for constant strings.
return n
case ir.OMETHEXPR:
return walkIndexMap(n, init)
case ir.ORECV:
- base.Fatalf("walkexpr ORECV") // should see inside OAS only
+ base.Fatalf("walkExpr ORECV") // should see inside OAS only
panic("unreachable")
case ir.OSLICEHEADER:
// make a copy; must not be used as an lvalue
if ir.IsAddressable(n) {
- base.Fatalf("missing lvalue case in safeexpr: %v", n)
+ base.Fatalf("missing lvalue case in safeExpr: %v", n)
}
return cheapExpr(n, init)
}
c := len(n.List)
if c < 2 {
- base.Fatalf("addstr count %d too small", c)
+ base.Fatalf("walkAddString count %d too small", c)
}
buf := typecheck.NodNil()
// Determine param type.
t := params.Field(i).Type
if base.Flag.Cfg.Instrumenting || fncall(arg, t) {
- // make assignment of fncall to tempAt
+ // make assignment of fncall to Temp
tmp := typecheck.Temp(t)
a := convas(ir.NewAssignStmt(base.Pos, tmp, arg), init)
tempAssigns = append(tempAssigns, a)
n.X = o.copyExpr(r)
// n.Prealloc is the temp for the iterator.
- // hiter contains pointers and needs to be zeroed.
+ // MapIterType contains pointers and needs to be zeroed.
n.Prealloc = o.newTemp(reflectdata.MapIterType(xt), true)
}
n.Key = o.exprInPlace(n.Key)
cas.Body.Prepend(o.cleanTempNoPop(t)...)
// TODO(mdempsky): Is this actually necessary?
- // walkselect appears to walk Ninit.
+ // walkSelect appears to walk Ninit.
cas.Body.Prepend(ir.TakeInit(cas)...)
}
o.cleanTemp(t)
// TODO(rsc): Clean temporaries more aggressively.
- // Note that because walkswitch will rewrite some of the
+ // Note that because walkSwitch will rewrite some of the
// switch into a binary search, this is not as easy as it looks.
// (If we ran that code here we could invoke order.stmt on
// the if-else chain instead.)
}
if v1 == nil && v2 != nil {
- base.Fatalf("walkrange: v2 != nil while v1 == nil")
+ base.Fatalf("walkRange: v2 != nil while v1 == nil")
}
var ifGuard *ir.IfStmt
var init []ir.Node
switch t.Kind() {
default:
- base.Fatalf("walkrange")
+ base.Fatalf("walkRange")
case types.TARRAY, types.TSLICE:
if nn := arrayClear(nrange, v1, v2, a); nn != nil {
hit := nrange.Prealloc
th := hit.Type()
- keysym := th.Field(0).Sym // depends on layout of iterator struct. See reflect.go:hiter
+ keysym := th.Field(0).Sym // depends on layout of iterator struct. See reflect.go:MapIterType
elemsym := th.Field(1).Sym // ditto
fn := typecheck.LookupRuntime("mapiterinit")
//
// in which the evaluation of a is side-effect-free.
//
-// Parameters are as in walkrange: "for v1, v2 = range a".
+// Parameters are as in walkRange: "for v1, v2 = range a".
func arrayClear(loop *ir.RangeStmt, v1, v2, a ir.Node) ir.Node {
if base.Flag.N != 0 || base.Flag.Cfg.Instrumenting {
return nil
func walkSelect(sel *ir.SelectStmt) {
lno := ir.SetPos(sel)
if len(sel.Compiled) != 0 {
- base.Fatalf("double walkselect")
+ base.Fatalf("double walkSelect")
}
init := ir.TakeInit(sel)
}
}
if nsends+nrecvs != ncas {
- base.Fatalf("walkselectcases: miscount: %v + %v != %v", nsends, nrecvs, ncas)
+ base.Fatalf("walkSelectCases: miscount: %v + %v != %v", nsends, nrecvs, ncas)
}
// run the select
// Given "switch string(byteslice)",
// with all cases being side-effect free,
// use a zero-cost alias of the byte slice.
- // Do this before calling walkexpr on cond,
- // because walkexpr will lower the string
+ // Do this before calling walkExpr on cond,
+ // because walkExpr will lower the string
// conversion into a runtime call.
// See issue 24937 for more discussion.
if cond.Op() == ir.OBYTES2STR && allCaseExprsAreSideEffectFree(sw) {
func walkAppendArgs(n *ir.CallExpr, init *ir.Nodes) {
walkExprListSafe(n.Args, init)
- // walkexprlistsafe will leave OINDEX (s[n]) alone if both s
+ // walkExprListSafe will leave OINDEX (s[n]) alone if both s
// and n are name or literal, but those may index the slice we're
// modifying here. Fix explicitly.
ls := n.Args
op := stmt.Op()
n := typecheck.Stmt(stmt)
if op == ir.OAS || op == ir.OAS2 {
- // If the assignment has side effects, walkexpr will append them
- // directly to init for us, while walkstmt will wrap it in an OBLOCK.
+ // If the assignment has side effects, walkExpr will append them
+ // directly to init for us, while walkStmt will wrap it in an OBLOCK.
// We need to append them directly.
// TODO(rsc): Clean this up.
n = walkExpr(n, init)
const maxOpenDefers = 8
// backingArrayPtrLen extracts the pointer and length from a slice or string.
-// This constructs two nodes referring to n, so n must be a cheapexpr.
+// This constructs two nodes referring to n, so n must be a cheapExpr.
func backingArrayPtrLen(n ir.Node) (ptr, length ir.Node) {
var init ir.Nodes
c := cheapExpr(n, &init)
// ifaceData loads the data field from an interface.
// The concrete type must be known to have type t.
-// It follows the pointer if !isdirectiface(t).
+// It follows the pointer if !IsDirectIface(t).
func ifaceData(pos src.XPos, n ir.Node, t *types.Type) ir.Node {
if t.IsInterface() {
base.Fatalf("ifaceData interface: %v", t)
// addBasicTypes returns the symbol names for basic types that are
// defined in the runtime and referenced in other packages.
-// Needs to be kept in sync with reflect.go:dumpbasictypes() and
-// reflect.go:dtypesym() in the compiler.
+// Needs to be kept in sync with reflect.go:WriteBasicTypes() and
+// reflect.go:writeType() in the compiler.
func enumerateBasicTypes() []extra {
names := [...]string{
"int8", "uint8", "int16", "uint16",
// This function uses its incoming context register.
NEEDCTXT = 64
- // When passed to ggloblsym, causes Local to be set to true on the LSym it creates.
+ // When passed to objw.Global, causes Local to be set to true on the LSym it creates.
LOCAL = 128
// Allocate a word of thread local storage and store the offset from the
// See the package documentation for more details about initializing an FS.
type FS struct {
// The compiler knows the layout of this struct.
- // See cmd/compile/internal/gc's initEmbed.
+ // See cmd/compile/internal/staticdata's WriteEmbed.
//
// The files list is sorted by name but not by simple string comparison.
// Instead, each file's name takes the form "dir/elem" or "dir/elem/".
// It implements fs.FileInfo and fs.DirEntry.
type file struct {
// The compiler knows the layout of this struct.
- // See cmd/compile/internal/gc's initEmbed.
+ // See cmd/compile/internal/staticdata's WriteEmbed.
name string
data string
hash [16]byte // truncated SHA256 hash
// Make a map type.
// Note: flag values must match those used in the TMAP case
- // in ../cmd/compile/internal/gc/reflect.go:dtypesym.
+ // in ../cmd/compile/internal/gc/reflect.go:writeType.
var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
mt := **(**mapType)(unsafe.Pointer(&imap))
mt.str = resolveReflectName(newName(s, "", false))
// layout of Itab known to compilers
// allocated in non-garbage-collected memory
// Needs to be in sync with
-// ../cmd/compile/internal/gc/reflect.go:/^func.dumptabs.
+// ../cmd/compile/internal/gc/reflect.go:/^func.WriteTabs.
type itab struct {
inter *interfacetype
_type *_type
}
// Note: flag values must match those used in the TMAP case
-// in ../cmd/compile/internal/gc/reflect.go:dtypesym.
+// in ../cmd/compile/internal/gc/reflect.go:writeType.
func (mt *maptype) indirectkey() bool { // store ptr to key instead of key itself
return mt.flags&1 != 0
}