本文整理汇总了Golang中cmd/internal/obj.Link.Diag方法的典型用法代码示例。如果您正苦于以下问题:Golang Link.Diag方法的具体用法?Golang Link.Diag怎么用?Golang Link.Diag使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类cmd/internal/obj.Link
的用法示例。
在下文中一共展示了Link.Diag方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: nacladdr
func nacladdr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
if p.As == ALEAL || p.As == ALEAQ {
return
}
if a.Reg == REG_BP {
ctxt.Diag("invalid address: %v", p)
return
}
if a.Reg == REG_TLS {
a.Reg = REG_BP
}
if a.Type == obj.TYPE_MEM && a.Name == obj.NAME_NONE {
switch a.Reg {
// all ok
case REG_BP, REG_SP, REG_R15:
break
default:
if a.Index != REG_NONE {
ctxt.Diag("invalid address %v", p)
}
a.Index = a.Reg
if a.Index != REG_NONE {
a.Scale = 1
}
a.Reg = REG_R15
}
}
}
示例2: oplook
func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
if oprange[AOR&obj.AMask].start == nil {
buildop(ctxt)
}
a1 := int(p.Optab)
if a1 != 0 {
return &optab[a1-1:][0]
}
a1 = int(p.From.Class)
if a1 == 0 {
a1 = aclass(ctxt, &p.From) + 1
p.From.Class = int8(a1)
}
a1--
a3 := int(p.To.Class)
if a3 == 0 {
a3 = aclass(ctxt, &p.To) + 1
p.To.Class = int8(a3)
}
a3--
a2 := C_NONE
if p.Reg != 0 {
a2 = C_REG
}
//print("oplook %P %d %d %d\n", p, a1, a2, a3);
r0 := p.As & obj.AMask
o := oprange[r0].start
if o == nil {
o = oprange[r0].stop /* just generate an error */
}
e := oprange[r0].stop
c1 := xcmp[a1][:]
c3 := xcmp[a3][:]
for ; -cap(o) < -cap(e); o = o[1:] {
if int(o[0].a2) == a2 {
if c1[o[0].a1] != 0 {
if c3[o[0].a3] != 0 {
p.Optab = uint16((-cap(o) + cap(optab)) + 1)
return &o[0]
}
}
}
}
ctxt.Diag("illegal combination %v %v %v %v", obj.Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3))
prasm(p)
if o == nil {
o = optab
}
return &o[0]
}
示例3: oplook
func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
if oprange[AOR&obj.AMask] == nil {
buildop(ctxt)
}
a1 := int(p.Optab)
if a1 != 0 {
return &optab[a1-1]
}
a1 = int(p.From.Class)
if a1 == 0 {
a1 = aclass(ctxt, &p.From) + 1
p.From.Class = int8(a1)
}
a1--
a3 := int(p.To.Class)
if a3 == 0 {
a3 = aclass(ctxt, &p.To) + 1
p.To.Class = int8(a3)
}
a3--
a2 := C_NONE
if p.Reg != 0 {
a2 = C_REG
}
//print("oplook %P %d %d %d\n", p, a1, a2, a3);
ops := oprange[p.As&obj.AMask]
c1 := &xcmp[a1]
c3 := &xcmp[a3]
for i := range ops {
op := &ops[i]
if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
return op
}
}
ctxt.Diag("illegal combination %v %v %v %v", obj.Aconv(p.As), DRconv(a1), DRconv(a2), DRconv(a3))
prasm(p)
if ops == nil {
ops = optab
}
return &ops[0]
}
示例4: rewriteToUseGot
// Rewrite p, if necessary, to access global data via the global offset table.
func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
var add, lea, mov obj.As
var reg int16
if p.Mode == 64 {
add = AADDQ
lea = ALEAQ
mov = AMOVQ
reg = REG_R15
} else {
add = AADDL
lea = ALEAL
mov = AMOVL
reg = REG_CX
}
if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
// ADUFFxxx $offset
// becomes
// $MOV [email protected], $reg
// $ADD $offset, $reg
// CALL $reg
var sym *obj.LSym
if p.As == obj.ADUFFZERO {
sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
} else {
sym = obj.Linklookup(ctxt, "runtime.duffcopy", 0)
}
offset := p.To.Offset
p.As = mov
p.From.Type = obj.TYPE_MEM
p.From.Name = obj.NAME_GOTREF
p.From.Sym = sym
p.To.Type = obj.TYPE_REG
p.To.Reg = reg
p.To.Offset = 0
p.To.Sym = nil
p1 := obj.Appendp(ctxt, p)
p1.As = add
p1.From.Type = obj.TYPE_CONST
p1.From.Offset = offset
p1.To.Type = obj.TYPE_REG
p1.To.Reg = reg
p2 := obj.Appendp(ctxt, p1)
p2.As = obj.ACALL
p2.To.Type = obj.TYPE_REG
p2.To.Reg = reg
}
// We only care about global data: NAME_EXTERN means a global
// symbol in the Go sense, and p.Sym.Local is true for a few
// internally defined symbols.
if p.As == lea && p.From.Type == obj.TYPE_MEM && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
// $LEA sym, Rx becomes $MOV $sym, Rx which will be rewritten below
p.As = mov
p.From.Type = obj.TYPE_ADDR
}
if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
// $MOV $sym, Rx becomes $MOV [email protected], Rx
// $MOV $sym+<off>, Rx becomes $MOV [email protected], Rx; $LEA <off>(Rx), Rx
// On 386 only, more complicated things like PUSHL $sym become $MOV [email protected], CX; PUSHL CX
cmplxdest := false
pAs := p.As
var dest obj.Addr
if p.To.Type != obj.TYPE_REG || pAs != mov {
if p.Mode == 64 {
ctxt.Diag("do not know how to handle LEA-type insn to non-register in %v with -dynlink", p)
}
cmplxdest = true
dest = p.To
p.As = mov
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_CX
p.To.Sym = nil
p.To.Name = obj.NAME_NONE
}
p.From.Type = obj.TYPE_MEM
p.From.Name = obj.NAME_GOTREF
q := p
if p.From.Offset != 0 {
q = obj.Appendp(ctxt, p)
q.As = lea
q.From.Type = obj.TYPE_MEM
q.From.Reg = p.To.Reg
q.From.Offset = p.From.Offset
q.To = p.To
p.From.Offset = 0
}
if cmplxdest {
q = obj.Appendp(ctxt, q)
q.As = pAs
q.To = dest
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_CX
}
}
if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
ctxt.Diag("don't know how to handle %v with -dynlink", p)
}
var source *obj.Addr
//.........这里部分代码省略.........
示例5: preprocess
//.........这里部分代码省略.........
p.As = AMOVW
p.Scond |= C_PBIT
p.From.Type = obj.TYPE_MEM
p.From.Offset = int64(autosize)
p.From.Reg = REGSP
p.To.Type = obj.TYPE_REG
p.To.Reg = REGPC
// If there are instructions following
// this ARET, they come from a branch
// with the same stackframe, so no spadj.
if p.To.Sym != nil { // retjmp
p.To.Reg = REGLINK
q2 = obj.Appendp(ctxt, p)
q2.As = AB
q2.To.Type = obj.TYPE_BRANCH
q2.To.Sym = p.To.Sym
p.To.Sym = nil
p = q2
}
case AADD:
if p.From.Type == obj.TYPE_CONST && p.From.Reg == 0 && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP {
p.Spadj = int32(-p.From.Offset)
}
case ASUB:
if p.From.Type == obj.TYPE_CONST && p.From.Reg == 0 && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP {
p.Spadj = int32(p.From.Offset)
}
case ADIV, ADIVU, AMOD, AMODU:
if cursym.Text.From3.Offset&obj.NOSPLIT != 0 {
ctxt.Diag("cannot divide in NOSPLIT function")
}
if ctxt.Debugdivmod != 0 {
break
}
if p.From.Type != obj.TYPE_REG {
break
}
if p.To.Type != obj.TYPE_REG {
break
}
// Make copy because we overwrite p below.
q1 := *p
if q1.Reg == REGTMP || q1.Reg == 0 && q1.To.Reg == REGTMP {
ctxt.Diag("div already using REGTMP: %v", p)
}
/* MOV m(g),REGTMP */
p.As = AMOVW
p.Lineno = q1.Lineno
p.From.Type = obj.TYPE_MEM
p.From.Reg = REGG
p.From.Offset = 6 * 4 // offset of g.m
p.Reg = 0
p.To.Type = obj.TYPE_REG
p.To.Reg = REGTMP
/* MOV a,m_divmod(REGTMP) */
p = obj.Appendp(ctxt, p)
p.As = AMOVW
p.Lineno = q1.Lineno
p.From.Type = obj.TYPE_REG
示例6: progedit
func progedit(ctxt *obj.Link, p *obj.Prog) {
p.From.Class = 0
p.To.Class = 0
// Rewrite B/BL to symbol as TYPE_BRANCH.
switch p.As {
case AB,
ABL,
obj.ADUFFZERO,
obj.ADUFFCOPY:
if p.To.Type == obj.TYPE_MEM && (p.To.Name == obj.NAME_EXTERN || p.To.Name == obj.NAME_STATIC) && p.To.Sym != nil {
p.To.Type = obj.TYPE_BRANCH
}
}
// Replace TLS register fetches on older ARM procesors.
switch p.As {
// Treat MRC 15, 0, <reg>, C13, C0, 3 specially.
case AMRC:
if p.To.Offset&0xffff0fff == 0xee1d0f70 {
// Because the instruction might be rewriten to a BL which returns in R0
// the register must be zero.
if p.To.Offset&0xf000 != 0 {
ctxt.Diag("%v: TLS MRC instruction must write to R0 as it might get translated into a BL instruction", p.Line())
}
if ctxt.Goarm < 7 {
// Replace it with BL runtime.read_tls_fallback(SB) for ARM CPUs that lack the tls extension.
if progedit_tlsfallback == nil {
progedit_tlsfallback = obj.Linklookup(ctxt, "runtime.read_tls_fallback", 0)
}
// MOVW LR, R11
p.As = AMOVW
p.From.Type = obj.TYPE_REG
p.From.Reg = REGLINK
p.To.Type = obj.TYPE_REG
p.To.Reg = REGTMP
// BL runtime.read_tls_fallback(SB)
p = obj.Appendp(ctxt, p)
p.As = ABL
p.To.Type = obj.TYPE_BRANCH
p.To.Sym = progedit_tlsfallback
p.To.Offset = 0
// MOVW R11, LR
p = obj.Appendp(ctxt, p)
p.As = AMOVW
p.From.Type = obj.TYPE_REG
p.From.Reg = REGTMP
p.To.Type = obj.TYPE_REG
p.To.Reg = REGLINK
break
}
}
// Otherwise, MRC/MCR instructions need no further treatment.
p.As = AWORD
}
// Rewrite float constants to values stored in memory.
switch p.As {
case AMOVF:
if p.From.Type == obj.TYPE_FCONST && chipfloat5(ctxt, p.From.Val.(float64)) < 0 && (chipzero5(ctxt, p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) {
f32 := float32(p.From.Val.(float64))
i32 := math.Float32bits(f32)
literal := fmt.Sprintf("$f32.%08x", i32)
s := obj.Linklookup(ctxt, literal, 0)
p.From.Type = obj.TYPE_MEM
p.From.Sym = s
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
case AMOVD:
if p.From.Type == obj.TYPE_FCONST && chipfloat5(ctxt, p.From.Val.(float64)) < 0 && (chipzero5(ctxt, p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) {
i64 := math.Float64bits(p.From.Val.(float64))
literal := fmt.Sprintf("$f64.%016x", i64)
s := obj.Linklookup(ctxt, literal, 0)
p.From.Type = obj.TYPE_MEM
p.From.Sym = s
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
}
}
示例7: rewriteToUseGot
// Rewrite p, if necessary, to access global data via the global offset table.
func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
// ADUFFxxx $offset
// becomes
// MOVD [email protected], R12
// ADD $offset, R12
// MOVD R12, CTR
// BL (CTR)
var sym *obj.LSym
if p.As == obj.ADUFFZERO {
sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
} else {
sym = obj.Linklookup(ctxt, "runtime.duffcopy", 0)
}
offset := p.To.Offset
p.As = AMOVD
p.From.Type = obj.TYPE_MEM
p.From.Name = obj.NAME_GOTREF
p.From.Sym = sym
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R12
p.To.Name = obj.NAME_NONE
p.To.Offset = 0
p.To.Sym = nil
p1 := obj.Appendp(ctxt, p)
p1.As = AADD
p1.From.Type = obj.TYPE_CONST
p1.From.Offset = offset
p1.To.Type = obj.TYPE_REG
p1.To.Reg = REG_R12
p2 := obj.Appendp(ctxt, p1)
p2.As = AMOVD
p2.From.Type = obj.TYPE_REG
p2.From.Reg = REG_R12
p2.To.Type = obj.TYPE_REG
p2.To.Reg = REG_CTR
p3 := obj.Appendp(ctxt, p2)
p3.As = obj.ACALL
p3.From.Type = obj.TYPE_REG
p3.From.Reg = REG_R12
p3.To.Type = obj.TYPE_REG
p3.To.Reg = REG_CTR
}
// We only care about global data: NAME_EXTERN means a global
// symbol in the Go sense, and p.Sym.Local is true for a few
// internally defined symbols.
if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
// MOVD $sym, Rx becomes MOVD [email protected], Rx
// MOVD $sym+<off>, Rx becomes MOVD [email protected], Rx; ADD <off>, Rx
if p.As != AMOVD {
ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
}
if p.To.Type != obj.TYPE_REG {
ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
}
p.From.Type = obj.TYPE_MEM
p.From.Name = obj.NAME_GOTREF
if p.From.Offset != 0 {
q := obj.Appendp(ctxt, p)
q.As = AADD
q.From.Type = obj.TYPE_CONST
q.From.Offset = p.From.Offset
q.To = p.To
p.From.Offset = 0
}
}
if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
ctxt.Diag("don't know how to handle %v with -dynlink", p)
}
var source *obj.Addr
// MOVx sym, Ry becomes MOVD [email protected], REGTMP; MOVx (REGTMP), Ry
// MOVx Ry, sym becomes MOVD [email protected], REGTMP; MOVx Ry, (REGTMP)
// An addition may be inserted between the two MOVs if there is an offset.
if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
}
source = &p.From
} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
source = &p.To
} else {
return
}
if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
return
}
if source.Sym.Type == obj.STLSBSS {
return
}
if source.Type != obj.TYPE_MEM {
ctxt.Diag("don't know how to handle %v with -dynlink", p)
}
p1 := obj.Appendp(ctxt, p)
p2 := obj.Appendp(ctxt, p1)
p1.As = AMOVD
p1.From.Type = obj.TYPE_MEM
p1.From.Sym = source.Sym
//.........这里部分代码省略.........
示例8: 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 {
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 ALWAR,
ASTWCCC,
AECIWX,
AECOWX,
AEIEIO,
AICBI,
AISYNC,
ATLBIE,
ATLBIEL,
ASLBIA,
ASLBIE,
ASLBMFEE,
ASLBMFEV,
ASLBMTE,
ADCBF,
ADCBI,
ADCBST,
ADCBT,
ADCBTST,
ADCBZ,
ASYNC,
ATLBSYNC,
APTESYNC,
ATW,
AWORD,
ARFI,
ARFCI,
ARFID,
AHRFID:
q = p
p.Mark |= LABEL | SYNC
continue
case AMOVW, AMOVWZ, AMOVD:
q = p
if p.From.Reg >= REG_SPECIAL || p.To.Reg >= REG_SPECIAL {
p.Mark |= LABEL | SYNC
}
continue
case AFABS,
//.........这里部分代码省略.........
示例9: rewriteToUseGot
// Rewrite p, if necessary, to access global data via the global offset table.
func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
// At the moment EXRL instructions are not emitted by the compiler and only reference local symbols in
// assembly code.
if p.As == AEXRL {
return
}
// We only care about global data: NAME_EXTERN means a global
// symbol in the Go sense, and p.Sym.Local is true for a few
// internally defined symbols.
if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
// MOVD $sym, Rx becomes MOVD [email protected], Rx
// MOVD $sym+<off>, Rx becomes MOVD [email protected], Rx; ADD <off>, Rx
if p.To.Type != obj.TYPE_REG || p.As != AMOVD {
ctxt.Diag("do not know how to handle LEA-type insn to non-register in %v with -dynlink", p)
}
p.From.Type = obj.TYPE_MEM
p.From.Name = obj.NAME_GOTREF
q := p
if p.From.Offset != 0 {
q = obj.Appendp(ctxt, p)
q.As = AADD
q.From.Type = obj.TYPE_CONST
q.From.Offset = p.From.Offset
q.To = p.To
p.From.Offset = 0
}
}
if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
ctxt.Diag("don't know how to handle %v with -dynlink", p)
}
var source *obj.Addr
// MOVD sym, Ry becomes MOVD [email protected], REGTMP; MOVD (REGTMP), Ry
// MOVD Ry, sym becomes MOVD [email protected], REGTMP; MOVD Ry, (REGTMP)
// An addition may be inserted between the two MOVs if there is an offset.
if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
}
source = &p.From
} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
source = &p.To
} else {
return
}
if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
return
}
if source.Sym.Type == obj.STLSBSS {
return
}
if source.Type != obj.TYPE_MEM {
ctxt.Diag("don't know how to handle %v with -dynlink", p)
}
p1 := obj.Appendp(ctxt, p)
p2 := obj.Appendp(ctxt, p1)
p1.As = AMOVD
p1.From.Type = obj.TYPE_MEM
p1.From.Sym = source.Sym
p1.From.Name = obj.NAME_GOTREF
p1.To.Type = obj.TYPE_REG
p1.To.Reg = REGTMP
p2.As = p.As
p2.From = p.From
p2.To = p.To
if p.From.Name == obj.NAME_EXTERN {
p2.From.Reg = REGTMP
p2.From.Name = obj.NAME_NONE
p2.From.Sym = nil
} else if p.To.Name == obj.NAME_EXTERN {
p2.To.Reg = REGTMP
p2.To.Name = obj.NAME_NONE
p2.To.Sym = nil
} else {
return
}
obj.Nopout(p)
}
示例10: preprocess
//.........这里部分代码省略.........
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R5
q = obj.Appendp(ctxt, q)
q.As = ABNE
q.To.Type = obj.TYPE_BRANCH
p2 = q
q = obj.Appendp(ctxt, q)
q.As = AADD
q.From.Type = obj.TYPE_CONST
q.From.Offset = 8
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R6
q = obj.Appendp(ctxt, q)
q.As = AMOVD
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R6
q.To.Type = obj.TYPE_MEM
q.To.Reg = REG_R3
q.To.Offset = 0 // Panic.argp
q = obj.Appendp(ctxt, q)
q.As = obj.ANOP
p1.Pcond = q
p2.Pcond = q
}
case ARETURN:
if p.From.Type == obj.TYPE_CONST {
ctxt.Diag("using BECOME (%v) is not supported!", p)
break
}
if p.To.Sym != nil { // retjmp
p.As = ABR
p.To.Type = obj.TYPE_BRANCH
break
}
if cursym.Text.Mark&LEAF != 0 {
if autosize == 0 {
p.As = ABR
p.From = obj.Addr{}
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_LR
p.Mark |= BRANCH
break
}
p.As = AADD
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(autosize)
p.To.Type = obj.TYPE_REG
p.To.Reg = REGSP
p.Spadj = -autosize
q = ctxt.NewProg()
q.As = ABR
q.Lineno = p.Lineno
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_LR
q.Mark |= BRANCH
示例11: oprrr
//.........这里部分代码省略.........
case AMULVU:
return OP(3, 5)
case AJMP:
return OP(1, 0)
case AJAL:
return OP(1, 1)
case ABREAK:
return OP(1, 5)
case ASYSCALL:
return OP(1, 4)
case ATLBP:
return MMU(1, 0)
case ATLBR:
return MMU(0, 1)
case ATLBWI:
return MMU(0, 2)
case ATLBWR:
return MMU(0, 6)
case ARFE:
return MMU(2, 0)
case ADIVF:
return FPF(0, 3)
case ADIVD:
return FPD(0, 3)
case AMULF:
return FPF(0, 2)
case AMULD:
return FPD(0, 2)
case ASUBF:
return FPF(0, 1)
case ASUBD:
return FPD(0, 1)
case AADDF:
return FPF(0, 0)
case AADDD:
return FPD(0, 0)
case ATRUNCFV:
return FPF(1, 1)
case ATRUNCDV:
return FPD(1, 1)
case ATRUNCFW:
return FPF(1, 5)
case ATRUNCDW:
return FPD(1, 5)
case AMOVFV:
return FPF(4, 5)
case AMOVDV:
return FPD(4, 5)
case AMOVVF:
return FPV(4, 0)
case AMOVVD:
return FPV(4, 1)
case AMOVFW:
return FPF(4, 4)
case AMOVDW:
return FPD(4, 4)
case AMOVWF:
return FPW(4, 0)
case AMOVDF:
return FPD(4, 0)
case AMOVWD:
return FPW(4, 1)
case AMOVFD:
return FPF(4, 1)
case AABSF:
return FPF(0, 5)
case AABSD:
return FPD(0, 5)
case AMOVF:
return FPF(0, 6)
case AMOVD:
return FPD(0, 6)
case ANEGF:
return FPF(0, 7)
case ANEGD:
return FPD(0, 7)
case ACMPEQF:
return FPF(6, 2)
case ACMPEQD:
return FPD(6, 2)
case ACMPGTF:
return FPF(7, 4)
case ACMPGTD:
return FPD(7, 4)
case ACMPGEF:
return FPF(7, 6)
case ACMPGED:
return FPD(7, 6)
}
if a >= ALAST {
ctxt.Diag("bad rrr opcode %v+ALAST", obj.Aconv(a-ALAST))
} else {
ctxt.Diag("bad rrr opcode %v", obj.Aconv(a))
}
return 0
}
示例12: span0
func span0(ctxt *obj.Link, cursym *obj.LSym) {
p := cursym.Text
if p == nil || p.Link == nil { // handle external functions and ELF section symbols
return
}
ctxt.Cursym = cursym
ctxt.Autosize = int32(p.To.Offset + 8)
if oprange[AOR&obj.AMask].start == nil {
buildop(ctxt)
}
c := int64(0)
p.Pc = c
var m int
var o *Optab
for p = p.Link; p != nil; p = p.Link {
ctxt.Curp = p
p.Pc = c
o = oplook(ctxt, p)
m = int(o.size)
if m == 0 {
if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
ctxt.Diag("zero-width instruction\n%v", p)
}
continue
}
c += int64(m)
}
cursym.Size = c
/*
* if any procedure is large enough to
* generate a large SBRA branch, then
* generate extra passes putting branches
* around jmps to fix. this is rare.
*/
bflag := 1
var otxt int64
var q *obj.Prog
for bflag != 0 {
if ctxt.Debugvlog != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
}
bflag = 0
c = 0
for p = cursym.Text.Link; p != nil; p = p.Link {
p.Pc = c
o = oplook(ctxt, p)
// very large conditional branches
if o.type_ == 6 && p.Pcond != nil {
otxt = p.Pcond.Pc - c
if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
q = ctxt.NewProg()
q.Link = p.Link
p.Link = q
q.As = AJMP
q.Lineno = p.Lineno
q.To.Type = obj.TYPE_BRANCH
q.Pcond = p.Pcond
p.Pcond = q
q = ctxt.NewProg()
q.Link = p.Link
p.Link = q
q.As = AJMP
q.Lineno = p.Lineno
q.To.Type = obj.TYPE_BRANCH
q.Pcond = q.Link.Link
addnop(ctxt, p.Link)
addnop(ctxt, p)
bflag = 1
}
}
m = int(o.size)
if m == 0 {
if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
ctxt.Diag("zero-width instruction\n%v", p)
}
continue
}
c += int64(m)
}
cursym.Size = c
}
c += -c & (FuncAlign - 1)
cursym.Size = c
/*
* lay out the code, emitting code and data relocations.
*/
//.........这里部分代码省略.........
示例13: preprocess
//.........这里部分代码省略.........
q.As = ABNE
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R2
q.Reg = REG_R3
q.To.Type = obj.TYPE_BRANCH
q.Mark |= BRANCH
p2 = q
q = obj.Appendp(ctxt, q)
q.As = add
q.From.Type = obj.TYPE_CONST
q.From.Offset = ctxt.FixedFrameSize()
q.Reg = REGSP
q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R2
q = obj.Appendp(ctxt, q)
q.As = mov
q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R2
q.To.Type = obj.TYPE_MEM
q.To.Reg = REG_R1
q.To.Offset = 0 // Panic.argp
q = obj.Appendp(ctxt, q)
q.As = obj.ANOP
p1.Pcond = q
p2.Pcond = q
}
case ARET:
if p.From.Type == obj.TYPE_CONST {
ctxt.Diag("using BECOME (%v) is not supported!", p)
break
}
retSym := p.To.Sym
p.To.Name = obj.NAME_NONE // clear fields as we may modify p to other instruction
p.To.Sym = nil
if cursym.Text.Mark&LEAF != 0 {
if autosize == 0 {
p.As = AJMP
p.From = obj.Addr{}
if retSym != nil { // retjmp
p.To.Type = obj.TYPE_BRANCH
p.To.Name = obj.NAME_EXTERN
p.To.Sym = retSym
} else {
p.To.Type = obj.TYPE_MEM
p.To.Reg = REGLINK
p.To.Offset = 0
}
p.Mark |= BRANCH
break
}
p.As = add
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(autosize)
p.To.Type = obj.TYPE_REG
p.To.Reg = REGSP
p.Spadj = -autosize
q = ctxt.NewProg()
示例14: progedit
func progedit(ctxt *obj.Link, p *obj.Prog) {
// Maintain information about code generation mode.
if ctxt.Mode == 0 {
switch ctxt.Arch.Family {
default:
ctxt.Diag("unsupported arch family")
case sys.MIPS:
ctxt.Mode = Mips32
case sys.MIPS64:
ctxt.Mode = Mips64
}
}
p.From.Class = 0
p.To.Class = 0
// Rewrite JMP/JAL to symbol as TYPE_BRANCH.
switch p.As {
case AJMP,
AJAL,
ARET,
obj.ADUFFZERO,
obj.ADUFFCOPY:
if p.To.Sym != nil {
p.To.Type = obj.TYPE_BRANCH
}
}
// Rewrite float constants to values stored in memory.
switch p.As {
case AMOVF:
if p.From.Type == obj.TYPE_FCONST {
f32 := float32(p.From.Val.(float64))
i32 := math.Float32bits(f32)
if i32 == 0 {
p.As = AMOVW
p.From.Type = obj.TYPE_REG
p.From.Reg = REGZERO
break
}
literal := fmt.Sprintf("$f32.%08x", i32)
s := obj.Linklookup(ctxt, literal, 0)
s.Size = 4
p.From.Type = obj.TYPE_MEM
p.From.Sym = s
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
case AMOVD:
if p.From.Type == obj.TYPE_FCONST {
i64 := math.Float64bits(p.From.Val.(float64))
if i64 == 0 && ctxt.Mode&Mips64 != 0 {
p.As = AMOVV
p.From.Type = obj.TYPE_REG
p.From.Reg = REGZERO
break
}
literal := fmt.Sprintf("$f64.%016x", i64)
s := obj.Linklookup(ctxt, literal, 0)
s.Size = 8
p.From.Type = obj.TYPE_MEM
p.From.Sym = s
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
// Put >32-bit constants in memory and load them
case AMOVV:
if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && int64(int32(p.From.Offset)) != p.From.Offset {
literal := fmt.Sprintf("$i64.%016x", uint64(p.From.Offset))
s := obj.Linklookup(ctxt, literal, 0)
s.Size = 8
p.From.Type = obj.TYPE_MEM
p.From.Sym = s
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
}
// Rewrite SUB constants into ADD.
switch p.As {
case ASUB:
if p.From.Type == obj.TYPE_CONST {
p.From.Offset = -p.From.Offset
p.As = AADD
}
case ASUBU:
if p.From.Type == obj.TYPE_CONST {
p.From.Offset = -p.From.Offset
p.As = AADDU
}
case ASUBV:
if p.From.Type == obj.TYPE_CONST {
p.From.Offset = -p.From.Offset
p.As = AADDV
}
//.........这里部分代码省略.........
示例15: preprocess
func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
if ctxt.Headtype == obj.Hplan9 && ctxt.Plan9privates == nil {
ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
}
ctxt.Cursym = cursym
if cursym.Text == nil || cursym.Text.Link == nil {
return
}
p := cursym.Text
autoffset := int32(p.To.Offset)
if autoffset < 0 {
autoffset = 0
}
var bpsize int
if p.Mode == 64 && ctxt.Framepointer_enabled && autoffset > 0 && p.From3.Offset&obj.NOFRAME == 0 {
// Make room for to save a base pointer. If autoffset == 0,
// this might do something special like a tail jump to
// another function, so in that case we omit this.
bpsize = ctxt.Arch.PtrSize
autoffset += int32(bpsize)
p.To.Offset += int64(bpsize)
} else {
bpsize = 0
}
textarg := int64(p.To.Val.(int32))
cursym.Args = int32(textarg)
cursym.Locals = int32(p.To.Offset)
// TODO(rsc): Remove.
if p.Mode == 32 && cursym.Locals < 0 {
cursym.Locals = 0
}
// TODO(rsc): Remove 'p.Mode == 64 &&'.
if p.Mode == 64 && autoffset < obj.StackSmall && p.From3Offset()&obj.NOSPLIT == 0 {
leaf := true
LeafSearch:
for q := p; q != nil; q = q.Link {
switch q.As {
case obj.ACALL:
// Treat common runtime calls that take no arguments
// the same as duffcopy and duffzero.
if !isZeroArgRuntimeCall(q.To.Sym) {
leaf = false
break LeafSearch
}
fallthrough
case obj.ADUFFCOPY, obj.ADUFFZERO:
if autoffset >= obj.StackSmall-8 {
leaf = false
break LeafSearch
}
}
}
if leaf {
p.From3.Offset |= obj.NOSPLIT
}
}
if p.From3Offset()&obj.NOSPLIT == 0 || p.From3Offset()&obj.WRAPPER != 0 {
p = obj.Appendp(ctxt, p)
p = load_g_cx(ctxt, p) // load g into CX
}
if cursym.Text.From3Offset()&obj.NOSPLIT == 0 {
p = stacksplit(ctxt, p, autoffset, int32(textarg)) // emit split check
}
if autoffset != 0 {
if autoffset%int32(ctxt.Arch.RegSize) != 0 {
ctxt.Diag("unaligned stack size %d", autoffset)
}
p = obj.Appendp(ctxt, p)
p.As = AADJSP
p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(autoffset)
p.Spadj = autoffset
}
deltasp := autoffset
if bpsize > 0 {
// Save caller's BP
p = obj.Appendp(ctxt, p)
p.As = AMOVQ
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_BP
p.To.Type = obj.TYPE_MEM
p.To.Reg = REG_SP
p.To.Scale = 1
p.To.Offset = int64(autoffset) - int64(bpsize)
// Move current frame to BP
//.........这里部分代码省略.........