本文整理汇总了Golang中code/google/com/p/go/tools/go/ssa.Function类的典型用法代码示例。如果您正苦于以下问题:Golang Function类的具体用法?Golang Function怎么用?Golang Function使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了Function类的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: Switches
// Switches examines the control-flow graph of fn and returns the
// set of inferred value and type switches. A value switch tests an
// ssa.Value for equality against two or more compile-time constant
// values. Switches involving link-time constants (addresses) are
// ignored. A type switch type-asserts an ssa.Value against two or
// more types.
//
// The switches are returned in dominance order.
//
// The resulting switches do not necessarily correspond to uses of the
// 'switch' keyword in the source: for example, a single source-level
// switch statement with non-constant cases may result in zero, one or
// many Switches, one per plural sequence of constant cases.
// Switches may even be inferred from if/else- or goto-based control flow.
// (In general, the control flow constructs of the source program
// cannot be faithfully reproduced from the SSA representation.)
//
func Switches(fn *ssa.Function) []Switch {
// Traverse the CFG in dominance order, so we don't
// enter an if/else-chain in the middle.
var switches []Switch
seen := make(map[*ssa.BasicBlock]bool) // TODO(adonovan): opt: use ssa.blockSet
for _, b := range fn.DomPreorder() {
if x, k := isComparisonBlock(b); x != nil {
// Block b starts a switch.
sw := Switch{Start: b, X: x}
valueSwitch(&sw, k, seen)
if len(sw.ConstCases) > 1 {
switches = append(switches, sw)
}
}
if y, x, T := isTypeAssertBlock(b); y != nil {
// Block b starts a type switch.
sw := Switch{Start: b, X: x}
typeSwitch(&sw, y, T, seen)
if len(sw.TypeCases) > 1 {
switches = append(switches, sw)
}
}
}
return switches
}
示例2: callSSA
// callSSA interprets a call to function fn with arguments args,
// and lexical environment env, returning its result.
// callpos is the position of the callsite.
//
func callSSA(i *interpreter, caller *frame, callpos token.Pos, fn *ssa.Function, args []value, env []value) value {
if i.mode&EnableTracing != 0 {
fset := fn.Prog.Fset
// TODO(adonovan): fix: loc() lies for external functions.
fmt.Fprintf(os.Stderr, "Entering %s%s.\n", fn, loc(fset, fn.Pos()))
suffix := ""
if caller != nil {
suffix = ", resuming " + caller.fn.String() + loc(fset, callpos)
}
defer fmt.Fprintf(os.Stderr, "Leaving %s%s.\n", fn, suffix)
}
fr := &frame{
i: i,
caller: caller, // for panic/recover
fn: fn,
}
if fn.Enclosing == nil {
name := fn.String()
if ext := externals[name]; ext != nil {
if i.mode&EnableTracing != 0 {
fmt.Fprintln(os.Stderr, "\t(external)")
}
return ext(fr, args)
}
if fn.Blocks == nil {
panic("no code for function: " + name)
}
}
fr.env = make(map[ssa.Value]value)
fr.block = fn.Blocks[0]
fr.locals = make([]value, len(fn.Locals))
for i, l := range fn.Locals {
fr.locals[i] = zero(deref(l.Type()))
fr.env[l] = &fr.locals[i]
}
for i, p := range fn.Params {
fr.env[p] = args[i]
}
for i, fv := range fn.FreeVars {
fr.env[fv] = env[i]
}
for fr.block != nil {
runFrame(fr)
}
// Destroy the locals to avoid accidental use after return.
for i := range fn.Locals {
fr.locals[i] = bad{}
}
return fr.result
}
示例3: prettyFunc
// prettyFunc pretty-prints fn for the user interface.
// TODO(adonovan): return HTML so we have more markup freedom.
func prettyFunc(this *types.Package, fn *ssa.Function) string {
if fn.Enclosing != nil {
return fmt.Sprintf("%s in %s",
types.TypeString(this, fn.Signature),
prettyFunc(this, fn.Enclosing))
}
if fn.Synthetic != "" && fn.Name() == "init" {
// (This is the actual initializer, not a declared 'func init').
if fn.Pkg.Object == this {
return "package initializer"
}
return fmt.Sprintf("%q package initializer", fn.Pkg.Object.Path())
}
return fn.RelString(this)
}
示例4: emitFuncStart
// Emit the start of a function.
func emitFuncStart(fn *ssa.Function, trackPhi bool, canOptMap map[string]bool) {
posStr := CodePosition(fn.Pos())
pName := "unknown" // TODO review why this code appears to duplicate that at the start of emitFunctions()
if fn.Pkg != nil {
if fn.Pkg.Object != nil {
pName = fn.Pkg.Object.Name()
}
}
mName := fn.Name()
if fn.Signature.Recv() != nil { // we have a method
pName = fn.Signature.Recv().Type().String() // note no underlying()
}
isPublic := unicode.IsUpper(rune(mName[0])) // TODO check rules for non-ASCII 1st characters and fix
l := TargetLang
fmt.Fprintln(&LanguageList[l].buffer,
LanguageList[l].FuncStart(pName, mName, fn, posStr, isPublic, trackPhi, canOptMap))
}
示例5: funcToken
func funcToken(fn *ssa.Function) token.Pos {
switch syntax := fn.Syntax().(type) {
case *ast.FuncLit:
return syntax.Type.Func
case *ast.FuncDecl:
return syntax.Type.Func
}
return token.NoPos
}
示例6: findIntrinsic
// findIntrinsic returns the constraint generation function for an
// intrinsic function fn, or nil if the function should be handled normally.
//
func (a *analysis) findIntrinsic(fn *ssa.Function) intrinsic {
// Consult the *Function-keyed cache.
// A cached nil indicates a normal non-intrinsic function.
impl, ok := a.intrinsics[fn]
if !ok {
impl = intrinsicsByName[fn.String()] // may be nil
if a.isReflect(fn) {
if !a.config.Reflection {
impl = ext۰NoEffect // reflection disabled
} else if impl == nil {
// Ensure all "reflect" code is treated intrinsically.
impl = ext۰NotYetImplemented
}
}
a.intrinsics[fn] = impl
}
return impl
}
示例7: resolveFunction
func (u *unit) resolveFunction(f *ssa.Function) *LLVMValue {
if v, ok := u.globals[f]; ok {
return v
}
name := f.String()
if f.Enclosing != nil {
// Anonymous functions are not guaranteed to
// have unique identifiers at the global scope.
name = f.Enclosing.String() + ":" + name
}
// It's possible that the function already exists in the module;
// for example, if it's a runtime intrinsic that the compiler
// has already referenced.
llvmFunction := u.module.Module.NamedFunction(name)
if llvmFunction.IsNil() {
llvmType := u.llvmtypes.ToLLVM(f.Signature)
llvmType = llvmType.StructElementTypes()[0].ElementType()
if len(f.FreeVars) > 0 {
// Add an implicit first argument.
returnType := llvmType.ReturnType()
paramTypes := llvmType.ParamTypes()
vararg := llvmType.IsFunctionVarArg()
blockElementTypes := make([]llvm.Type, len(f.FreeVars))
for i, fv := range f.FreeVars {
blockElementTypes[i] = u.llvmtypes.ToLLVM(fv.Type())
}
blockType := llvm.StructType(blockElementTypes, false)
blockPtrType := llvm.PointerType(blockType, 0)
paramTypes = append([]llvm.Type{blockPtrType}, paramTypes...)
llvmType = llvm.FunctionType(returnType, paramTypes, vararg)
}
llvmFunction = llvm.AddFunction(u.module.Module, name, llvmType)
if f.Enclosing != nil {
llvmFunction.SetLinkage(llvm.PrivateLinkage)
}
u.undefinedFuncs[f] = true
}
v := u.NewValue(llvmFunction, f.Signature)
u.globals[f] = v
return v
}
示例8: FuncName
func (l langType) FuncName(fnx *ssa.Function) string {
pn := ""
if fnx.Signature.Recv() != nil {
pn = fnx.Signature.Recv().Type().String() // NOTE no use of underlying here
} else {
pn = "unknown"
fn := fnx
if fn.Enclosing != nil {
fn = fn.Enclosing
}
if fn.Pkg != nil {
if fn.Pkg.Object != nil {
pn = fn.Pkg.Object.Name()
}
} else {
if fn.Object() != nil {
if fn.Object().Pkg() != nil {
pn = fn.Object().Pkg().Name()
}
}
}
}
return l.LangName(pn, fnx.Name())
}
示例9: defineFunction
func (u *unit) defineFunction(f *ssa.Function) {
// Nothing to do for functions without bodies.
if len(f.Blocks) == 0 {
return
}
// Only define functions from this package.
if f.Pkg == nil {
if r := f.Signature.Recv(); r != nil {
if r.Pkg() != nil && r.Pkg() != u.pkg.Object {
return
} else if named, ok := r.Type().(*types.Named); ok && named.Obj().Parent() == types.Universe {
// This condition is true iff f is error.Error.
if u.pkg.Object.Path() != "runtime" {
return
}
}
}
} else if f.Pkg != u.pkg {
return
}
fr := frame{
unit: u,
blocks: make([]llvm.BasicBlock, len(f.Blocks)),
env: make(map[ssa.Value]*LLVMValue),
}
fr.logf("Define function: %s", f.String())
llvmFunction := fr.resolveFunction(f).LLVMValue()
delete(u.undefinedFuncs, f)
// Push the function onto the debug context.
// TODO(axw) create a fake CU for synthetic functions
if u.GenerateDebug && f.Synthetic == "" {
u.debug.pushFunctionContext(llvmFunction, f.Signature, f.Pos())
defer u.debug.popFunctionContext()
u.debug.setLocation(u.builder, f.Pos())
}
// Functions that call recover must not be inlined, or we
// can't tell whether the recover call is valid at runtime.
if f.Recover != nil {
llvmFunction.AddFunctionAttr(llvm.NoInlineAttribute)
}
for i, block := range f.Blocks {
fr.blocks[i] = llvm.AddBasicBlock(llvmFunction, fmt.Sprintf(".%d.%s", i, block.Comment))
}
fr.builder.SetInsertPointAtEnd(fr.blocks[0])
var paramOffset int
if len(f.FreeVars) > 0 {
// Extract captures from the first implicit parameter.
arg0 := llvmFunction.Param(0)
for i, fv := range f.FreeVars {
addressPtr := fr.builder.CreateStructGEP(arg0, i, "")
address := fr.builder.CreateLoad(addressPtr, "")
fr.env[fv] = fr.NewValue(address, fv.Type())
}
paramOffset++
}
// Map parameter positions to indices. We use this
// when processing locals to map back to parameters
// when generating debug metadata.
paramPos := make(map[token.Pos]int)
for i, param := range f.Params {
paramPos[param.Pos()] = i + paramOffset
llparam := llvmFunction.Param(i + paramOffset)
fr.env[param] = fr.NewValue(llparam, param.Type())
}
// Allocate stack space for locals in the prologue block.
prologueBlock := llvm.InsertBasicBlock(fr.blocks[0], "prologue")
fr.builder.SetInsertPointAtEnd(prologueBlock)
for _, local := range f.Locals {
typ := fr.llvmtypes.ToLLVM(deref(local.Type()))
alloca := fr.builder.CreateAlloca(typ, local.Comment)
u.memsetZero(alloca, llvm.SizeOf(typ))
value := fr.NewValue(alloca, local.Type())
fr.env[local] = value
if fr.GenerateDebug {
paramIndex, ok := paramPos[local.Pos()]
if !ok {
paramIndex = -1
}
fr.debug.declare(fr.builder, local, alloca, paramIndex)
}
}
// Move any allocs relating to named results from the entry block
// to the prologue block, so they dominate the rundefers and recover
// blocks.
//
// TODO(axw) ask adonovan for a cleaner way of doing this, e.g.
// have ssa generate an entry block that defines Allocs and related
// stores, and then a separate block for function body instructions.
if f.Synthetic == "" {
if results := f.Signature.Results(); results != nil {
for i := 0; i < results.Len(); i++ {
//.........这里部分代码省略.........
示例10: emitFunc
// Emit a particular function.
func emitFunc(fn *ssa.Function) {
/* TODO research if the ssautil.Switches() function can be incorporated to provide any run-time improvement to the code
sw := ssautil.Switches(fn)
if len(sw) > 0 {
fmt.Printf("DEBUG Switches: %s = %+v\n", fn, sw)
}
*/
subFnList := make([]subFnInstrs, 0)
canOptMap := make(map[string]bool) // TODO review use of this mechanism
//println("DEBUG processing function: ", fn.Name())
MakePosHash(fn.Pos()) // mark that we have entered a function
trackPhi := true
switch len(fn.Blocks) {
case 0: // NoOp - only output a function if it has a body... so ignore pure definitions (target language may generate an error, if truely undef)
//fmt.Printf("DEBUG function has no body, ignored: %v %v \n", fn.Name(), fn.String())
case 1: // Only one block, so no Phi tracking required
trackPhi = false
fallthrough
default:
if trackPhi {
// check that there actually are Phi instructions to track
trackPhi = false
phiSearch:
for b := range fn.Blocks {
for i := range fn.Blocks[b].Instrs {
_, trackPhi = fn.Blocks[b].Instrs[i].(*ssa.Phi)
if trackPhi {
break phiSearch
}
}
}
}
instrCount := 0
for b := range fn.Blocks {
instrCount += len(fn.Blocks[b].Instrs)
}
mustSplitCode := false
if instrCount > LanguageList[TargetLang].InstructionLimit {
//println("DEBUG mustSplitCode => large function length:", instrCount, " in ", fn.Name())
mustSplitCode = true
}
for b := range fn.Blocks { // go though the blocks looking for sub-functions
instrsEmitted := 0
inSubFn := false
for i := range fn.Blocks[b].Instrs {
canPutInSubFn := true
in := fn.Blocks[b].Instrs[i]
switch in.(type) {
case *ssa.Phi: // phi uses self-referential temp vars that must be pre-initialised
canPutInSubFn = false
case *ssa.Return:
canPutInSubFn = false
case *ssa.Call:
switch in.(*ssa.Call).Call.Value.(type) {
case *ssa.Builtin:
//NoOp
default:
canPutInSubFn = false
}
case *ssa.Select, *ssa.Send, *ssa.Defer, *ssa.RunDefers, *ssa.Panic:
canPutInSubFn = false
case *ssa.UnOp:
if in.(*ssa.UnOp).Op == token.ARROW {
canPutInSubFn = false
}
}
if canPutInSubFn {
if inSubFn {
if instrsEmitted > LanguageList[TargetLang].SubFnInstructionLimit {
subFnList[len(subFnList)-1].end = i
subFnList = append(subFnList, subFnInstrs{b, i, 0})
instrsEmitted = 0
}
} else {
subFnList = append(subFnList, subFnInstrs{b, i, 0})
inSubFn = true
}
} else {
if inSubFn {
subFnList[len(subFnList)-1].end = i
inSubFn = false
}
}
instrsEmitted++
}
if inSubFn {
subFnList[len(subFnList)-1].end = len(fn.Blocks[b].Instrs)
}
}
for sf := range subFnList { // go though the sub-functions looking for optimisable temp vars
var instrMap = make(map[ssa.Instruction]bool)
for ii := subFnList[sf].start; ii < subFnList[sf].end; ii++ {
instrMap[fn.Blocks[subFnList[sf].block].Instrs[ii]] = true
}
for i := subFnList[sf].start; i < subFnList[sf].end; i++ {
//.........这里部分代码省略.........