本文整理汇总了Golang中code/google/com/p/go/tools/ssa.Function类的典型用法代码示例。如果您正苦于以下问题:Golang Function类的具体用法?Golang Function怎么用?Golang Function使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了Function类的7个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的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: makeFunction
// makeFunction creates the shared function object (aka contour) for
// function fn and returns a 'func' value node that points to it.
//
func (a *analysis) makeFunction(fn *ssa.Function) nodeid {
obj := a.makeFunctionObject(fn)
a.funcObj[fn] = obj
var comment string
if a.log != nil {
comment = fn.String()
}
id := a.addOneNode(fn.Type(), comment, nil)
a.addressOf(id, obj)
return id
}
示例3: 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)
}
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(fn, args)
}
if fn.Blocks == nil {
panic("no code for function: " + name)
}
}
fr := &frame{
i: i,
caller: caller, // currently unused; for unwinding.
fn: fn,
env: make(map[ssa.Value]value),
block: fn.Blocks[0],
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
}
示例4: 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 fn.Pkg != nil && a.reflectValueObj != nil && a.reflectValueObj.Pkg() == fn.Pkg.Object {
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
}
示例5: resolveFunction
func (u *unit) resolveFunction(f *ssa.Function) *LLVMValue {
if v, ok := u.globals[f]; ok {
return v
}
name := f.String()
// 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
}
示例6: 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 && r.Pkg() != nil && r.Pkg() != u.pkg.Object {
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)
// 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++
}
for i, param := range f.Params {
fr.env[param] = fr.NewValue(llvmFunction.Param(i+paramOffset), 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
}
// 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++ {
result := results.At(i)
if result.Name() == "" {
break
}
for i, instr := range f.Blocks[0].Instrs {
if instr, ok := instr.(*ssa.Alloc); ok && instr.Heap && instr.Pos() == result.Pos() {
fr.instruction(instr)
instrs := f.Blocks[0].Instrs
instrs = append(instrs[:i], instrs[i+1:]...)
f.Blocks[0].Instrs = instrs
break
}
}
}
}
}
// If the function contains any defers, we must first call
// setjmp so we can call rundefers in response to a panic.
// We can short-circuit the check for defers with
// f.Recover != nil.
if f.Recover != nil || hasDefer(f) {
rdblock := llvm.AddBasicBlock(llvmFunction, "rundefers")
defers := fr.builder.CreateAlloca(fr.runtime.defers.llvm, "")
fr.builder.CreateCall(fr.runtime.initdefers.LLVMValue(), []llvm.Value{defers}, "")
jb := fr.builder.CreateStructGEP(defers, 0, "")
jb = fr.builder.CreateBitCast(jb, llvm.PointerType(llvm.Int8Type(), 0), "")
result := fr.builder.CreateCall(fr.runtime.setjmp.LLVMValue(), []llvm.Value{jb}, "")
//.........这里部分代码省略.........
示例7: 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.Files
// TODO(adonovan): fix: loc() lies for external functions.
fmt.Fprintf(os.Stderr, "Entering %s%s.\n", fn.FullName(), loc(fset, fn.Pos()))
suffix := ""
if caller != nil {
suffix = ", resuming " + caller.fn.FullName() + loc(fset, callpos)
}
defer fmt.Fprintf(os.Stderr, "Leaving %s%s.\n", fn.FullName(), suffix)
}
if fn.Enclosing == nil {
name := fn.FullName()
if ext := externals[name]; ext != nil {
if i.mode&EnableTracing != 0 {
fmt.Fprintln(os.Stderr, "\t(external)")
}
return ext(fn, args)
}
if fn.Blocks == nil {
panic("no code for function: " + name)
}
}
fr := &frame{
i: i,
caller: caller, // currently unused; for unwinding.
fn: fn,
env: make(map[ssa.Value]value),
block: fn.Blocks[0],
locals: make([]value, len(fn.Locals)),
}
for i, l := range fn.Locals {
fr.locals[i] = zero(l.Type().Deref())
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]
}
var instr ssa.Instruction
defer func() {
if fr.status != stComplete {
if fr.i.mode&DisableRecover != 0 {
return // let interpreter crash
}
fr.status, fr.panic = stPanic, recover()
}
fr.rundefers()
// Destroy the locals to avoid accidental use after return.
for i := range fn.Locals {
fr.locals[i] = bad{}
}
if fr.status == stPanic {
panic(fr.panic) // panic stack is not entirely clean
}
}()
for {
if i.mode&EnableTracing != 0 {
fmt.Fprintf(os.Stderr, ".%s:\n", fr.block)
}
block:
for _, instr = range fr.block.Instrs {
if i.mode&EnableTracing != 0 {
if v, ok := instr.(ssa.Value); ok {
fmt.Fprintln(os.Stderr, "\t", v.Name(), "=", instr)
} else {
fmt.Fprintln(os.Stderr, "\t", instr)
}
}
switch visitInstr(fr, instr) {
case kReturn:
fr.status = stComplete
return fr.result
case kNext:
// no-op
case kJump:
break block
}
}
}
panic("unreachable")
}