Exemple #1
0
func (f *Function) AllocInstr(instr *ssa.Alloc) (string, *Error) {
	asm := ""
	if instr == nil {
		return ErrorMsg("AllocInstr: nil instr")

	}
	if instr.Heap {
		msg := "Heap allocations are unsupported (are all print and log statements removed?), ssa variable: %v, type: %v"
		msgstr := fmt.Sprintf(msg, instr.Name(), instr.Type())
		return ErrorMsg(msgstr)
	}

	//Alloc values are always addresses, and have pointer types, so the type
	//of the allocated variable is actually
	//Type().Underlying().(*types.Pointer).Elem().
	info := f.identifiers[instr.Name()]
	if info.local == nil {
		ice(fmt.Sprintf("expected %v to be a local variable", instr.Name()))
	}
	if _, ok := info.typ.(*types.Pointer); ok {
	} else {
	}
	f.identifiers[instr.Name()] = info
	return asm, nil
}
Exemple #2
0
func visitAlloc(instr *ssa.Alloc, infer *TypeInfer, ctx *Context) {
	allocType := instr.Type().(*types.Pointer).Elem()
	switch t := allocType.Underlying().(type) {
	case *types.Array: // Static size array
		ctx.F.locals[instr] = &Value{instr, ctx.F.InstanceID(), ctx.L.Index}
		if instr.Heap {
			ctx.F.Prog.arrays[ctx.F.locals[instr]] = make(Elems, t.Len())
			infer.Logger.Print(ctx.F.Sprintf(NewSymbol+"%s = alloc (array@heap) of type %s (%d elems)", ctx.F.locals[instr], instr.Type(), t.Len()))
		} else {
			ctx.F.arrays[ctx.F.locals[instr]] = make(Elems, t.Len())
			infer.Logger.Print(ctx.F.Sprintf(NewSymbol+"%s = alloc (array@local) of type %s (%d elems)", ctx.F.locals[instr], instr.Type(), t.Len()))
		}
	case *types.Struct:
		ctx.F.locals[instr] = &Value{instr, ctx.F.InstanceID(), ctx.L.Index}
		if instr.Heap {
			ctx.F.Prog.structs[ctx.F.locals[instr]] = make(Fields, t.NumFields())
			infer.Logger.Print(ctx.F.Sprintf(NewSymbol+"%s = alloc (struct@heap) of type %s (%d fields)", ctx.F.locals[instr], instr.Type(), t.NumFields()))
		} else {
			ctx.F.structs[ctx.F.locals[instr]] = make(Fields, t.NumFields())
			infer.Logger.Print(ctx.F.Sprintf(NewSymbol+"%s = alloc (struct@local) of type %s (%d fields)", ctx.F.locals[instr], instr.Type(), t.NumFields()))
		}
	case *types.Pointer:
		switch pt := t.Elem().Underlying().(type) {
		case *types.Array:
			ctx.F.locals[instr] = &Value{instr, ctx.F.InstanceID(), ctx.L.Index}
			if instr.Heap {
				ctx.F.Prog.arrays[ctx.F.locals[instr]] = make(Elems, pt.Len())
				infer.Logger.Print(ctx.F.Sprintf(NewSymbol+"%s = alloc/indirect (array@heap) of type %s (%d elems)", ctx.F.locals[instr], instr.Type(), pt.Len()))
			} else {
				ctx.F.locals[instr] = &Value{instr, ctx.F.InstanceID(), ctx.L.Index}
				ctx.F.arrays[ctx.F.locals[instr]] = make(Elems, pt.Len())
				infer.Logger.Print(ctx.F.Sprintf(NewSymbol+"%s = alloc/indirect (array@local) of type %s (%d elems)", ctx.F.locals[instr], instr.Type(), pt.Len()))
			}
		case *types.Struct:
			ctx.F.locals[instr] = &Value{instr, ctx.F.InstanceID(), ctx.L.Index}
			if instr.Heap {
				ctx.F.Prog.structs[ctx.F.locals[instr]] = make(Fields, pt.NumFields())
				infer.Logger.Print(ctx.F.Sprintf(NewSymbol+"%s = alloc/indirect (struct@heap) of type %s (%d fields)", ctx.F.locals[instr], instr.Type(), pt.NumFields()))
			} else {
				ctx.F.structs[ctx.F.locals[instr]] = make(Fields, pt.NumFields())
				infer.Logger.Print(ctx.F.Sprintf(NewSymbol+"%s = alloc/indirect (struct@local) of type %s (%d fields)", ctx.F.locals[instr], instr.Type(), pt.NumFields()))
			}
		default:
			ctx.F.locals[instr] = &Value{instr, ctx.F.InstanceID(), ctx.L.Index}
			infer.Logger.Print(ctx.F.Sprintf(NewSymbol+"%s = alloc/indirect of type %s", ctx.F.locals[instr], instr.Type().Underlying()))
		}
	default:
		ctx.F.locals[instr] = &Value{instr, ctx.F.InstanceID(), ctx.L.Index}
		infer.Logger.Print(ctx.F.Sprintf(NewSymbol+"%s = alloc of type %s", ctx.F.locals[instr], instr.Type().Underlying()))
	}
}
Exemple #3
0
// Return true iff we think it might be beneficial to turn this alloc instruction
// into a statically allocated global.
// Precondition: we are compiling the init function.
func (fr *frame) shouldStaticallyAllocate(alloc *ssa.Alloc) bool {
	// First, see if the allocated type is an array or struct, and if so determine
	// the number of elements in the type. If the type is anything else, we
	// statically allocate unconditionally.
	var numElems int64
	switch ty := deref(alloc.Type()).Underlying().(type) {
	case *types.Array:
		numElems = ty.Len()
	case *types.Struct:
		numElems = int64(ty.NumFields())
	default:
		return true
	}

	// We treat the number of referrers to the alloc instruction as a rough
	// proxy for the number of elements initialized. If the data structure
	// is densely initialized (> 1/4 elements initialized), enable the
	// optimization.
	return int64(len(*alloc.Referrers()))*4 > numElems
}
Exemple #4
0
// visitAlloc is for variable allocation (usually by 'new')
// Everything allocated here are pointers
func visitAlloc(inst *ssa.Alloc, fr *frame) {
	locn := loc(fr, inst.Pos())
	allocType := inst.Type().(*types.Pointer).Elem()
	if allocType == nil {
		panic("Alloc: Cannot Alloc for non-pointer type")
	}
	var val ssa.Value = inst

	switch t := allocType.Underlying().(type) {
	case *types.Array:
		vd := utils.NewDef(val)
		fr.locals[val] = vd
		if inst.Heap {
			fr.env.arrays[vd] = make(Elems)
			fmt.Fprintf(os.Stderr, "   %s = Alloc (array@heap) of type %s (%d elems) at %s\n", cyan(reg(inst)), inst.Type().String(), t.Len(), locn)
		} else {
			fr.arrays[vd] = make(Elems)
			fmt.Fprintf(os.Stderr, "   %s = Alloc (array@local) of type %s (%d elems) at %s\n", cyan(reg(inst)), inst.Type().String(), t.Len(), locn)
		}

	case *types.Chan:
		// VD will be created in MakeChan so no need to allocate here.
		fmt.Fprintf(os.Stderr, "   %s = Alloc (chan) of type %s at %s\n", cyan(reg(inst)), inst.Type().String(), locn)

	case *types.Struct:
		vd := utils.NewDef(val)
		fr.locals[val] = vd
		if inst.Heap {
			fr.env.structs[vd] = make(Fields, t.NumFields())
			fmt.Fprintf(os.Stderr, "   %s = Alloc (struct@heap) of type %s (%d fields) at %s\n", cyan(reg(inst)), inst.Type().String(), t.NumFields(), locn)
		} else {
			fr.structs[vd] = make(Fields, t.NumFields())
			fmt.Fprintf(os.Stderr, "   %s = Alloc (struct@local) of type %s (%d fields) at %s\n", cyan(reg(inst)), inst.Type().String(), t.NumFields(), locn)
		}

	default:
		fmt.Fprintf(os.Stderr, "   # %s = "+red("Alloc %s")+" of type %s\n", inst.Name(), inst.String(), t.String())
	}
}