作者:bryanx
项目:go-zh.tool
// genInvoke generates constraints for a dynamic method invocation.
func (a *analysis) genInvoke(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
if call.Value.Type() == a.reflectType {
a.genInvokeReflectType(caller, site, call, result)
return
}
sig := call.Signature()
// Allocate a contiguous targets/params/results block for this call.
block := a.nextNode()
// pts(targets) will be the set of possible call targets
site.targets = a.addOneNode(sig, "invoke.targets", nil)
p := a.addNodes(sig.Params(), "invoke.params")
r := a.addNodes(sig.Results(), "invoke.results")
// Copy the actual parameters into the call's params block.
for i, n := 0, sig.Params().Len(); i < n; i++ {
sz := a.sizeof(sig.Params().At(i).Type())
a.copy(p, a.valueNode(call.Args[i]), sz)
p += nodeid(sz)
}
// Copy the call's results block to the actual results.
if result != 0 {
a.copy(result, r, a.sizeof(sig.Results()))
}
// We add a dynamic invoke constraint that will connect the
// caller's and the callee's P/R blocks for each discovered
// call target.
a.addConstraint(&invokeConstraint{call.Method, a.valueNode(call.Value), block})
}
作者:bryanx
项目:go-zh.tool
// genStaticCall generates constraints for a statically dispatched function call.
func (a *analysis) genStaticCall(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
fn := call.StaticCallee()
// Special cases for inlined intrinsics.
switch fn {
case a.runtimeSetFinalizer:
// Inline SetFinalizer so the call appears direct.
site.targets = a.addOneNode(tInvalid, "SetFinalizer.targets", nil)
a.addConstraint(&runtimeSetFinalizerConstraint{
targets: site.targets,
x: a.valueNode(call.Args[0]),
f: a.valueNode(call.Args[1]),
})
return
case a.reflectValueCall:
// Inline (reflect.Value).Call so the call appears direct.
dotdotdot := false
ret := reflectCallImpl(a, caller, site, a.valueNode(call.Args[0]), a.valueNode(call.Args[1]), dotdotdot)
if result != 0 {
a.addressOf(fn.Signature.Results().At(0).Type(), result, ret)
}
return
}
// Ascertain the context (contour/cgnode) for a particular call.
var obj nodeid
if a.shouldUseContext(fn) {
obj = a.makeFunctionObject(fn, site) // new contour
} else {
obj = a.objectNode(nil, fn) // shared contour
}
a.callEdge(caller, site, obj)
sig := call.Signature()
// Copy receiver, if any.
params := a.funcParams(obj)
args := call.Args
if sig.Recv() != nil {
sz := a.sizeof(sig.Recv().Type())
a.copy(params, a.valueNode(args[0]), sz)
params += nodeid(sz)
args = args[1:]
}
// Copy actual parameters into formal params block.
// Must loop, since the actuals aren't contiguous.
for i, arg := range args {
sz := a.sizeof(sig.Params().At(i).Type())
a.copy(params, a.valueNode(arg), sz)
params += nodeid(sz)
}
// Copy formal results block to actual result.
if result != 0 {
a.copy(result, a.funcResults(obj), a.sizeof(sig.Results()))
}
}
作者:bryanx
项目:go-zh.tool
// genDynamicCall generates constraints for a dynamic function call.
func (a *analysis) genDynamicCall(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
// pts(targets) will be the set of possible call targets.
site.targets = a.valueNode(call.Value)
// We add dynamic closure rules that store the arguments into
// the P-block and load the results from the R-block of each
// function discovered in pts(targets).
sig := call.Signature()
var offset uint32 = 1 // P/R block starts at offset 1
for i, arg := range call.Args {
sz := a.sizeof(sig.Params().At(i).Type())
a.genStore(caller, call.Value, a.valueNode(arg), offset, sz)
offset += sz
}
if result != 0 {
a.genLoad(caller, result, call.Value, offset, a.sizeof(sig.Results()))
}
}
作者:pombredann
项目:tardisg
// Emit the code for a call to a function or builtin, which could be deferred.
func emitCall(isBuiltin, isGo, isDefer bool, register string, callInfo ssa.CallCommon, errorInfo, comment string) {
l := TargetLang
fnToCall := ""
if isBuiltin {
fnToCall = callInfo.Value.(*ssa.Builtin).Name()
} else if callInfo.StaticCallee() != nil {
pName := "unknown"
if callInfo.Signature().Recv() != nil {
pName = callInfo.Signature().Recv().Type().String() // no use of Underlying() here
} else {
pkg := callInfo.StaticCallee().Pkg
if pkg != nil {
pName = pkg.Object.Name()
}
}
fnToCall = LanguageList[l].LangName(pName, callInfo.StaticCallee().Name())
} else { // Dynamic call
fnToCall = LanguageList[l].Value(callInfo.Value, errorInfo)
}
if isBuiltin {
switch fnToCall {
case "len", "cap", "append", "real", "imag", "complex": // "copy" may have the results unused
if register == "" {
LogError(errorInfo, "pogo", fmt.Errorf("the result from a built-in function is not used"))
} else {
}
default:
}
} else {
if callInfo.Signature().Results().Len() > 0 {
if register == "" {
LogWarning(errorInfo, "pogo", fmt.Errorf("the result from a function call is not used")) //TODO is this needed?
} else {
}
}
}
// target language code must do builtin emulation
text := LanguageList[l].Call(register, callInfo, callInfo.Args, isBuiltin, isGo, isDefer, fnToCall, errorInfo)
fmt.Fprintln(&LanguageList[l].buffer, text+LanguageList[l].Comment(comment))
}
作者:pombredann
项目:tardisg
func (l langType) Call(register string, cc ssa.CallCommon, args []ssa.Value, isBuiltin, isGo, isDefer bool, fnToCall, errorInfo string) string {
isHaxeAPI := false
hashIf := "" // #if - only if required
hashEnd := "" // #end - ditto
ret := ""
pn := "" // package name
if isBuiltin {
if register != "" {
register += "="
}
switch fnToCall { // TODO handle other built-in functions?
case "len", "cap":
switch args[0].Type().Underlying().(type) {
case *types.Chan, *types.Slice:
if fnToCall == "len" {
return register + "({var _v=" + l.IndirectValue(args[0], errorInfo) + ";_v==null?0:_v.len();});"
}
// cap
return register + "({var _v=" + l.IndirectValue(args[0], errorInfo) + ";_v==null?0:_v.cap();});"
case *types.Array: // assume len
return register + l.IndirectValue(args[0], errorInfo /*, false*/) + ".length;"
case *types.Map: // assume len(map) - requires counting the itterator
return register + l.IndirectValue(args[0], errorInfo) + "==null?0:{var _l:Int=0;" + // TODO remove two uses of same variable
"var _it=" + l.IndirectValue(args[0], errorInfo) + ".iterator();" +
"while(_it.hasNext()) {_l++; _it.next();};" +
"_l;};"
case *types.Basic: // assume string as anything else would have produced an error previously
return register + "Force.toUTF8length(this._goroutine," + l.IndirectValue(args[0], errorInfo /*, false*/) + ");"
default: // TODO handle other types?
// TODO error on string?
pogo.LogError(errorInfo, "Haxe", fmt.Errorf("haxe.Call() - unhandled len/cap type: %s",
reflect.TypeOf(args[0].Type().Underlying())))
return register + `null;`
}
case "print", "println": // NOTE ugly and target-specific output!
ret += "trace(" + fmt.Sprintf("Go.CPos(%d)", pogo.LatestValidPosHash)
if len(args) > 0 { // if there are more arguments to pass, add a comma
ret += ","
}
case "delete":
if l.LangType(args[1].Type().Underlying(), false, errorInfo) == "GOint64" {
//useInt64 = true
}
return register + l.IndirectValue(args[0], errorInfo) + ".remove(" + l.IndirectValue(args[1], errorInfo) + ");"
case "append":
return register + l.append(args, errorInfo) + ";"
case "copy": //TODO rework & test
return register + "{var _n={if(" + l.IndirectValue(args[0], errorInfo) + ".len()<" + l.IndirectValue(args[1], errorInfo) + ".len())" +
l.IndirectValue(args[0], errorInfo) + ".len();else " + l.IndirectValue(args[1], errorInfo) + ".len();};" +
"for(_i in 0..._n)" + l.IndirectValue(args[0], errorInfo) + ".setAt(_i,Deep.copy(" + l.IndirectValue(args[1], errorInfo) +
`.getAt(_i` + `))` + `);` +
"_n;};" // TODO remove two uses of same variable in case of side-effects
case "close":
return register + "" + l.IndirectValue(args[0], errorInfo) + ".close();"
case "recover":
return register + "" + "Scheduler.recover(this._goroutine);"
case "real":
return register + "" + l.IndirectValue(args[0], errorInfo) + ".real;"
case "imag":
return register + "" + l.IndirectValue(args[0], errorInfo) + ".imag;"
case "complex":
return register + "new Complex(" + l.IndirectValue(args[0], errorInfo) + "," + l.IndirectValue(args[1], errorInfo) + ");"
default:
pogo.LogError(errorInfo, "Haxe", fmt.Errorf("haxe.Call() - Unhandled builtin function: %s", fnToCall))
ret = "MISSING_BUILTIN("
}
} else {
switch fnToCall {
//
// pogo specific function rewriting
//
case "tardisgolib_HAXE": // insert raw haxe code into the ouput file!! BEWARE
nextReturnAddress-- //decrement to set new return address for next call generation
if register != "" {
register += "="
}
return register + strings.Trim(l.IndirectValue(args[0], errorInfo), `"`) // NOTE user must supply own ";" if required
case "tardisgolib_Host":
nextReturnAddress-- //decrement to set new return address for next call generation
return register + `="` + l.LanguageName() + `";`
case "tardisgolib_Platform":
nextReturnAddress-- //decrement to set new return address for next call generation
return register + `=Go.Platform();`
case "tardisgolib_CPos":
nextReturnAddress-- //decrement to set new return address for next call generation
return register + fmt.Sprintf("=Go.CPos(%d);", pogo.LatestValidPosHash)
case "tardisgolib_Zilen":
nextReturnAddress-- //decrement to set new return address for next call generation
return register + "='хнЧ'.length;"
//
// Go library complex function rewriting
//
case "math_Inf":
nextReturnAddress-- //decrement to set new return address for next call generation
return register + "=(" + l.IndirectValue(args[0], errorInfo) + ">=0?Math.POSITIVE_INFINITY:Math.NEGATIVE_INFINITY);"
default:
//.........这里部分代码省略.........