本文整理汇总了Golang中rsc/io/c2go/cc.Expr类的典型用法代码示例。如果您正苦于以下问题:Golang Expr类的具体用法?Golang Expr怎么用?Golang Expr使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了Expr类的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: checkNoSideEffects
func checkNoSideEffects(x *cc.Expr, mode int) {
var before, after []*cc.Stmt
old := x.String()
doSideEffects(x, &before, &after, mode)
if len(before)+len(after) > 0 {
fprintf(x.Span, "cannot handle side effects in %s", old)
}
}
示例2: fixMerge
func fixMerge(dst, src *cc.Expr) {
syn := dst.SyntaxInfo
syn.Comments.Before = append(syn.Comments.Before, src.Comments.Before...)
syn.Comments.After = append(syn.Comments.After, src.Comments.After...)
syn.Comments.Suffix = append(syn.Comments.Suffix, src.Comments.Suffix...)
*dst = *src
dst.SyntaxInfo = syn
}
示例3: matchSize
func matchSize(fn *cc.Decl, obj *cc.Expr, objType *cc.Type, siz *cc.Expr) bool {
switch siz.Op {
default:
return false
case cc.SizeofType:
// ok if sizeof type of first arg
return sameType(siz.Type, objType)
case cc.SizeofExpr:
// ok if sizeof *firstarg
y := siz.Left
if y.Op == cc.Paren {
y = y.Left
}
return obj.String() == y.String()
}
}
示例4: tryPrintf
func tryPrintf(curfn *cc.Decl, x *cc.Expr, name string, fmtpos int, newName string) bool {
if (x.Left.Text == name || (strings.Contains(name, ".") || strings.Contains(name, "->")) && x.Left.String() == name) && len(x.List) >= fmtpos+1 && x.List[fmtpos].Op == cc.String {
x.List = append(x.List[:fmtpos+1], fixPrintFormat(curfn, x.List[fmtpos], x.List[fmtpos+1:])...)
if newName != "" {
x.Left.Text = newName
x.Left.XDecl = nil
}
return true
}
return false
}
示例5: fixSpecialCall
func fixSpecialCall(fn *cc.Decl, x *cc.Expr, targ *cc.Type) bool {
if x.Left.Op != cc.Name {
return false
}
switch x.Left.Text {
case "memmove":
if len(x.List) != 3 {
// fprintf(x.Span, "unsupported %v", x)
return false
}
siz := x.List[2]
if siz.Op == cc.Number && siz.Text == "4" {
obj1, obj1Type := objIndir(fn, x.List[0])
obj2, obj2Type := objIndir(fn, x.List[1])
if obj1Type == nil || obj2Type == nil {
// fprintf(x.Span, "unsupported %v - missing types", x)
return true
}
if (obj1Type.Kind == Uint32 || obj1Type.Kind == Int32) && obj2Type.Kind == Float32 {
x.Op = cc.Eq
x.Left = obj1
x.Right = &cc.Expr{
Op: cc.Call,
Left: &cc.Expr{Op: cc.Name,
Text: "math.Float32bits",
},
List: []*cc.Expr{obj2},
}
x.XType = uint32Type
return true
}
// fprintf(x.Span, "unsupported %v - size 4 type %v %v", x, GoString(obj1Type), GoString(obj2Type))
}
if siz.Op == cc.Number && siz.Text == "8" {
obj1, obj1Type := objIndir(fn, x.List[0])
obj2, obj2Type := objIndir(fn, x.List[1])
if obj1Type == nil || obj2Type == nil {
// fprintf(x.Span, "unsupported %v - missing types", x)
return true
}
if (obj1Type.Kind == Uint64 || obj1Type.Kind == Int64) && obj2Type.Kind == Float64 {
x.Op = cc.Eq
x.Left = obj1
x.Right = &cc.Expr{
Op: cc.Call,
Left: &cc.Expr{Op: cc.Name,
Text: "math.Float64bits",
},
List: []*cc.Expr{obj2},
}
x.XType = uint64Type
return true
}
// fprintf(x.Span, "unsupported %v - size 8 type %v %v", x, GoString(obj1Type), GoString(obj2Type))
}
if siz.Op == cc.SizeofExpr {
obj1Type := fixGoTypesExpr(fn, x.List[0], nil)
obj2Type := fixGoTypesExpr(fn, x.List[1], nil)
sizeType := fixGoTypesExpr(fn, siz.Left, nil)
if obj1Type == nil || obj2Type == nil {
// fprintf(x.Span, "unsupported %v - bad types", x)
return true
}
if obj2Type.Kind == cc.Array && sameType(obj2Type, sizeType) || obj2Type.Kind == Slice && GoString(x.List[1]) == GoString(siz.Left) {
x.Left.Text = "copy"
x.Left.XDecl = nil
x.List = x.List[:2]
return true
}
// fprintf(x.Span, "unsupported %v - not array %v %v", x, GoString(obj2Type), GoString(sizeType))
return true
}
left := fixGoTypesExpr(fn, x.List[0], nil)
right := fixGoTypesExpr(fn, x.List[1], nil)
fixGoTypesExpr(fn, siz, nil)
if isSliceOrArray(left) && isSliceOrArray(right) && left.Base.Is(Uint8) && right.Base.Is(Uint8) {
x.Left.Text = "copy"
x.Left.XDecl = nil
if x.List[1].Op == ExprSlice && x.List[1].List[1] == nil {
x.List[1].List[2] = siz
} else {
x.List[1] = &cc.Expr{Op: ExprSlice, List: []*cc.Expr{x.List[1], nil, siz}}
}
x.List = x.List[:2]
return true
}
// fprintf(x.Span, "unsupported %v (%v %v)", x, GoString(left), GoString(right))
return true
case "mal", "malloc", "emallocz", "xmalloc":
if len(x.List) != 1 {
fprintf(x.Span, "unsupported %v - too many args", x)
return false
}
siz := x.List[0]
var count *cc.Expr
if siz.Op == cc.Mul {
count = siz.Left
siz = siz.Right
if count.Op == cc.SizeofType || count.Op == cc.SizeofExpr {
//.........这里部分代码省略.........
示例6: forceConvert
func forceConvert(fn *cc.Decl, x *cc.Expr, actual, targ *cc.Type) {
if isEmptyInterface(targ) {
return
}
if isEmptyInterface(actual) {
old := copyExpr(x)
x.Op = TypeAssert
x.Left = old
x.Right = nil
x.List = nil
x.Type = targ
x.XType = targ
return
}
if isNumericConst(x) && targ != nil {
switch targ.Kind {
case cc.Ptr, Slice:
if x.Op == cc.Number && x.Text == "0" {
x.Op = cc.Name
x.Text = "nil"
x.XType = targ
}
case String:
if x.Op == cc.Number && x.Text == "0" {
x.Op = cc.Name
x.Text = `""`
x.XType = targ
}
}
return
}
if x.Op == cc.Name && x.Text == "nil" && targ != nil {
switch targ.Kind {
case cc.Func, cc.Ptr, Slice:
return
case String:
x.Text = `""`
x.XType = targ
x.XDecl = nil
return
}
}
if actual == nil || targ == nil {
return
}
if actual.Kind == Ideal && Int8 <= targ.Kind && targ.Kind <= Float64 {
return
}
if x != nil && x.Op == cc.Name && x.Text == "nil" {
if targ.Kind == cc.Func || targ.Kind == cc.Ptr || targ.Kind == Slice {
return
}
}
// Func conversions are never useful.
// If the func types are different, the conversion will fail;
// if not, the conversion is unnecessary.
// Either way the conversion is an eyesore.
if targ.Kind == cc.Func || targ.Kind == cc.Ptr && targ.Base.Kind == cc.Func {
return
}
if actual.Kind == Bool && Int8 <= targ.Kind && targ.Kind <= Float64 {
old := copyExpr(x)
if targ.Kind == Int {
x.Op = cc.Call
x.Left = &cc.Expr{Op: cc.Name, Text: "bool2int"}
x.List = []*cc.Expr{old}
x.Right = nil
} else {
x.Op = cc.Cast
x.Left = &cc.Expr{Op: cc.Call, Left: &cc.Expr{Op: cc.Name, Text: "bool2int"}, List: []*cc.Expr{old}}
x.Type = targ
}
return
}
if actual.Kind == cc.Array && targ.Kind == Slice && sameType(actual.Base, targ.Base) {
old := copyExpr(x)
x.Op = ExprSlice
x.List = []*cc.Expr{old, nil, nil}
x.Left = nil
x.Right = nil
return
}
if actual.Kind == Slice && targ.Kind == cc.Ptr && sameType(actual.Base, targ.Base) {
if isCall(x, "make") {
return
}
old := copyExpr(x)
x.Op = cc.Addr
x.Left = &cc.Expr{Op: cc.Index, Left: old, Right: &cc.Expr{Op: cc.Number, Text: "0"}}
return
}
//.........这里部分代码省略.........
示例7: fixGoTypesExpr
func fixGoTypesExpr(fn *cc.Decl, x *cc.Expr, targ *cc.Type) (ret *cc.Type) {
if x == nil {
return nil
}
defer func() {
x.XType = ret
}()
if x.Op == cc.Paren {
return fixGoTypesExpr(fn, x.Left, targ)
}
// Make explicit C's implicit conversions from boolean to non-boolean and vice versa.
switch x.Op {
case cc.AndAnd, cc.OrOr, cc.Not, cc.EqEq, cc.Lt, cc.LtEq, cc.Gt, cc.GtEq, cc.NotEq:
if targ != nil && targ.Kind != Bool {
old := copyExpr(x)
if targ.Kind == Int {
x.Op = cc.Call
x.Left = &cc.Expr{Op: cc.Name, Text: "bool2int"}
x.List = []*cc.Expr{old}
x.Right = nil
} else {
x.Op = cc.Cast
x.Left = &cc.Expr{Op: cc.Call, Left: &cc.Expr{Op: cc.Name, Text: "bool2int"}, List: []*cc.Expr{old}}
x.Type = targ
}
fixGoTypesExpr(fn, old, boolType)
return targ
}
default:
if targ != nil && targ.Kind == Bool {
old := copyExpr(x)
left := fixGoTypesExpr(fn, old, nil)
if left != nil && left.Kind == Bool {
return targ
}
if old.Op == cc.Number {
switch old.Text {
case "1":
x.Op = cc.Name
x.Text = "true"
return targ
case "0":
x.Op = cc.Name
x.Text = "false"
return targ
}
}
x.Op = cc.NotEq
x.Left = old
x.Right = zeroFor(left)
fixSpecialCompare(fn, x)
return targ
}
}
fixArray(fn, x)
switch x.Op {
default:
panic(fmt.Sprintf("unexpected construct %v in fixGoTypesExpr - %v - %v", GoString(x), x.Op, x.Span))
case ExprType:
// inserted by a rewrite
return nil
case ExprSlice:
// inserted by rewriteLen
left := fixGoTypesExpr(fn, x.List[0], targ)
fixGoTypesExpr(fn, x.List[1], nil)
fixGoTypesExpr(fn, x.List[2], nil)
return left
case cc.Comma:
for i, y := range x.List {
t := targ
if i+1 < len(x.List) {
t = nil
}
fixGoTypesExpr(fn, y, t)
}
return nil
case ExprBlock:
for _, stmt := range x.Block {
fixGoTypesStmt(nil, fn, stmt)
}
return nil
case cc.Add, cc.And, cc.Div, cc.Mod, cc.Mul, cc.Or, cc.Sub, cc.Xor:
if x.Op == cc.Sub && isPtrSliceOrArray(x.Left.XType) && isPtrSliceOrArray(x.Right.XType) {
left := fixGoTypesExpr(fn, x.Left, nil)
right := fixGoTypesExpr(fn, x.Right, nil)
if left != nil && right != nil && left.Kind != right.Kind {
if left.Kind == Slice {
forceConvert(fn, x.Right, right, left)
} else {
forceConvert(fn, x.Left, left, right)
//.........这里部分代码省略.........
示例8: negate
func negate(x *cc.Expr) *cc.Expr {
switch x.Op {
case cc.Paren:
return negate(x.Left)
case cc.OrOr:
x.Op = cc.AndAnd
x.Left = negate(x.Left)
x.Right = negate(x.Right)
case cc.AndAnd:
x.Op = cc.OrOr
x.Left = negate(x.Left)
x.Right = negate(x.Right)
case cc.EqEq:
x.Op = cc.NotEq
case cc.NotEq:
x.Op = cc.EqEq
case cc.Lt:
x.Op = cc.GtEq
case cc.GtEq:
x.Op = cc.Lt
case cc.Gt:
x.Op = cc.LtEq
case cc.LtEq:
x.Op = cc.Gt
default:
x = &cc.Expr{Op: cc.Not, Left: x}
}
return x
}
示例9: fixSpecialCompare
func fixSpecialCompare(fn *cc.Decl, x *cc.Expr) bool {
if (x.Right.Op != cc.Number || x.Right.Text != "0") && x.Right.String() != "nil" && x.Right.String() != `""` || x.Left.Op != cc.Call || x.Left.Left.Op != cc.Name {
return false
}
call := x.Left
switch call.Left.Text {
case "memcmp":
if len(call.List) != 3 {
// fprintf(x.Span, "unsupported %v", x)
return false
}
obj1, obj1Type := objIndir(fn, call.List[0])
obj2, obj2Type := objIndir(fn, call.List[1])
if obj1Type == nil || !sameType(obj1Type, obj2Type) {
// fprintf(x.Span, "unsupported %v", call)
return true
}
if !matchSize(fn, obj1, obj1Type, call.List[2]) && !matchSize(fn, obj2, obj2Type, call.List[2]) {
// fprintf(x.Span, "unsupported %v - wrong size", call)
return true
}
x.Left = obj1
x.Right = obj2
x.List = nil
x.XType = boolType
return true
case "strncmp":
if len(call.List) != 3 {
fprintf(x.Span, "unsupported %v", x)
return false
}
call.Left = &cc.Expr{Op: cc.Name, Text: "strings.HasPrefix"}
call.List = call.List[:2]
call.XType = boolType
if x.Op == cc.EqEq {
*x = *call
} else if x.Op == cc.NotEq {
x.Op = cc.Not
x.Right = nil
}
x.XType = boolType
return true
case "strstr":
if len(call.List) != 2 {
fprintf(x.Span, "unsupported %v", x)
return false
}
call.Left = &cc.Expr{Op: cc.Name, Text: "strings.Contains"}
call.XType = boolType
if x.Op == cc.NotEq {
*x = *call
} else if x.Op == cc.EqEq {
x.Op = cc.Not
x.Right = nil
}
x.XType = boolType
return true
case "utfrune":
if len(call.List) != 2 {
fprintf(x.Span, "unsupported %v", x)
return false
}
call.Left = &cc.Expr{Op: cc.Name, Text: "strings.ContainsRune"}
call.XType = boolType
if x.Op == cc.NotEq {
*x = *call
} else if x.Op == cc.EqEq {
x.Op = cc.Not
x.Right = nil
}
x.XType = boolType
return true
case "ucistrcmp":
if len(call.List) != 2 {
fprintf(x.Span, "unsupported %v", x)
return false
}
call.Left = &cc.Expr{Op: cc.Name, Text: "strings.EqualFold"}
call.XType = boolType
if x.Op == cc.EqEq {
*x = *call
} else if x.Op == cc.NotEq {
x.Op = cc.Not
x.Right = nil
}
x.XType = boolType
return true
case "strcmp":
if len(call.List) != 2 {
fprintf(x.Span, "unsupported %v", x)
return false
}
//.........这里部分代码省略.........
示例10: fixArray
// fixArrays rewrites uses of the untyped "Array" container defined in cmd/gc
// to use native Go slices.
// It has nothing to do with standard C arrays.
func fixArray(fn *cc.Decl, x *cc.Expr) {
// arraynew(n, sizeof(T)) becomes Go make([]T, 0, n).
if isCall(x, "arraynew") {
if len(x.List) != 2 {
fprintf(x.Span, "wrong number of arguments to arraynew")
return
}
if x.List[1].Op != cc.SizeofType {
fprintf(x.Span, "second argument to arraynew must be sizeof(T)")
return
}
x.Left.Text = "make"
x.Left.XDecl = nil
typ := &cc.Type{Kind: Slice, Base: x.List[1].Type}
x.XType = typ
x.List = append(x.List, x.List[0])
x.List[1] = &cc.Expr{Op: cc.Number, Text: "0"}
x.List[0] = &cc.Expr{Op: ExprType, Type: typ}
return
}
// arraylength(x) becomes len(x)
if isCall(x, "arraylength") {
x.Left.Text = "len"
x.Left.XDecl = nil
return
}
// arrayset is unused in practice!
// arrayadd(x, &elem) becomes x = append(x, elem).
// Strictly speaking, this is not a complete translation,
// because in the C code x might be a pointer taken from
// another place, and arrayadd changes the len at that
// other place too. In cmd/gc this does not happen.
if isCall(x, "arrayadd") {
if len(x.List) != 2 {
fprintf(x.Span, "wrong number of arguments to arrayadd")
return
}
if x.List[1].Op != cc.Addr {
fprintf(x.Span, "second argument to arrayadd must be &x, have %v", x.List[1])
return
}
append := copyExpr(x)
append.Left.Text = "append"
append.Left.XDecl = nil
x.Op = cc.Eq
x.Left = append.List[0]
x.Right = append
append.List[1] = append.List[1].Left
return
}
// *(T**)(arrayget(x, i)) turns into x[i].
// Record that x should have translated type T*.
if x.Op == cc.Indir && x.Left.Op == cc.Cast && x.Left.Type.Kind == cc.Ptr && x.Left.Type.Base.Kind == cc.Ptr && isCall(x.Left.Left, "arrayget") {
call := x.Left.Left
x.Op = cc.Index
x.XType = x.Left.Type.Base
x.Left = call.List[0]
x.Right = call.List[1]
saveSliceType(x.Left, x.XType)
return
}
// TODO: arraysort
}
示例11: fixQsortCmp
func fixQsortCmp(decl *cc.Decl) (*cc.Type, *cc.Decl) {
ftyp := decl.Type
if ftyp.Kind != cc.Func || len(ftyp.Decls) != 2 || !isEmptyInterface(ftyp.Decls[0].Type) || !isEmptyInterface(ftyp.Decls[1].Type) {
fprintf(decl.Span, "invalid qsort cmp function %v - wrong args", GoString(ftyp))
return nil, nil
}
a1, a2 := ftyp.Decls[0], ftyp.Decls[1]
var eq1, eq2, p1, p2 *cc.Expr
var indir1, indir2 bool
cc.Preorder(decl.Body, func(x cc.Syntax) {
switch x := x.(type) {
case *cc.Expr:
if x.Op != cc.Eq {
return
}
r := x.Right
if r.Op == cc.Indir {
r = r.Left
}
if (r.Op == TypeAssert || r.Op == cc.Cast) && r.Left.Op == cc.Name {
if r.Left.XDecl == a1 && p1 == nil {
p1 = x.Left
eq1 = x
indir1 = r != x.Right
}
if r.Left.XDecl == a2 && p2 == nil {
p2 = x.Left
eq2 = x
indir2 = r != x.Right
}
}
}
})
if p1 == nil || p2 == nil {
fprintf(decl.Span, "invalid qsort cmp function - cannot find arg extraction")
return nil, nil
}
if !sameType(p1.XType, p2.XType) {
fprintf(decl.Span, "invalid qsort cmp function - different arg types %v and %v", GoString(p1.XType), GoString(p2.XType))
return nil, nil
}
if indir1 != indir2 {
fprintf(decl.Span, "invalid qsort cmp function - different arg indirection")
return nil, nil
}
typ := p1.XType
if !indir1 {
if typ.Def().Kind != cc.Ptr {
fprintf(decl.Span, "invalid qsort cmp function - arg ptr cast to non-ptr %v", GoString(typ))
return nil, nil
}
typ = typ.Def().Base
}
// Have all the information. Committed.
// Rewrite to take x, i, j, use x[i] for p1, x[j] for p2,
// take address of x[i], x[j] if there was no indirect,
// replace all return z with return z < 0.
newDecl := *decl
decl.Body = nil
decl = &newDecl
cmp := decl.Name
decl.Name = "(x " + cmp + ") Less"
decl.Type = &cc.Type{
Kind: cc.Func,
Base: boolType,
Decls: []*cc.Decl{
{Name: "i", Type: &cc.Type{Kind: cc.TypedefType}},
{Name: "j", Type: intType},
},
}
prefix := ""
if !indir1 {
prefix = "&"
}
eq1.Right = &cc.Expr{Op: cc.Name, Text: prefix + "x[i]", XType: p1.XType}
eq2.Right = &cc.Expr{Op: cc.Name, Text: prefix + "x[j]", XType: p1.XType}
cc.Preorder(decl.Body, func(x cc.Syntax) {
switch x := x.(type) {
case *cc.Stmt:
if x.Op == cc.Return && x.Expr != nil {
ret := x.Expr
// Pick off 0, -1, +1.
// Otherwise rewrite ret to ret < 0.
switch ret.Op {
case cc.Minus, cc.Plus:
if ret.Left.Op == cc.Number && ret.Left.Text == "1" {
if ret.Op == cc.Plus {
ret.Text = "false"
} else {
ret.Text = "true"
}
ret.Op = cc.Name
//.........这里部分代码省略.........
示例12: fixQsort
func fixQsort(prog *cc.Prog, x *cc.Expr) {
if len(x.List) != 4 {
fprintf(x.Span, "unsupported %v - wrong arg count", x)
return
}
if x.List[2].Op != cc.SizeofExpr || unparen(x.List[2].Left).String() != unparen(x.List[0]).String()+"[0]" {
fprintf(x.Span, "unsupported %v - wrong elem size %v vs %v", x, unparen(x.List[2].Left).String(), unparen(x.List[0]).String()+"[0]")
return
}
if x.List[3].Op != cc.Name || x.List[3].XDecl == nil {
fprintf(x.Span, "unsupported %v - unknown comparison function", x)
return
}
cmp := x.List[3].XDecl.Name
decl := x.List[3].XDecl
typ, newDecl := fixQsortCmp(decl)
if typ == nil {
return
}
x.Left.Text = "sort.Sort"
x.Left.XDecl = nil
x.List = []*cc.Expr{
&cc.Expr{
Op: cc.Call,
Left: &cc.Expr{Op: cc.Name, Text: cmp},
List: []*cc.Expr{
{
Op: ExprSlice,
List: []*cc.Expr{
x.List[0],
nil,
x.List[1],
},
},
},
},
}
typeDecl := &cc.Decl{
GoPackage: decl.GoPackage,
SyntaxInfo: cc.SyntaxInfo{Span: decl.Span},
Name: cmp,
Storage: cc.Typedef,
Type: &cc.Type{
Kind: Slice,
Base: typ,
},
}
lenFunc := &cc.Decl{
GoPackage: decl.GoPackage,
SyntaxInfo: cc.SyntaxInfo{Span: decl.Span},
Name: "(x " + cmp + ") Len",
Type: &cc.Type{
Kind: cc.Func,
Base: intType,
},
Body: &cc.Stmt{
Op: cc.Block,
Block: []*cc.Stmt{
{
Op: cc.Return,
Expr: &cc.Expr{
Op: cc.Name,
Text: "len(x)",
},
},
},
},
}
swapFunc := &cc.Decl{
GoPackage: decl.GoPackage,
SyntaxInfo: cc.SyntaxInfo{Span: decl.Span},
Name: "(x " + cmp + ") Swap",
Type: &cc.Type{
Kind: cc.Func,
Base: &cc.Type{Kind: cc.Void},
Decls: []*cc.Decl{
{Name: "i", Type: &cc.Type{Kind: cc.TypedefType}},
{Name: "j", Type: intType},
},
},
Body: &cc.Stmt{
Op: cc.Block,
Block: []*cc.Stmt{
{
Op: cc.StmtExpr,
Expr: &cc.Expr{
Op: cc.Name,
Text: "x[i], x[j] = x[j], x[i]",
},
},
},
},
}
for i, d := range prog.Decls {
//.........这里部分代码省略.........
示例13: fixPrintf
func fixPrintf(curfn *cc.Decl, x *cc.Expr) bool {
if x.Op != cc.Call {
return false
}
if tryPrintf(curfn, x, "sprint", 1, "fmt.Sprintf") {
targ := x.List[0]
x.List = x.List[1:]
x.Right = copyExpr(x)
x.List = nil
x.Left = targ
x.Op = cc.Eq
// sprint(strchr(s, 0), "hello") => s += "hello"
if targ.Op == cc.Call && len(targ.List) == 2 && targ.Left.Text == "strchr" && targ.List[1].Text == "0" {
x.Left = targ.List[0]
x.Op = cc.AddEq
} else if targ.Op == cc.Add && targ.Right.Op == cc.Call && targ.Right.Left.Text == "strlen" && len(targ.Right.List) == 1 && GoString(targ.Left) == GoString(targ.Right.List[0]) {
x.Left = targ.Left
x.Op = cc.AddEq
}
return true
}
if tryPrintf(curfn, x, "snprint", 2, "fmt.Sprintf") {
targ := x.List[0]
x.List = x.List[2:]
x.Right = copyExpr(x)
x.List = nil
x.Left = targ
x.Op = cc.Eq
return true
}
if tryPrintf(curfn, x, "fmtprint", 1, "fmt.Sprintf") {
targ := x.List[0]
x.List = x.List[1:]
x.Right = copyExpr(x)
x.List = nil
x.Left = targ
x.Op = cc.AddEq
if x.Left.Op == cc.Addr {
x.Left = x.Left.Left
}
return true
}
if tryPrintf(curfn, x, "smprint", 0, "fmt.Sprintf") {
x.XType = stringType
return true
}
if tryPrintf(curfn, x, "print", 0, "fmt.Printf") {
return true
}
if tryPrintf(curfn, x, "fprint", 1, "fmt.Fprintf") {
if x.List[0].String() == "2" {
x.List[0] = &cc.Expr{Op: cc.Name, Text: "os.Stderr"}
}
return true
}
if tryPrintf(curfn, x, "sysfatal", 0, "log.Fatalf") {
return true
}
if tryPrintf(curfn, x, "fatal", 0, "") {
return true
}
if tryPrintf(curfn, x, "ctxt->diag", 0, "") {
return true
}
if tryPrintf(curfn, x, "diag", 0, "") {
return true
}
if tryPrintf(curfn, x, "werrstr", 0, "") {
return true
}
if tryPrintf(curfn, x, "yyerror", 0, "") {
return true
}
if tryPrintf(curfn, x, "yyerrorl", 1, "") {
forceConvert(curfn, x.List[0], x.List[0].XType, intType)
return true
}
if tryPrintf(curfn, x, "onearg", 1, "") {
return true
}
if tryPrintf(curfn, x, "warn", 0, "") {
return true
}
if tryPrintf(curfn, x, "warnl", 1, "") {
forceConvert(curfn, x.List[0], x.List[0].XType, intType)
return true
}
if tryPrintf(curfn, x, "Bprint", 1, "fmt.Fprintf") {
return true
}
if isCall(x, "exprfmt") && len(x.List) == 3 {
// exprfmt(fp, x, y) becomes fp += exprfmt(x, y)
x.Op = cc.AddEq
x.Right = &cc.Expr{Op: cc.Call, Left: x.Left, List: x.List[1:]}
x.Left = x.List[0]
x.List = nil
x.XType = stringType
return true
//.........这里部分代码省略.........
示例14: doSideEffects
func doSideEffects(x *cc.Expr, before, after *[]*cc.Stmt, mode int) {
if x == nil {
return
}
// Cannot hoist side effects from conditionally evaluated expressions
// into unconditionally evaluated statement lists.
// For now, detect but do not handle.
switch x.Op {
case cc.Cond:
doSideEffects(x.List[0], before, after, mode&^sideStmt|sideNoAfter)
checkNoSideEffects(x.List[1], 0)
checkNoSideEffects(x.List[2], 0)
case cc.AndAnd, cc.OrOr:
doSideEffects(x.Left, before, after, mode&^sideStmt|sideNoAfter)
checkNoSideEffects(x.Right, 0)
case cc.Comma:
var leftover []*cc.Expr
for i, y := range x.List {
m := mode | sideNoAfter
if i+1 < len(x.List) {
m |= sideStmt
}
doSideEffects(y, before, after, m)
switch y.Op {
case cc.PostInc, cc.PostDec, cc.Eq, cc.AddEq, cc.SubEq, cc.MulEq, cc.DivEq, cc.ModEq, cc.XorEq, cc.OrEq, cc.AndEq, cc.LshEq, cc.RshEq:
*before = append(*before, &cc.Stmt{Op: cc.StmtExpr, Expr: y})
default:
leftover = append(leftover, y)
}
}
x.List = leftover
default:
doSideEffects(x.Left, before, after, mode&^sideStmt)
doSideEffects(x.Right, before, after, mode&^sideStmt)
for _, y := range x.List {
doSideEffects(y, before, after, mode&^sideStmt)
}
}
if mode&sideStmt != 0 {
// Expression as statement.
// Can leave x++ alone, can rewrite ++x to x++, can leave x [op]= y alone.
switch x.Op {
case cc.PreInc:
x.Op = cc.PostInc
return
case cc.PreDec:
x.Op = cc.PostDec
return
case cc.PostInc, cc.PostDec:
return
case cc.Eq, cc.AddEq, cc.SubEq, cc.MulEq, cc.DivEq, cc.ModEq, cc.XorEq, cc.OrEq, cc.AndEq, cc.LshEq, cc.RshEq:
return
case cc.Call:
return
}
}
switch x.Op {
case cc.Eq, cc.AddEq, cc.SubEq, cc.MulEq, cc.DivEq, cc.ModEq, cc.XorEq, cc.OrEq, cc.AndEq, cc.LshEq, cc.RshEq:
x.Left = forceCheap(before, x.Left)
old := copyExpr(x)
*before = append(*before, &cc.Stmt{Op: cc.StmtExpr, Expr: old})
fixMerge(x, x.Left)
case cc.PreInc, cc.PreDec:
x.Left = forceCheap(before, x.Left)
old := copyExpr(x)
old.SyntaxInfo = cc.SyntaxInfo{}
if old.Op == cc.PreInc {
old.Op = cc.PostInc
} else {
old.Op = cc.PostDec
}
*before = append(*before, &cc.Stmt{Op: cc.StmtExpr, Expr: old})
fixMerge(x, x.Left)
case cc.PostInc, cc.PostDec:
x.Left = forceCheap(before, x.Left)
if mode&sideNoAfter != 0 {
// Not allowed to generate fixups afterward.
d := &cc.Decl{
Name: fmt.Sprintf("tmp%d", <-tmpGen),
Type: x.Left.XType,
}
eq := &cc.Expr{
Op: ColonEq,
Left: &cc.Expr{Op: cc.Name, Text: d.Name, XDecl: d},
Right: x.Left,
}
old := copyExpr(x.Left)
old.SyntaxInfo = cc.SyntaxInfo{}
*before = append(*before,
&cc.Stmt{Op: cc.StmtExpr, Expr: eq},
&cc.Stmt{Op: cc.StmtExpr, Expr: &cc.Expr{Op: x.Op, Left: old}},
)
//.........这里部分代码省略.........