本文整理匯總了Golang中cmd/internal/obj.Prog.From方法的典型用法代碼示例。如果您正苦於以下問題:Golang Prog.From方法的具體用法?Golang Prog.From怎麽用?Golang Prog.From使用的例子?那麽, 這裏精選的方法代碼示例或許可以為您提供幫助。您也可以進一步了解該方法所在類cmd/internal/obj.Prog
的用法示例。
在下文中一共展示了Prog.From方法的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: outgcode
func outgcode(a int, g1 *obj.Addr, reg int, g2, g3 *obj.Addr) {
var p *obj.Prog
var pl *obj.Plist
if asm.Pass == 1 {
goto out
}
p = asm.Ctxt.NewProg()
p.As = int16(a)
p.Lineno = stmtline
if nosched != 0 {
p.Mark |= ppc64.NOSCHED
}
p.From = *g1
p.Reg = int16(reg)
p.From3 = *g2
p.To = *g3
p.Pc = int64(asm.PC)
if lastpc == nil {
pl = obj.Linknewplist(asm.Ctxt)
pl.Firstpc = p
} else {
lastpc.Link = p
}
lastpc = p
out:
if a != obj.AGLOBL && a != obj.ADATA {
asm.PC++
}
}
示例2: outcode
func outcode(a int, g2 *Addr2) {
var p *obj.Prog
var pl *obj.Plist
if asm.Pass == 1 {
goto out
}
p = new(obj.Prog)
*p = obj.Prog{}
p.Ctxt = asm.Ctxt
p.As = int16(a)
p.Lineno = stmtline
p.From = g2.from
p.To = g2.to
p.Pc = int64(asm.PC)
if lastpc == nil {
pl = obj.Linknewplist(asm.Ctxt)
pl.Firstpc = p
} else {
lastpc.Link = p
}
lastpc = p
out:
if a != obj.AGLOBL && a != obj.ADATA {
asm.PC++
}
}
示例3: outcode
func outcode(a int, g1 *obj.Addr, reg int, g2 *obj.Addr) {
var p *obj.Prog
var pl *obj.Plist
if asm.Pass == 1 {
goto out
}
if g1.Scale != 0 {
if reg != 0 || g2.Scale != 0 {
yyerror("bad addressing modes")
}
reg = int(g1.Scale)
} else if g2.Scale != 0 {
if reg != 0 {
yyerror("bad addressing modes")
}
reg = int(g2.Scale)
}
p = asm.Ctxt.NewProg()
p.As = int16(a)
p.Lineno = stmtline
if nosched != 0 {
p.Mark |= ppc64.NOSCHED
}
p.From = *g1
p.Reg = int16(reg)
p.To = *g2
p.Pc = int64(asm.PC)
if lastpc == nil {
pl = obj.Linknewplist(asm.Ctxt)
pl.Firstpc = p
} else {
lastpc.Link = p
}
lastpc = p
out:
if a != obj.AGLOBL && a != obj.ADATA {
asm.PC++
}
}
示例4: constprop
/*
* The idea is to remove redundant constants.
* $c1->v1
* ($c1->v2 s/$c1/v1)*
* set v1 return
* The v1->v2 should be eliminated by copy propagation.
*/
func constprop(c1 *obj.Addr, v1 *obj.Addr, r *gc.Flow) {
if gc.Debug['P'] != 0 {
fmt.Printf("constprop %v->%v\n", gc.Ctxt.Dconv(c1), gc.Ctxt.Dconv(v1))
}
var p *obj.Prog
for ; r != nil; r = r.S1 {
p = r.Prog
if gc.Debug['P'] != 0 {
fmt.Printf("%v", p)
}
if gc.Uniqp(r) == nil {
if gc.Debug['P'] != 0 {
fmt.Printf("; merge; return\n")
}
return
}
if p.As == arm.AMOVW && copyas(&p.From, c1) {
if gc.Debug['P'] != 0 {
fmt.Printf("; sub%v/%v", gc.Ctxt.Dconv(&p.From), gc.Ctxt.Dconv(v1))
}
p.From = *v1
} else if copyu(p, v1, nil) > 1 {
if gc.Debug['P'] != 0 {
fmt.Printf("; %vset; return\n", gc.Ctxt.Dconv(v1))
}
return
}
if gc.Debug['P'] != 0 {
fmt.Printf("\n")
}
if r.S2 != nil {
constprop(c1, v1, r.S2)
}
}
}
示例5: copyu
// If s==nil, copyu returns the set/use of v in p; otherwise, it
// modifies p to replace reads of v with reads of s and returns 0 for
// success or non-zero for failure.
//
// If s==nil, copy returns one of the following values:
// _Read if v only used
// _ReadWriteSame if v is set and used in one address (read-alter-rewrite;
// can't substitute)
// _Write if v is only set
// _ReadWriteDiff if v is set in one address and used in another (so addresses
// can be rewritten independently)
// _None otherwise (not touched)
func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) usage {
if p.From3Type() != obj.TYPE_NONE && p.From3Type() != obj.TYPE_CONST {
// Currently we never generate a From3 with anything other than a constant in it.
fmt.Printf("copyu: From3 (%v) not implemented\n", gc.Ctxt.Dconv(p.From3))
}
switch p.As {
default:
fmt.Printf("copyu: can't find %v\n", p.As)
return _ReadWriteSame
case // read p.From, write p.To
s390x.AMOVH,
s390x.AMOVHZ,
s390x.AMOVB,
s390x.AMOVBZ,
s390x.AMOVW,
s390x.AMOVWZ,
s390x.AMOVD,
s390x.ANEG,
s390x.AADDME,
s390x.AADDZE,
s390x.ASUBME,
s390x.ASUBZE,
s390x.AFMOVS,
s390x.AFMOVD,
s390x.ALEDBR,
s390x.AFNEG,
s390x.ALDEBR,
s390x.ACLFEBR,
s390x.ACLGEBR,
s390x.ACLFDBR,
s390x.ACLGDBR,
s390x.ACFEBRA,
s390x.ACGEBRA,
s390x.ACFDBRA,
s390x.ACGDBRA,
s390x.ACELFBR,
s390x.ACELGBR,
s390x.ACDLFBR,
s390x.ACDLGBR,
s390x.ACEFBRA,
s390x.ACEGBRA,
s390x.ACDFBRA,
s390x.ACDGBRA,
s390x.AFSQRT:
if s != nil {
copysub(&p.From, v, s)
// Update only indirect uses of v in p.To
if !copyas(&p.To, v) {
copysub(&p.To, v, s)
}
return _None
}
if copyas(&p.To, v) {
// Fix up implicit from
if p.From.Type == obj.TYPE_NONE {
p.From = p.To
}
if copyau(&p.From, v) {
return _ReadWriteDiff
}
return _Write
}
if copyau(&p.From, v) {
return _Read
}
if copyau(&p.To, v) {
// p.To only indirectly uses v
return _Read
}
return _None
// read p.From, read p.Reg, write p.To
case s390x.AADD,
s390x.AADDC,
s390x.AADDE,
s390x.ASUB,
s390x.ASLW,
s390x.ASRW,
s390x.ASRAW,
s390x.ASLD,
s390x.ASRD,
//.........這裏部分代碼省略.........
示例6: peep
func peep(firstp *obj.Prog) {
g := (*gc.Graph)(gc.Flowstart(firstp, nil))
if g == nil {
return
}
gactive = 0
// byte, word arithmetic elimination.
elimshortmov(g)
// constant propagation
// find MOV $con,R followed by
// another MOV $con,R without
// setting R in the interim
var p *obj.Prog
for r := (*gc.Flow)(g.Start); r != nil; r = r.Link {
p = r.Prog
switch p.As {
case x86.ALEAL,
x86.ALEAQ:
if regtyp(&p.To) {
if p.From.Sym != nil {
if p.From.Index == x86.REG_NONE {
conprop(r)
}
}
}
case x86.AMOVB,
x86.AMOVW,
x86.AMOVL,
x86.AMOVQ,
x86.AMOVSS,
x86.AMOVSD:
if regtyp(&p.To) {
if p.From.Type == obj.TYPE_CONST || p.From.Type == obj.TYPE_FCONST {
conprop(r)
}
}
}
}
var r *gc.Flow
var r1 *gc.Flow
var p1 *obj.Prog
var t int
loop1:
if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 {
gc.Dumpit("loop1", g.Start, 0)
}
t = 0
for r = g.Start; r != nil; r = r.Link {
p = r.Prog
switch p.As {
case x86.AMOVL,
x86.AMOVQ,
x86.AMOVSS,
x86.AMOVSD:
if regtyp(&p.To) {
if regtyp(&p.From) {
if copyprop(g, r) {
excise(r)
t++
} else if subprop(r) && copyprop(g, r) {
excise(r)
t++
}
}
}
case x86.AMOVBLZX,
x86.AMOVWLZX,
x86.AMOVBLSX,
x86.AMOVWLSX:
if regtyp(&p.To) {
r1 = rnops(gc.Uniqs(r))
if r1 != nil {
p1 = r1.Prog
if p.As == p1.As && p.To.Type == p1.From.Type && p.To.Reg == p1.From.Reg {
p1.As = x86.AMOVL
t++
}
}
}
case x86.AMOVBQSX,
x86.AMOVBQZX,
x86.AMOVWQSX,
x86.AMOVWQZX,
x86.AMOVLQSX,
x86.AMOVLQZX,
x86.AMOVQL:
if regtyp(&p.To) {
r1 = rnops(gc.Uniqs(r))
if r1 != nil {
p1 = r1.Prog
if p.As == p1.As && p.To.Type == p1.From.Type && p.To.Reg == p1.From.Reg {
p1.As = x86.AMOVQ
t++
//.........這裏部分代碼省略.........
示例7: preprocess
func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
// TODO(minux): add morestack short-cuts with small fixed frame-size.
ctxt.Cursym = cursym
if cursym.Text == nil || cursym.Text.Link == nil {
return
}
p := cursym.Text
textstksiz := p.To.Offset
cursym.Args = p.To.Val.(int32)
cursym.Locals = int32(textstksiz)
/*
* find leaf subroutines
* strip NOPs
* expand RET
* expand BECOME pseudo
*/
if ctxt.Debugvlog != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f noops\n", obj.Cputime())
}
ctxt.Bso.Flush()
var q *obj.Prog
var q1 *obj.Prog
for p := cursym.Text; p != nil; p = p.Link {
switch p.As {
/* too hard, just leave alone */
case obj.ATEXT:
q = p
p.Mark |= LABEL | LEAF | SYNC
if p.Link != nil {
p.Link.Mark |= LABEL
}
case ANOR:
q = p
if p.To.Type == obj.TYPE_REG {
if p.To.Reg == REGZERO {
p.Mark |= LABEL | SYNC
}
}
case ASYNC,
AWORD:
q = p
p.Mark |= LABEL | SYNC
continue
case AMOVW, AMOVWZ, AMOVD:
q = p
if p.From.Reg >= REG_RESERVED || p.To.Reg >= REG_RESERVED {
p.Mark |= LABEL | SYNC
}
continue
case AFABS,
AFADD,
AFDIV,
AFMADD,
AFMOVD,
/* case AFMOVDS: */
AFMOVS,
/* case AFMOVSD: */
AFMSUB,
AFMUL,
AFNABS,
AFNEG,
AFNMADD,
AFNMSUB,
AFRSP,
AFSUB:
q = p
p.Mark |= FLOAT
continue
case ABL,
ABCL,
obj.ADUFFZERO,
obj.ADUFFCOPY:
cursym.Text.Mark &^= LEAF
fallthrough
case ABC,
ABEQ,
ABGE,
ABGT,
ABLE,
ABLT,
ABNE,
ABR,
ABVC,
ABVS,
ACMPBEQ,
ACMPBGE,
//.........這裏部分代碼省略.........
示例8: copyu
// If s==nil, copyu returns the set/use of v in p; otherwise, it
// modifies p to replace reads of v with reads of s and returns 0 for
// success or non-zero for failure.
//
// If s==nil, copy returns one of the following values:
// 1 if v only used
// 2 if v is set and used in one address (read-alter-rewrite;
// can't substitute)
// 3 if v is only set
// 4 if v is set in one address and used in another (so addresses
// can be rewritten independently)
// 0 otherwise (not touched)
func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
if p.From3Type() != obj.TYPE_NONE {
// never generates a from3
fmt.Printf("copyu: from3 (%v) not implemented\n", gc.Ctxt.Dconv(p.From3))
}
switch p.As {
default:
fmt.Printf("copyu: can't find %v\n", obj.Aconv(int(p.As)))
return 2
case obj.ANOP, /* read p->from, write p->to */
mips.AMOVV,
mips.AMOVF,
mips.AMOVD,
mips.AMOVH,
mips.AMOVHU,
mips.AMOVB,
mips.AMOVBU,
mips.AMOVW,
mips.AMOVWU,
mips.AMOVFD,
mips.AMOVDF,
mips.AMOVDW,
mips.AMOVWD,
mips.AMOVFW,
mips.AMOVWF,
mips.AMOVDV,
mips.AMOVVD,
mips.AMOVFV,
mips.AMOVVF,
mips.ATRUNCFV,
mips.ATRUNCDV,
mips.ATRUNCFW,
mips.ATRUNCDW:
if s != nil {
if copysub(&p.From, v, s, 1) != 0 {
return 1
}
// Update only indirect uses of v in p->to
if !copyas(&p.To, v) {
if copysub(&p.To, v, s, 1) != 0 {
return 1
}
}
return 0
}
if copyas(&p.To, v) {
// Fix up implicit from
if p.From.Type == obj.TYPE_NONE {
p.From = p.To
}
if copyau(&p.From, v) {
return 4
}
return 3
}
if copyau(&p.From, v) {
return 1
}
if copyau(&p.To, v) {
// p->to only indirectly uses v
return 1
}
return 0
case mips.ASGT, /* read p->from, read p->reg, write p->to */
mips.ASGTU,
mips.AADD,
mips.AADDU,
mips.ASUB,
mips.ASUBU,
mips.ASLL,
mips.ASRL,
mips.ASRA,
mips.AOR,
mips.ANOR,
mips.AAND,
mips.AXOR,
mips.AADDV,
mips.AADDVU,
mips.ASUBV,
//.........這裏部分代碼省略.........
示例9: progedit
func progedit(ctxt *obj.Link, p *obj.Prog) {
// Maintain information about code generation mode.
if ctxt.Mode == 0 {
ctxt.Mode = ctxt.Arch.Regsize * 8
}
p.Mode = int8(ctxt.Mode)
switch p.As {
case AMODE:
if p.From.Type == obj.TYPE_CONST || (p.From.Type == obj.TYPE_MEM && p.From.Reg == REG_NONE) {
switch int(p.From.Offset) {
case 16, 32, 64:
ctxt.Mode = int(p.From.Offset)
}
}
obj.Nopout(p)
}
// Thread-local storage references use the TLS pseudo-register.
// As a register, TLS refers to the thread-local storage base, and it
// can only be loaded into another register:
//
// MOVQ TLS, AX
//
// An offset from the thread-local storage base is written off(reg)(TLS*1).
// Semantically it is off(reg), but the (TLS*1) annotation marks this as
// indexing from the loaded TLS base. This emits a relocation so that
// if the linker needs to adjust the offset, it can. For example:
//
// MOVQ TLS, AX
// MOVQ 0(AX)(TLS*1), CX // load g into CX
//
// On systems that support direct access to the TLS memory, this
// pair of instructions can be reduced to a direct TLS memory reference:
//
// MOVQ 0(TLS), CX // load g into CX
//
// The 2-instruction and 1-instruction forms correspond to the two code
// sequences for loading a TLS variable in the local exec model given in "ELF
// Handling For Thread-Local Storage".
//
// We apply this rewrite on systems that support the 1-instruction form.
// The decision is made using only the operating system and the -shared flag,
// not the link mode. If some link modes on a particular operating system
// require the 2-instruction form, then all builds for that operating system
// will use the 2-instruction form, so that the link mode decision can be
// delayed to link time.
//
// In this way, all supported systems use identical instructions to
// access TLS, and they are rewritten appropriately first here in
// liblink and then finally using relocations in the linker.
//
// When -shared is passed, we leave the code in the 2-instruction form but
// assemble (and relocate) them in different ways to generate the initial
// exec code sequence. It's a bit of a fluke that this is possible without
// rewriting the instructions more comprehensively, and it only does because
// we only support a single TLS variable (g).
if CanUse1InsnTLS(ctxt) {
// Reduce 2-instruction sequence to 1-instruction sequence.
// Sequences like
// MOVQ TLS, BX
// ... off(BX)(TLS*1) ...
// become
// NOP
// ... off(TLS) ...
//
// TODO(rsc): Remove the Hsolaris special case. It exists only to
// guarantee we are producing byte-identical binaries as before this code.
// But it should be unnecessary.
if (p.As == AMOVQ || p.As == AMOVL) && p.From.Type == obj.TYPE_REG && p.From.Reg == REG_TLS && p.To.Type == obj.TYPE_REG && REG_AX <= p.To.Reg && p.To.Reg <= REG_R15 && ctxt.Headtype != obj.Hsolaris {
obj.Nopout(p)
}
if p.From.Type == obj.TYPE_MEM && p.From.Index == REG_TLS && REG_AX <= p.From.Reg && p.From.Reg <= REG_R15 {
p.From.Reg = REG_TLS
p.From.Scale = 0
p.From.Index = REG_NONE
}
if p.To.Type == obj.TYPE_MEM && p.To.Index == REG_TLS && REG_AX <= p.To.Reg && p.To.Reg <= REG_R15 {
p.To.Reg = REG_TLS
p.To.Scale = 0
p.To.Index = REG_NONE
}
} else {
// load_g_cx, below, always inserts the 1-instruction sequence. Rewrite it
// as the 2-instruction sequence if necessary.
// MOVQ 0(TLS), BX
// becomes
// MOVQ TLS, BX
// MOVQ 0(BX)(TLS*1), BX
if (p.As == AMOVQ || p.As == AMOVL) && p.From.Type == obj.TYPE_MEM && p.From.Reg == REG_TLS && p.To.Type == obj.TYPE_REG && REG_AX <= p.To.Reg && p.To.Reg <= REG_R15 {
q := obj.Appendp(ctxt, p)
q.As = p.As
q.From = p.From
q.From.Type = obj.TYPE_MEM
q.From.Reg = p.To.Reg
q.From.Index = REG_TLS
q.From.Scale = 2 // TODO: use 1
q.To = p.To
//.........這裏部分代碼省略.........
示例10: peep
func peep(firstp *obj.Prog) {
g := gc.Flowstart(firstp, nil)
if g == nil {
return
}
gactive = 0
var p *obj.Prog
var r *gc.Flow
var t int
loop1:
if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 {
gc.Dumpit("loop1", g.Start, 0)
}
t = 0
for r = g.Start; r != nil; r = r.Link {
p = r.Prog
// TODO(minux) Handle smaller moves. arm and amd64
// distinguish between moves that *must* sign/zero
// extend and moves that don't care so they
// can eliminate moves that don't care without
// breaking moves that do care. This might let us
// simplify or remove the next peep loop, too.
if p.As == arm64.AMOVD || p.As == arm64.AFMOVD {
if regtyp(&p.To) {
// Try to eliminate reg->reg moves
if regtyp(&p.From) {
if p.From.Type == p.To.Type {
if copyprop(r) {
excise(r)
t++
} else if subprop(r) && copyprop(r) {
excise(r)
t++
}
}
}
}
}
}
if t != 0 {
goto loop1
}
/*
* look for MOVB x,R; MOVB R,R (for small MOVs not handled above)
*/
var p1 *obj.Prog
var r1 *gc.Flow
for r := g.Start; r != nil; r = r.Link {
p = r.Prog
switch p.As {
default:
continue
case arm64.AMOVH,
arm64.AMOVHU,
arm64.AMOVB,
arm64.AMOVBU,
arm64.AMOVW,
arm64.AMOVWU:
if p.To.Type != obj.TYPE_REG {
continue
}
}
r1 = r.Link
if r1 == nil {
continue
}
p1 = r1.Prog
if p1.As != p.As {
continue
}
if p1.From.Type != obj.TYPE_REG || p1.From.Reg != p.To.Reg {
continue
}
if p1.To.Type != obj.TYPE_REG || p1.To.Reg != p.To.Reg {
continue
}
excise(r1)
}
if gc.Debug['D'] > 1 {
goto ret /* allow following code improvement to be suppressed */
}
// MOVD $c, R'; ADD R', R (R' unused) -> ADD $c, R
for r := g.Start; r != nil; r = r.Link {
p = r.Prog
switch p.As {
default:
continue
case arm64.AMOVD:
if p.To.Type != obj.TYPE_REG {
continue
//.........這裏部分代碼省略.........
示例11: copyu
// If s==nil, copyu returns the set/use of v in p; otherwise, it
// modifies p to replace reads of v with reads of s and returns 0 for
// success or non-zero for failure.
//
// If s==nil, copy returns one of the following values:
// 1 if v only used
// 2 if v is set and used in one address (read-alter-rewrite;
// can't substitute)
// 3 if v is only set
// 4 if v is set in one address and used in another (so addresses
// can be rewritten independently)
// 0 otherwise (not touched)
func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
if p.From3.Type != obj.TYPE_NONE {
// 7g never generates a from3
fmt.Printf("copyu: from3 (%v) not implemented\n", gc.Ctxt.Dconv(&p.From3))
}
if p.To2.Type != obj.TYPE_NONE {
// 7g never generates a to2
fmt.Printf("copyu: to2 (%v) not implemented\n", gc.Ctxt.Dconv(&p.To2))
}
switch p.As {
default:
fmt.Printf("copyu: can't find %v\n", obj.Aconv(int(p.As)))
return 2
case obj.ANOP, /* read p->from, write p->to */
arm64.ANEG,
arm64.AFNEGD,
arm64.AFNEGS,
arm64.AFSQRTD,
arm64.AFCVTZSD,
arm64.AFCVTZSS,
arm64.AFCVTZSDW,
arm64.AFCVTZSSW,
arm64.AFCVTZUD,
arm64.AFCVTZUS,
arm64.AFCVTZUDW,
arm64.AFCVTZUSW,
arm64.AFCVTSD,
arm64.AFCVTDS,
arm64.ASCVTFD,
arm64.ASCVTFS,
arm64.ASCVTFWD,
arm64.ASCVTFWS,
arm64.AUCVTFD,
arm64.AUCVTFS,
arm64.AUCVTFWD,
arm64.AUCVTFWS,
arm64.AMOVB,
arm64.AMOVBU,
arm64.AMOVH,
arm64.AMOVHU,
arm64.AMOVW,
arm64.AMOVWU,
arm64.AMOVD,
arm64.AFMOVS,
arm64.AFMOVD:
if p.Scond == 0 {
if s != nil {
if copysub(&p.From, v, s, 1) != 0 {
return 1
}
// Update only indirect uses of v in p->to
if !copyas(&p.To, v) {
if copysub(&p.To, v, s, 1) != 0 {
return 1
}
}
return 0
}
if copyas(&p.To, v) {
// Fix up implicit from
if p.From.Type == obj.TYPE_NONE {
p.From = p.To
}
if copyau(&p.From, v) {
return 4
}
return 3
}
if copyau(&p.From, v) {
return 1
}
if copyau(&p.To, v) {
// p->to only indirectly uses v
return 1
}
return 0
}
/* rar p->from, write p->to or read p->from, rar p->to */
if p.From.Type == obj.TYPE_MEM {
if copyas(&p.From, v) {
// No s!=nil check; need to fail
//.........這裏部分代碼省略.........
示例12: copyu
// If s==nil, copyu returns the set/use of v in p; otherwise, it
// modifies p to replace reads of v with reads of s and returns 0 for
// success or non-zero for failure.
//
// If s==nil, copy returns one of the following values:
// 1 if v only used
// 2 if v is set and used in one address (read-alter-rewrite;
// can't substitute)
// 3 if v is only set
// 4 if v is set in one address and used in another (so addresses
// can be rewritten independently)
// 0 otherwise (not touched)
func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
if p.From3Type() != obj.TYPE_NONE && p.From3Type() != obj.TYPE_CONST {
// Currently we never generate a From3 with anything other than a constant in it.
fmt.Printf("copyu: From3 (%v) not implemented\n", gc.Ctxt.Dconv(p.From3))
}
switch p.As {
default:
fmt.Printf("copyu: can't find %v\n", obj.Aconv(int(p.As)))
return 2
case obj.ANOP, /* read p->from, write p->to */
s390x.AMOVH,
s390x.AMOVHZ,
s390x.AMOVB,
s390x.AMOVBZ,
s390x.AMOVW,
s390x.AMOVWZ,
s390x.AMOVD,
s390x.ANEG,
s390x.AADDME,
s390x.AADDZE,
s390x.ASUBME,
s390x.ASUBZE,
s390x.AFMOVS,
s390x.AFMOVD,
s390x.AFRSP,
s390x.AFNEG,
s390x.ALDEBR,
s390x.ACLFEBR,
s390x.ACLGEBR,
s390x.ACLFDBR,
s390x.ACLGDBR,
s390x.ACFEBRA,
s390x.ACGEBRA,
s390x.ACFDBRA,
s390x.ACGDBRA,
s390x.ACELFBR,
s390x.ACELGBR,
s390x.ACDLFBR,
s390x.ACDLGBR,
s390x.ACEFBRA,
s390x.ACEGBRA,
s390x.ACDFBRA,
s390x.ACDGBRA,
s390x.AFSQRT:
if s != nil {
if copysub(&p.From, v, s, 1) != 0 {
return 1
}
// Update only indirect uses of v in p->to
if !copyas(&p.To, v) {
if copysub(&p.To, v, s, 1) != 0 {
return 1
}
}
return 0
}
if copyas(&p.To, v) {
// Fix up implicit from
if p.From.Type == obj.TYPE_NONE {
p.From = p.To
}
if copyau(&p.From, v) {
return 4
}
return 3
}
if copyau(&p.From, v) {
return 1
}
if copyau(&p.To, v) {
// p->to only indirectly uses v
return 1
}
return 0
// read p->from, read p->reg, rar p->to
case s390x.ARLWMI:
if copyas(&p.To, v) {
return 2
}
fallthrough
//.........這裏部分代碼省略.........
示例13: preprocess
func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
// TODO(minux): add morestack short-cuts with small fixed frame-size.
ctxt.Cursym = cursym
if cursym.Text == nil || cursym.Text.Link == nil {
return
}
p := cursym.Text
textstksiz := p.To.Offset
if textstksiz == -8 {
// Compatibility hack.
p.From3.Offset |= obj.NOFRAME
textstksiz = 0
}
if textstksiz%8 != 0 {
ctxt.Diag("frame size %d not a multiple of 8", textstksiz)
}
if p.From3.Offset&obj.NOFRAME != 0 {
if textstksiz != 0 {
ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
}
}
cursym.Args = p.To.Val.(int32)
cursym.Locals = int32(textstksiz)
/*
* find leaf subroutines
* strip NOPs
* expand RET
* expand BECOME pseudo
*/
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f noops\n", obj.Cputime())
}
var q *obj.Prog
var q1 *obj.Prog
for p := cursym.Text; p != nil; p = p.Link {
switch p.As {
/* too hard, just leave alone */
case obj.ATEXT:
q = p
p.Mark |= LABEL | LEAF | SYNC
if p.Link != nil {
p.Link.Mark |= LABEL
}
case ASYNC,
AWORD:
q = p
p.Mark |= LABEL | SYNC
continue
case AMOVW, AMOVWZ, AMOVD:
q = p
if p.From.Reg >= REG_RESERVED || p.To.Reg >= REG_RESERVED {
p.Mark |= LABEL | SYNC
}
continue
case AFABS,
AFADD,
AFDIV,
AFMADD,
AFMOVD,
AFMOVS,
AFMSUB,
AFMUL,
AFNABS,
AFNEG,
AFNMADD,
AFNMSUB,
ALEDBR,
ALDEBR,
AFSUB:
q = p
p.Mark |= FLOAT
continue
case ABL,
ABCL,
obj.ADUFFZERO,
obj.ADUFFCOPY:
cursym.Text.Mark &^= LEAF
fallthrough
case ABC,
ABEQ,
ABGE,
ABGT,
ABLE,
ABLT,
ABLEU,
ABLTU,
ABNE,
ABR,
//.........這裏部分代碼省略.........
示例14: progedit
func progedit(ctxt *obj.Link, p *obj.Prog) {
// Maintain information about code generation mode.
if ctxt.Mode == 0 {
ctxt.Mode = ctxt.Arch.Regsize * 8
}
p.Mode = int8(ctxt.Mode)
switch p.As {
case AMODE:
if p.From.Type == obj.TYPE_CONST || (p.From.Type == obj.TYPE_MEM && p.From.Reg == REG_NONE) {
switch int(p.From.Offset) {
case 16, 32, 64:
ctxt.Mode = int(p.From.Offset)
}
}
obj.Nopout(p)
}
// Thread-local storage references use the TLS pseudo-register.
// As a register, TLS refers to the thread-local storage base, and it
// can only be loaded into another register:
//
// MOVQ TLS, AX
//
// An offset from the thread-local storage base is written off(reg)(TLS*1).
// Semantically it is off(reg), but the (TLS*1) annotation marks this as
// indexing from the loaded TLS base. This emits a relocation so that
// if the linker needs to adjust the offset, it can. For example:
//
// MOVQ TLS, AX
// MOVQ 8(AX)(TLS*1), CX // load m into CX
//
// On systems that support direct access to the TLS memory, this
// pair of instructions can be reduced to a direct TLS memory reference:
//
// MOVQ 8(TLS), CX // load m into CX
//
// The 2-instruction and 1-instruction forms correspond roughly to
// ELF TLS initial exec mode and ELF TLS local exec mode, respectively.
//
// We applies this rewrite on systems that support the 1-instruction form.
// The decision is made using only the operating system (and probably
// the -shared flag, eventually), not the link mode. If some link modes
// on a particular operating system require the 2-instruction form,
// then all builds for that operating system will use the 2-instruction
// form, so that the link mode decision can be delayed to link time.
//
// In this way, all supported systems use identical instructions to
// access TLS, and they are rewritten appropriately first here in
// liblink and then finally using relocations in the linker.
if canuselocaltls(ctxt) {
// Reduce TLS initial exec model to TLS local exec model.
// Sequences like
// MOVQ TLS, BX
// ... off(BX)(TLS*1) ...
// become
// NOP
// ... off(TLS) ...
//
// TODO(rsc): Remove the Hsolaris special case. It exists only to
// guarantee we are producing byte-identical binaries as before this code.
// But it should be unnecessary.
if (p.As == AMOVQ || p.As == AMOVL) && p.From.Type == obj.TYPE_REG && p.From.Reg == REG_TLS && p.To.Type == obj.TYPE_REG && REG_AX <= p.To.Reg && p.To.Reg <= REG_R15 && ctxt.Headtype != obj.Hsolaris {
obj.Nopout(p)
}
if p.From.Type == obj.TYPE_MEM && p.From.Index == REG_TLS && REG_AX <= p.From.Reg && p.From.Reg <= REG_R15 {
p.From.Reg = REG_TLS
p.From.Scale = 0
p.From.Index = REG_NONE
}
if p.To.Type == obj.TYPE_MEM && p.To.Index == REG_TLS && REG_AX <= p.To.Reg && p.To.Reg <= REG_R15 {
p.To.Reg = REG_TLS
p.To.Scale = 0
p.To.Index = REG_NONE
}
} else {
// As a courtesy to the C compilers, rewrite TLS local exec load as TLS initial exec load.
// The instruction
// MOVQ off(TLS), BX
// becomes the sequence
// MOVQ TLS, BX
// MOVQ off(BX)(TLS*1), BX
// This allows the C compilers to emit references to m and g using the direct off(TLS) form.
if (p.As == AMOVQ || p.As == AMOVL) && p.From.Type == obj.TYPE_MEM && p.From.Reg == REG_TLS && p.To.Type == obj.TYPE_REG && REG_AX <= p.To.Reg && p.To.Reg <= REG_R15 {
q := obj.Appendp(ctxt, p)
q.As = p.As
q.From = p.From
q.From.Type = obj.TYPE_MEM
q.From.Reg = p.To.Reg
q.From.Index = REG_TLS
q.From.Scale = 2 // TODO: use 1
q.To = p.To
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_TLS
p.From.Index = REG_NONE
p.From.Offset = 0
}
}
//.........這裏部分代碼省略.........
示例15: mergetemp
func mergetemp(firstp *obj.Prog) {
const (
debugmerge = 1
)
g := Flowstart(firstp, nil)
if g == nil {
return
}
// Build list of all mergeable variables.
nvar := 0
for l := Curfn.Dcl; l != nil; l = l.Next {
if canmerge(l.N) {
nvar++
}
}
var_ := make([]TempVar, nvar)
nvar = 0
var n *Node
var v *TempVar
for l := Curfn.Dcl; l != nil; l = l.Next {
n = l.N
if canmerge(n) {
v = &var_[nvar]
nvar++
n.Opt = v
v.node = n
}
}
// Build list of uses.
// We assume that the earliest reference to a temporary is its definition.
// This is not true of variables in general but our temporaries are all
// single-use (that's why we have so many!).
var p *obj.Prog
var info ProgInfo
for f := g.Start; f != nil; f = f.Link {
p = f.Prog
info = Thearch.Proginfo(p)
if p.From.Node != nil && ((p.From.Node).(*Node)).Opt != nil && p.To.Node != nil && ((p.To.Node).(*Node)).Opt != nil {
Fatal("double node %v", p)
}
v = nil
n, _ = p.From.Node.(*Node)
if n != nil {
v, _ = n.Opt.(*TempVar)
}
if v == nil {
n, _ = p.To.Node.(*Node)
if n != nil {
v, _ = n.Opt.(*TempVar)
}
}
if v != nil {
if v.def == nil {
v.def = f
}
f.Data = v.use
v.use = f
if n == p.From.Node && (info.Flags&LeftAddr != 0) {
v.addr = 1
}
}
}
if debugmerge > 1 && Debug['v'] != 0 {
Dumpit("before", g.Start, 0)
}
nkill := 0
// Special case.
var p1 *obj.Prog
var info1 ProgInfo
var f *Flow
for i := 0; i < len(var_); i++ {
v = &var_[i]
if v.addr != 0 {
continue
}
// Used in only one instruction, which had better be a write.
f = v.use
if f != nil && f.Data.(*Flow) == nil {
p = f.Prog
info = Thearch.Proginfo(p)
if p.To.Node == v.node && (info.Flags&RightWrite != 0) && info.Flags&RightRead == 0 {
p.As = obj.ANOP
p.To = obj.Addr{}
v.removed = 1
if debugmerge > 0 && Debug['v'] != 0 {
fmt.Printf("drop write-only %v\n", Sconv(v.node.Sym, 0))
}
} else {
Fatal("temp used and not set: %v", p)
}
nkill++
//.........這裏部分代碼省略.........