本文整理匯總了Golang中subc/compile/arch.LV類的典型用法代碼示例。如果您正苦於以下問題:Golang LV類的具體用法?Golang LV怎麽用?Golang LV使用的例子?那麽, 這裏精選的類代碼示例或許可以為您提供幫助。
在下文中一共展示了LV類的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: sizeofExpr
// sizeofExpr generates code for a sizeof(x) expression.
func (c *compiler) sizeofExpr(e *ast.SizeofExpr, lv *arch.LV, tv types.TypeAndValue) *node {
lv.Value = tv.Value
lv.Addressable = false
n := newNode(opLit, lv, nil, nil, nil)
return n
}
示例2: selectorExpr
// selectorExpr generates code for record accesses (a.x, a->x, etc)
func (c *compiler) selectorExpr(e *ast.SelectorExpr, lv *arch.LV) *node {
sel, found := c.Selections[e]
if !found {
c.errorf(e.Op.Pos, "no selection expression information found")
return nil
}
n := c.exprInternal(e.X, lv)
if sel.Indirect() {
n = c.rvalue(n, lv)
lv.Ident = false
}
lv.Addressable = true
if !sel.IsUnion() && sel.Offset() != 0 {
lv.Value = constant.MakeInt64(sel.Offset())
m := newNode(opLit, lv, nil, nil, nil)
n = newNode(opAdd, lv, nil, n, m)
}
if isArray(sel.Obj().Type()) {
lv.Addressable = false
}
lv.Type = sel.Type().Underlying()
return n
}
示例3: logical
// logical generates code for || and && operators.
func (c *compiler) logical(op scan.Type, e *ast.BinaryExpr, lv *arch.LV) *node {
l := []*ast.BinaryExpr{e}
for x := e.X; ; {
y, ok := x.(*ast.BinaryExpr)
if !ok || y.Op.Type != op {
break
}
l = append(l, y)
x = y.X
}
var lx arch.LV
n := c.exprInternal(l[len(l)-1].X, lv)
for i := len(l) - 1; i >= 0; i-- {
var lv2 arch.LV
if lx.Addr == 0 {
lx.Addr = c.cg.Label()
}
n = c.rvalue(n, lv)
n2 := c.exprInternal(l[i].Y, &lv2)
n2 = c.rvalue(n2, &lv2)
if op == scan.Lor {
n = newNode(opBrTrue, &lx, nil, n, n2)
} else {
n = newNode(opBrFalse, &lx, nil, n, n2)
}
}
n = newNode(opLab, &lx, nil, n, nil)
n = newNode(opBool, nil, nil, n, nil)
lv.Type = types.Typ[types.Int]
lv.Addressable = false
return n
}
示例4: indexExpr
// indexExpr generates code for array accesses (a[x], etc).
func (c *compiler) indexExpr(e *ast.IndexExpr, lv *arch.LV) *node {
var lv2 arch.LV
n := c.exprInternal(e.X, lv)
lv.Type = lv.Type.Underlying()
n = c.indirection(e, n, lv)
m := c.exprInternal(e.Index, &lv2)
m = c.rvalue(m, &lv2)
record, isRecord := lv.Type.(*types.Record)
if !isRecord && lv.Type != types.Typ[types.Char] {
// if it is not a record, we just need to scale
// it by the sizeof of the type
m = newNode(opScale, nil, nil, m, nil)
} else if isRecord {
// if it is a struct, we use sizeof to figure
// out the size to multiply by to get to the index
lv2.Size = c.cg.Sizeof(record)
m = newNode(opScaleBy, &lv2, nil, m, nil)
}
lv.Ident = false
lv.Addressable = true
return newNode(opAdd, lv, &lv2, n, m)
}
示例5: fold1
// fold1 folds constant unary expressions.
func (c *compiler) fold1(n *node) *node {
var lv arch.LV
switch n.op {
case opScale:
v, _ := strconv.Atoi(n.left.lv[0].Value.String())
lv.Value = constant.MakeInt64(int64(v * c.cg.Int()))
default:
return n
}
return newNode(opLit, &lv, nil, nil, nil)
}
示例6: reduce
// reduce transforms expressions into equivalent but faster expressions.
func (c *compiler) reduce(n *node) *node {
var vl, vr int
var lv arch.LV
op := n.op
cl := n.left.op == opLit
cr := n.right.op == opLit
if cl {
vl, _ = strconv.Atoi(n.left.lv[0].Value.String())
}
if cr {
vr, _ = strconv.Atoi(n.right.lv[0].Value.String())
}
switch {
case (op == opPlus || op == opAdd) && cr && vr == 0: // x+0 -> x
return n.left
case (op == opPlus || op == opAdd) && cl && vl == 0: // 0+x -> x
return n.right
case op == opSub && cr && vr == 0: // x-0 -> x
return n.left
case op == opSub && cl && vl == 0: // 0-x -> -x
return newNode(opNeg, nil, nil, n.right, nil)
case op == opMul && ((cl && vl == 0) || (cr && vr == 0)): // 0*x -> 0 || x*0 -> 0
lv.Value = constant.MakeInt64(0)
return newNode(opLit, &lv, nil, nil, nil)
case op == opMul || op == opDiv: // reduce x*(2^n) or x/(2^n) to x<<n or x>>n
lim := c.cg.Int()*8 - 1
for i, k := 0, 1; i < lim; i, k = i+1, k<<1 {
lv.Value = constant.MakeInt64(int64(i))
m := newNode(opLit, &lv, nil, nil, nil)
if cr && k == vr {
if op == opMul {
return newNode(opLsh, nil, nil, n.left, m)
} else {
return newNode(opRsh, nil, nil, n.left, m)
}
} else if cl && k == vl && op == opMul {
return newNode(opLsh, nil, nil, n.right, m)
}
}
}
return n
}
示例7: unaryExpr
// unaryExpr generates code unary operators (+a, -a, ~a, !a, etc).
func (c *compiler) unaryExpr(e *ast.UnaryExpr, lv *arch.LV) *node {
pos := e.Span().Start
n := c.exprInternal(e.X, lv)
var x opcode
switch op := e.Op.Type; op {
case scan.Inc, scan.Dec:
switch {
case op == scan.Inc && e.Affix == ast.Prefix:
x = opPreInc
case op == scan.Inc && e.Affix == ast.Postfix:
x = opPostInc
case op == scan.Dec && e.Affix == ast.Prefix:
x = opPreDec
case op == scan.Dec && e.Affix == ast.Postfix:
x = opPostDec
}
n = newNode(x, lv, nil, n, nil)
lv.Addressable = false
case scan.Plus:
n = c.rvalue(n, lv)
lv.Addressable = false
case scan.Minus, scan.Negate, scan.Not:
switch op {
case scan.Minus:
x = opNeg
case scan.Negate:
x = opNot
case scan.Not:
x = opLogNot
}
n = c.rvalue(n, lv)
n = newNode(x, lv, nil, n, nil)
lv.Addressable = false
case scan.And:
if lv.Addressable && lv.Ident {
n = newNode(opAddr, lv, nil, n, nil)
}
lv.Addressable = false
default:
c.errorf(pos, "invalid unary expression %v", op)
}
return n
}
示例8: rvalue
// rvalue generates code for loading a value of the variable if it addressable.
func (*compiler) rvalue(n *node, lv *arch.LV) *node {
if lv.Addressable {
n = newNode(opRval, lv, nil, n, nil)
lv.Addressable = false
}
return n
}
示例9: binaryExpr
// binaryExpr generates code for binary operators.
func (c *compiler) binaryExpr(e *ast.BinaryExpr, lv *arch.LV) *node {
op := e.Op.Type
if op == scan.Land || op == scan.Lor {
return c.logical(op, e, lv)
}
var lv2 arch.LV
n := c.exprInternal(e.X, lv)
m := c.rvalue(c.exprInternal(e.Y, &lv2), &lv2)
bop := binOp(op)
aop := arithOp(op)
switch {
// regular binary operators (+, -, *, /, etc)
case bop != 0:
tv, found := c.typAndValue(e)
if !found {
return nil
}
n = c.rvalue(n, lv)
lv.Btype = tv.Type
return newNode(bop, lv, &lv2, n, m)
// binary assignment operator such as (+=, -=, *=, /=, etc)
case aop != 0:
lvs := *lv
src := c.rvalue(n, &lvs)
m = newNode(aop, lv, &lv2, src, m)
n = newNode(opAssign, lv, &lv2, n, m)
lv.Addressable = false
// assignment operator (=)
case op == scan.Assign:
n = newNode(opAssign, lv, &lv2, n, m)
lv.Addressable = false
// comma operator (,)
case op == scan.Comma:
n = c.rvalue(n, lv)
n = newNode(opComma, &lv2, nil, n, m)
default:
c.errorf(e.Span().Start, "unknown binary op: %s\n", e.Op.Text)
}
return n
}
示例10: indirection
// indirection dereferences a pointer and generate code to load it.
func (c *compiler) indirection(e ast.Expr, n *node, lv *arch.LV) *node {
pos := e.Span().Start
n = c.rvalue(n, lv)
ptr, ok := lv.Type.(*types.Pointer)
if !ok {
c.errorf(pos, "indirection through non pointer")
return nil
} else if isVoidPointer(lv.Type) {
c.errorf(pos, "dereferencing void pointer")
return nil
}
lv.Ident = false
lv.Type = ptr.Elem().Underlying()
return n
}
示例11: callExpr
// call expression generates code for calling functions (f(x), fact(1), etc).
func (c *compiler) callExpr(e *ast.CallExpr, lv *arch.LV) *node {
c.exprInternal(e.Fun, lv)
n := c.fnArgs(e.Args)
if sig, ok := lv.Type.(*types.Signature); ok {
lv.Size = len(e.Args)
lv.Type = sig.Result().Type().Underlying()
if !lv.Addressable {
// regular function calls
n = newNode(opCall, lv, nil, n, nil)
} else {
// function pointer calls
n = newNode(opCalr, lv, nil, n, nil)
}
}
lv.Addressable = false
return n
}
示例12: condExpr
// condExpr generates code for ? and : operators.
func (c *compiler) condExpr(e *ast.CondExpr, lv *arch.LV) *node {
l := []*ast.CondExpr{e}
for x := e.Cond; ; {
y, ok := x.(*ast.CondExpr)
if !ok {
break
}
l = append(l, y)
x = y.Cond
}
var lx arch.LV
var l2 int
var typ types.Type
n := c.exprInternal(l[len(l)-1].Cond, lv)
for i := len(l) - 1; i >= 0; i-- {
var lv2 arch.LV
n = c.rvalue(n, lv)
l1 := c.cg.Label()
if l2 == 0 {
l2 = c.cg.Label()
}
n2 := c.exprInternal(l[i].X, &lv2)
n2 = c.rvalue(n2, &lv2)
lx.Addr = l1
n = newNode(opBrFalse, &lx, nil, n, n2)
if typ == nil {
typ = lv2.Type
}
n2 = c.exprInternal(l[i].Y, &lv2)
n2 = c.rvalue(n2, &lv2)
n = newNode(opGlue, nil, nil, n, n2)
}
lx.Addr = l2
n = newNode(opIfElse, &lx, nil, n, nil)
lv.Type = typ
lv.Addressable = false
return n
}
示例13: defineLocal
// defineLocal defines a variable at a function scope.
func (c *compiler) defineLocal(v *types.Var, lv *arch.LV) {
val := c.cg.Label()
lv.Addr = val
c.cg.Data()
intSize := c.cg.Int()
ptrSize := c.cg.Pointer()
size := 1
typ := v.Type().Underlying()
prim := primType(typ)
array, isArray := typ.(*types.Array)
isRecord := isRecord(typ, true)
if isArray {
size = int(array.Len())
}
init := 0
if x := v.Value(); x != nil {
init, _ = strconv.Atoi(x.String())
}
if !isArray && !isRecord {
c.cg.Lab(val)
}
switch {
case isRecord:
c.cg.BSS(c.cg.Labname(val), c.cg.Sizeof(typ), true)
case prim == types.Typ[types.Char]:
if isArray {
c.cg.BSS(c.cg.Labname(val), size, true)
} else {
c.cg.Defb(init)
c.cg.Align(1, intSize)
}
case prim == types.Typ[types.Int]:
if isArray {
c.cg.BSS(c.cg.Labname(val), size*intSize, true)
} else {
c.cg.Defw(init)
}
default:
if isArray {
c.cg.BSS(c.cg.Labname(val), size*ptrSize, true)
} else {
c.cg.Defp(init)
}
}
}
示例14: starExpr
// starExpr generates code for a dereference expression (*a, etc).
func (c *compiler) starExpr(e *ast.StarExpr, lv *arch.LV) *node {
n := c.exprInternal(e.X, lv)
n = c.indirection(e, n, lv)
lv.Addressable = true
return n
}
示例15: ident
// ident generates code for an identifier by loading it into the accumulator.
func (c *compiler) ident(e *ast.Ident, lv *arch.LV, tv types.TypeAndValue) *node {
lv.Ident = true
lv.Type = tv.Type.Underlying()
lv.Name = e.Name
_, isFunc := tv.Type.(*types.Signature)
if isFunc {
if x, ok := c.Uses[e]; ok {
switch x := x.(type) {
case *types.Func:
lv.Storage = x.Storage()
return newNode(opAddr, lv, nil, nil, nil)
case *types.Fwrd:
return newNode(opAddr, lv, nil, nil, nil)
}
}
}
v, found := c.variable(e, c.Uses)
if !found {
lv.Ident = false
return nil
}
s, found := c.symbol(v)
if !found {
lv.Ident = false
return nil
}
_, isRecord := lv.Type.(*types.Record)
// arrays decay to pointers, so we need to get the original type
// because the type and value by the typechecker is recorded as a pointer
array, isArray := v.Type().(*types.Array)
lv.Addr = s.Addr
lv.Value = s.Value
lv.Storage = v.Storage()
switch {
// constants
case tv.Value != nil:
lv.Value = tv.Value
return newNode(opLit, lv, nil, nil, nil)
case isArray:
lv.Type = types.NewPointer(array.Elem(), nil)
return newNode(opAddr, lv, nil, nil, nil)
case isRecord:
lv.Ident = false
return newNode(opAddr, lv, nil, nil, nil)
// variable that a integer or a pointer
default:
lv.Addressable = true
return newNode(opIdent, lv, nil, nil, nil)
}
}