// 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) }
// 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 }