From a037c73ccfc7c35a389e95ffa7996c8dd38e0cde Mon Sep 17 00:00:00 2001 From: Ryan Brown Date: Mon, 14 Mar 2016 09:23:04 -0700 Subject: cmd/link: generate DWARF info using symbols This updates dwarf.go to generate debug information as symbols instead of directly writing to the output file. This should make it easier to move generation of some of the debug info into the compiler. Change-Id: Id2358988bfb689865ab4d68f82716f0676336df4 Reviewed-on: https://go-review.googlesource.com/20679 Reviewed-by: David Crawshaw Run-TryBot: David Crawshaw TryBot-Result: Gobot Gobot --- src/cmd/internal/obj/link.go | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 24f028f737..9c06e8dec6 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -423,6 +423,8 @@ const ( SCONST SDYNIMPORT SHOSTOBJ + SDWARFSECT + SDWARFINFO SSUB = 1 << 8 SMASK = SSUB - 1 SHIDDEN = 1 << 9 @@ -495,6 +497,8 @@ const ( // of a JMP instruction, by encoding the address into the instruction. // The stack nosplit check ignores this since it is not a function call. R_JMPMIPS + // R_DWARFREF resolves to the offset of the symbol from its section. + R_DWARFREF // Platform dependent relocations. Architectures with fixed width instructions // have the inherent issue that a 32-bit (or 64-bit!) displacement cannot be -- cgit v1.3 From c6e11fe03765e3fe1fc68bd794625ca0ecd833be Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 6 Apr 2016 12:01:40 -0700 Subject: cmd: add new common architecture representation Information about CPU architectures (e.g., name, family, byte ordering, pointer and register size) is currently redundantly scattered around the source tree. Instead consolidate the basic information into a single new package cmd/internal/sys. Also, introduce new sys.I386, sys.AMD64, etc. names for the constants '8', '6', etc. and replace most uses of the latter. The notable exceptions are a couple of error messages that still refer to the old char-based toolchain names and function reltype in cmd/link. Passes toolstash/buildall. Change-Id: I8a6f0cbd49577ec1672a98addebc45f767e36461 Reviewed-on: https://go-review.googlesource.com/21623 Reviewed-by: Michael Hudson-Doyle Reviewed-by: Brad Fitzpatrick Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot --- src/cmd/asm/internal/asm/asm.go | 49 +++++----- src/cmd/asm/internal/asm/parse.go | 16 ++-- src/cmd/compile/internal/amd64/galign.go | 12 +-- src/cmd/compile/internal/arm/galign.go | 7 +- src/cmd/compile/internal/arm64/galign.go | 7 +- src/cmd/compile/internal/gc/cgen.go | 88 +++++++++--------- src/cmd/compile/internal/gc/gen.go | 3 +- src/cmd/compile/internal/gc/go.go | 5 +- src/cmd/compile/internal/gc/gsubr.go | 19 ++-- src/cmd/compile/internal/gc/main.go | 21 +++-- src/cmd/compile/internal/gc/pgen.go | 5 +- src/cmd/compile/internal/gc/plive.go | 3 +- src/cmd/compile/internal/gc/reg.go | 7 +- src/cmd/compile/internal/gc/ssa.go | 7 +- src/cmd/compile/internal/gc/walk.go | 10 +-- src/cmd/compile/internal/mips64/galign.go | 10 +-- src/cmd/compile/internal/ppc64/galign.go | 11 +-- src/cmd/compile/internal/x86/galign.go | 7 +- src/cmd/dist/buildtool.go | 1 + src/cmd/internal/obj/arm/obj5.go | 15 ++-- src/cmd/internal/obj/arm64/obj7.go | 15 ++-- src/cmd/internal/obj/data.go | 2 +- src/cmd/internal/obj/link.go | 19 ++-- src/cmd/internal/obj/mips/obj0.go | 22 ++--- src/cmd/internal/obj/objfile.go | 3 +- src/cmd/internal/obj/pcln.go | 4 +- src/cmd/internal/obj/ppc64/obj9.go | 22 ++--- src/cmd/internal/obj/s390x/objz.go | 15 ++-- src/cmd/internal/obj/sym.go | 3 +- src/cmd/internal/obj/x86/asm6.go | 2 +- src/cmd/internal/obj/x86/obj6.go | 55 +++++------- src/cmd/internal/sys/arch.go | 145 ++++++++++++++++++++++++++++++ src/cmd/link/internal/amd64/asm.go | 2 +- src/cmd/link/internal/amd64/l.go | 5 -- src/cmd/link/internal/amd64/obj.go | 11 +-- src/cmd/link/internal/arm/l.go | 2 - src/cmd/link/internal/arm/obj.go | 9 +- src/cmd/link/internal/arm64/asm.go | 2 +- src/cmd/link/internal/arm64/l.go | 2 - src/cmd/link/internal/arm64/obj.go | 9 +- src/cmd/link/internal/ld/arch.go | 97 -------------------- src/cmd/link/internal/ld/data.go | 57 ++++++------ src/cmd/link/internal/ld/deadcode.go | 3 +- src/cmd/link/internal/ld/decodesym.go | 77 ++++++++-------- src/cmd/link/internal/ld/dwarf.go | 44 ++++----- src/cmd/link/internal/ld/elf.go | 92 ++++++++++--------- src/cmd/link/internal/ld/ldelf.go | 26 +++--- src/cmd/link/internal/ld/ldmacho.go | 18 ++-- src/cmd/link/internal/ld/ldpe.go | 3 +- src/cmd/link/internal/ld/lib.go | 53 +++++------ src/cmd/link/internal/ld/link.go | 25 ++---- src/cmd/link/internal/ld/macho.go | 46 ++++------ src/cmd/link/internal/ld/pcln.go | 38 ++++---- src/cmd/link/internal/ld/pe.go | 29 +++--- src/cmd/link/internal/ld/pobj.go | 9 +- src/cmd/link/internal/ld/sym.go | 33 +++---- src/cmd/link/internal/ld/symtab.go | 5 +- src/cmd/link/internal/mips64/asm.go | 9 +- src/cmd/link/internal/mips64/l.go | 2 - src/cmd/link/internal/mips64/obj.go | 15 ++-- src/cmd/link/internal/ppc64/l.go | 2 - src/cmd/link/internal/ppc64/obj.go | 17 ++-- src/cmd/link/internal/s390x/l.go | 5 -- src/cmd/link/internal/s390x/obj.go | 9 +- src/cmd/link/internal/x86/asm.go | 4 +- src/cmd/link/internal/x86/l.go | 3 - src/cmd/link/internal/x86/obj.go | 9 +- 67 files changed, 639 insertions(+), 743 deletions(-) create mode 100644 src/cmd/internal/sys/arch.go delete mode 100644 src/cmd/link/internal/ld/arch.go (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go index 950fd735c9..d674914c67 100644 --- a/src/cmd/asm/internal/asm/asm.go +++ b/src/cmd/asm/internal/asm/asm.go @@ -13,6 +13,7 @@ import ( "cmd/asm/internal/flags" "cmd/asm/internal/lex" "cmd/internal/obj" + "cmd/internal/sys" ) // TODO: configure the architecture @@ -23,14 +24,14 @@ var testOut *bytes.Buffer // Gathers output when testing. // If doLabel is set, it also defines the labels collect for this Prog. func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) { if cond != "" { - switch p.arch.Thechar { - case '5': + switch p.arch.Family { + case sys.ARM: if !arch.ARMConditionCodes(prog, cond) { p.errorf("unrecognized condition code .%q", cond) return } - case '7': + case sys.ARM64: if !arch.ARM64Suffix(prog, cond) { p.errorf("unrecognized suffix .%q", cond) return @@ -361,7 +362,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) { target = &a[1] prog.From = a[0] case 3: - if p.arch.Thechar == '9' { + if p.arch.Family == sys.PPC64 { // Special 3-operand jumps. // First two must be constants; a[1] is a register number. target = &a[2] @@ -378,7 +379,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) { prog.Reg = reg break } - if p.arch.Thechar == '0' { + if p.arch.Family == sys.MIPS64 { // 3-operand jumps. // First two must be registers target = &a[2] @@ -386,7 +387,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) { prog.Reg = p.getRegister(prog, op, &a[1]) break } - if p.arch.Thechar == 'z' { + if p.arch.Family == sys.S390X { // 3-operand jumps. target = &a[2] prog.From = a[0] @@ -438,7 +439,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) { // JMP 4(R0) prog.To = *target // On the ppc64, 9a encodes BR (CTR) as BR CTR. We do the same. - if p.arch.Thechar == '9' && target.Offset == 0 { + if p.arch.Family == sys.PPC64 && target.Offset == 0 { prog.To.Type = obj.TYPE_REG } case target.Type == obj.TYPE_CONST: @@ -492,14 +493,14 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { prog.From = a[0] // prog.To is no address. } - if p.arch.Thechar == '9' && arch.IsPPC64NEG(op) { + if p.arch.Family == sys.PPC64 && arch.IsPPC64NEG(op) { // NEG: From and To are both a[0]. prog.To = a[0] prog.From = a[0] break } case 2: - if p.arch.Thechar == '5' { + if p.arch.Family == sys.ARM { if arch.IsARMCMP(op) { prog.From = a[0] prog.Reg = p.getRegister(prog, op, &a[1]) @@ -532,11 +533,11 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { prog.Reg = p.getRegister(prog, op, &a[1]) break } - } else if p.arch.Thechar == '7' && arch.IsARM64CMP(op) { + } else if p.arch.Family == sys.ARM64 && arch.IsARM64CMP(op) { prog.From = a[0] prog.Reg = p.getRegister(prog, op, &a[1]) break - } else if p.arch.Thechar == '0' { + } else if p.arch.Family == sys.MIPS64 { if arch.IsMIPS64CMP(op) || arch.IsMIPS64MUL(op) { prog.From = a[0] prog.Reg = p.getRegister(prog, op, &a[1]) @@ -546,12 +547,12 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { prog.From = a[0] prog.To = a[1] case 3: - switch p.arch.Thechar { - case '0': + switch p.arch.Family { + case sys.MIPS64: prog.From = a[0] prog.Reg = p.getRegister(prog, op, &a[1]) prog.To = a[2] - case '5': + case sys.ARM: // Special cases. if arch.IsARMSTREX(op) { /* @@ -567,7 +568,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { prog.From = a[0] prog.Reg = p.getRegister(prog, op, &a[1]) prog.To = a[2] - case '7': + case sys.ARM64: // ARM64 instructions with one input and two outputs. if arch.IsARM64STLXR(op) { prog.From = a[0] @@ -582,11 +583,11 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { prog.From = a[0] prog.Reg = p.getRegister(prog, op, &a[1]) prog.To = a[2] - case '6', '8': + case sys.AMD64, sys.I386: prog.From = a[0] prog.From3 = newAddr(a[1]) prog.To = a[2] - case '9': + case sys.PPC64: if arch.IsPPC64CMP(op) { // CMPW etc.; third argument is a CR register that goes into prog.Reg. prog.From = a[0] @@ -612,7 +613,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { p.errorf("invalid addressing modes for %s instruction", obj.Aconv(op)) return } - case 'z': + case sys.S390X: if arch.IsS390xWithLength(op) || arch.IsS390xWithIndex(op) { prog.From = a[1] prog.From3 = newAddr(a[0]) @@ -626,7 +627,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { return } case 4: - if p.arch.Thechar == '5' && arch.IsARMMULA(op) { + if p.arch.Family == sys.ARM && arch.IsARMMULA(op) { // All must be registers. p.getRegister(prog, op, &a[0]) r1 := p.getRegister(prog, op, &a[1]) @@ -639,14 +640,14 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { prog.Reg = r1 break } - if p.arch.Thechar == '7' { + if p.arch.Family == sys.ARM64 { prog.From = a[0] prog.Reg = p.getRegister(prog, op, &a[1]) prog.From3 = newAddr(a[2]) prog.To = a[3] break } - if p.arch.Thechar == '9' && arch.IsPPC64RLD(op) { + if p.arch.Family == sys.PPC64 && arch.IsPPC64RLD(op) { // 2nd operand must always be a register. // TODO: Do we need to guard this with the instruction type? // That is, are there 4-operand instructions without this property? @@ -656,7 +657,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { prog.To = a[3] break } - if p.arch.Thechar == 'z' { + if p.arch.Family == sys.S390X { prog.From = a[1] prog.Reg = p.getRegister(prog, op, &a[2]) prog.From3 = newAddr(a[0]) @@ -666,7 +667,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { p.errorf("can't handle %s instruction with 4 operands", obj.Aconv(op)) return case 5: - if p.arch.Thechar == '9' && arch.IsPPC64RLD(op) { + if p.arch.Family == sys.PPC64 && arch.IsPPC64RLD(op) { // Always reg, reg, con, con, reg. (con, con is a 'mask'). prog.From = a[0] prog.Reg = p.getRegister(prog, op, &a[1]) @@ -688,7 +689,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { p.errorf("can't handle %s instruction with 5 operands", obj.Aconv(op)) return case 6: - if p.arch.Thechar == '5' && arch.IsARMMRC(op) { + if p.arch.Family == sys.ARM && arch.IsARMMRC(op) { // Strange special case: MCR, MRC. prog.To.Type = obj.TYPE_CONST x0 := p.getConstant(prog, op, &a[0]) diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go index ee37439962..40206e6dc1 100644 --- a/src/cmd/asm/internal/asm/parse.go +++ b/src/cmd/asm/internal/asm/parse.go @@ -19,6 +19,7 @@ import ( "cmd/asm/internal/flags" "cmd/asm/internal/lex" "cmd/internal/obj" + "cmd/internal/sys" ) type Parser struct { @@ -130,7 +131,7 @@ func (p *Parser) line() bool { for { tok = p.lex.Next() if len(operands) == 0 && len(items) == 0 { - if (p.arch.Thechar == '5' || p.arch.Thechar == '7') && tok == '.' { + if p.arch.InFamily(sys.ARM, sys.ARM64) && tok == '.' { // ARM conditionals. tok = p.lex.Next() str := p.lex.Text() @@ -420,7 +421,7 @@ func (p *Parser) atStartOfRegister(name string) bool { // We have consumed the register or R prefix. func (p *Parser) atRegisterShift() bool { // ARM only. - if p.arch.Thechar != '5' { + if p.arch.Family != sys.ARM { return false } // R1<<... @@ -476,15 +477,14 @@ func (p *Parser) register(name string, prefix rune) (r1, r2 int16, scale int8, o if c == ':' || c == ',' || c == '+' { // 2nd register; syntax (R1+R2) etc. No two architectures agree. // Check the architectures match the syntax. - char := p.arch.Thechar switch p.next().ScanToken { case ',': - if char != '5' && char != '7' { + if !p.arch.InFamily(sys.ARM, sys.ARM64) { p.errorf("(register,register) not supported on this architecture") return } case '+': - if char != '9' { + if p.arch.Family != sys.PPC64 { p.errorf("(register+register) not supported on this architecture") return } @@ -649,7 +649,7 @@ func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) { a.Reg = r1 if r2 != 0 { // TODO: Consistency in the encoding would be nice here. - if p.arch.Thechar == '5' || p.arch.Thechar == '7' { + if p.arch.InFamily(sys.ARM, sys.ARM64) { // Special form // ARM: destination register pair (R1, R2). // ARM64: register pair (R1, R2) for LDP/STP. @@ -662,7 +662,7 @@ func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) { // Nothing may follow return } - if p.arch.Thechar == '9' { + if p.arch.Family == sys.PPC64 { // Special form for PPC64: (R1+R2); alias for (R1)(R2*1). if prefix != 0 || scale != 0 { p.errorf("illegal address mode for register+register") @@ -752,7 +752,7 @@ ListLoop: // register number is ARM-specific. It returns the number of the specified register. func (p *Parser) registerNumber(name string) uint16 { - if p.arch.Thechar == '5' && name == "g" { + if p.arch.Family == sys.ARM && name == "g" { return 10 } if name[0] != 'R' { diff --git a/src/cmd/compile/internal/amd64/galign.go b/src/cmd/compile/internal/amd64/galign.go index 14721ea35b..461ef2ada1 100644 --- a/src/cmd/compile/internal/amd64/galign.go +++ b/src/cmd/compile/internal/amd64/galign.go @@ -18,12 +18,7 @@ var ( ) func betypeinit() { - gc.Widthptr = 8 - gc.Widthint = 8 - gc.Widthreg = 8 if obj.Getgoarch() == "amd64p32" { - gc.Widthptr = 4 - gc.Widthint = 4 addptr = x86.AADDL movptr = x86.AMOVL leaptr = x86.ALEAL @@ -42,12 +37,9 @@ func Main() { resvd = append(resvd, x86.REG_BP) } - gc.Thearch.Thechar = '6' - gc.Thearch.Thestring = "amd64" - gc.Thearch.Thelinkarch = &x86.Linkamd64 + gc.Thearch.LinkArch = &x86.Linkamd64 if obj.Getgoarch() == "amd64p32" { - gc.Thearch.Thestring = "amd64p32" - gc.Thearch.Thelinkarch = &x86.Linkamd64p32 + gc.Thearch.LinkArch = &x86.Linkamd64p32 } gc.Thearch.REGSP = x86.REGSP gc.Thearch.REGCTXT = x86.REGCTXT diff --git a/src/cmd/compile/internal/arm/galign.go b/src/cmd/compile/internal/arm/galign.go index e05f4d06bb..afd86e44c8 100644 --- a/src/cmd/compile/internal/arm/galign.go +++ b/src/cmd/compile/internal/arm/galign.go @@ -11,15 +11,10 @@ import ( ) func betypeinit() { - gc.Widthptr = 4 - gc.Widthint = 4 - gc.Widthreg = 4 } func Main() { - gc.Thearch.Thechar = '5' - gc.Thearch.Thestring = "arm" - gc.Thearch.Thelinkarch = &arm.Linkarm + gc.Thearch.LinkArch = &arm.Linkarm gc.Thearch.REGSP = arm.REGSP gc.Thearch.REGCTXT = arm.REGCTXT gc.Thearch.REGCALLX = arm.REG_R1 diff --git a/src/cmd/compile/internal/arm64/galign.go b/src/cmd/compile/internal/arm64/galign.go index 7e1226fee1..17c851cb14 100644 --- a/src/cmd/compile/internal/arm64/galign.go +++ b/src/cmd/compile/internal/arm64/galign.go @@ -10,15 +10,10 @@ import ( ) func betypeinit() { - gc.Widthptr = 8 - gc.Widthint = 8 - gc.Widthreg = 8 } func Main() { - gc.Thearch.Thechar = '7' - gc.Thearch.Thestring = "arm64" - gc.Thearch.Thelinkarch = &arm64.Linkarm64 + gc.Thearch.LinkArch = &arm64.Linkarm64 gc.Thearch.REGSP = arm64.REGSP gc.Thearch.REGCTXT = arm64.REGCTXT gc.Thearch.REGCALLX = arm64.REGRT1 diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go index c594ad4c11..a9cedf7cfc 100644 --- a/src/cmd/compile/internal/gc/cgen.go +++ b/src/cmd/compile/internal/gc/cgen.go @@ -7,6 +7,7 @@ package gc import ( "cmd/internal/obj" "cmd/internal/obj/ppc64" + "cmd/internal/sys" "fmt" ) @@ -88,7 +89,7 @@ func cgen_wb(n, res *Node, wb bool) { if !res.Addable { if n.Ullman > res.Ullman { - if Ctxt.Arch.Regsize == 4 && Is64(n.Type) { + if Ctxt.Arch.RegSize == 4 && Is64(n.Type) { var n1 Node Tempname(&n1, n.Type) Cgen(n, &n1) @@ -127,7 +128,7 @@ func cgen_wb(n, res *Node, wb bool) { f = false } - if !n.Type.IsComplex() && Ctxt.Arch.Regsize == 8 && !wb { + if !n.Type.IsComplex() && Ctxt.Arch.RegSize == 8 && !wb { a := Thearch.Optoas(OAS, res.Type) var addr obj.Addr if Thearch.Sudoaddable(a, res, &addr) { @@ -151,7 +152,7 @@ func cgen_wb(n, res *Node, wb bool) { } } - if Ctxt.Arch.Thechar == '8' { + if Ctxt.Arch.Family == sys.I386 { // no registers to speak of var n1, n2 Node Tempname(&n1, n.Type) @@ -203,7 +204,7 @@ func cgen_wb(n, res *Node, wb bool) { // Write barrier now handled. Code below this line can ignore wb. - if Ctxt.Arch.Thechar == '5' { // TODO(rsc): Maybe more often? + if Ctxt.Arch.Family == sys.ARM { // TODO(rsc): Maybe more often? // if both are addressable, move if n.Addable && res.Addable { if Is64(n.Type) || Is64(res.Type) || n.Op == OREGISTER || res.Op == OREGISTER || n.Type.IsComplex() || res.Type.IsComplex() { @@ -246,12 +247,12 @@ func cgen_wb(n, res *Node, wb bool) { return } - if (Ctxt.Arch.Thechar == '6' || Ctxt.Arch.Thechar == '8') && n.Addable { + if Ctxt.Arch.InFamily(sys.AMD64, sys.I386) && n.Addable { Thearch.Gmove(n, res) return } - if Ctxt.Arch.Thechar == '0' || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' { + if Ctxt.Arch.InFamily(sys.ARM64, sys.MIPS64, sys.PPC64) { // if both are addressable, move if n.Addable { if n.Op == OREGISTER || res.Op == OREGISTER { @@ -268,7 +269,7 @@ func cgen_wb(n, res *Node, wb bool) { } // if n is sudoaddable generate addr and move - if Ctxt.Arch.Thechar == '5' && !Is64(n.Type) && !Is64(res.Type) && !n.Type.IsComplex() && !res.Type.IsComplex() { + if Ctxt.Arch.Family == sys.ARM && !Is64(n.Type) && !Is64(res.Type) && !n.Type.IsComplex() && !res.Type.IsComplex() { a := Thearch.Optoas(OAS, n.Type) var addr obj.Addr if Thearch.Sudoaddable(a, n, &addr) { @@ -310,7 +311,7 @@ func cgen_wb(n, res *Node, wb bool) { } // 64-bit ops are hard on 32-bit machine. - if Ctxt.Arch.Regsize == 4 && (Is64(n.Type) || Is64(res.Type) || n.Left != nil && Is64(n.Left.Type)) { + if Ctxt.Arch.RegSize == 4 && (Is64(n.Type) || Is64(res.Type) || n.Left != nil && Is64(n.Left.Type)) { switch n.Op { // math goes to cgen64. case OMINUS, @@ -334,7 +335,7 @@ func cgen_wb(n, res *Node, wb bool) { return } - if !n.Type.IsComplex() && Ctxt.Arch.Regsize == 8 { + if !n.Type.IsComplex() && Ctxt.Arch.RegSize == 8 { a := Thearch.Optoas(OAS, n.Type) var addr obj.Addr if Thearch.Sudoaddable(a, n, &addr) { @@ -401,11 +402,11 @@ func cgen_wb(n, res *Node, wb bool) { Regalloc(&n1, nl.Type, res) Cgen(nl, &n1) - if Ctxt.Arch.Thechar == '5' { + if Ctxt.Arch.Family == sys.ARM { var n2 Node Nodconst(&n2, nl.Type, 0) Thearch.Gins(a, &n2, &n1) - } else if Ctxt.Arch.Thechar == '7' { + } else if Ctxt.Arch.Family == sys.ARM64 { Thearch.Gins(a, &n1, &n1) } else { Thearch.Gins(a, nil, &n1) @@ -452,7 +453,7 @@ func cgen_wb(n, res *Node, wb bool) { return } - if Ctxt.Arch.Thechar == '8' { + if Ctxt.Arch.Family == sys.I386 { var n1 Node var n2 Node Tempname(&n2, n.Type) @@ -465,7 +466,7 @@ func cgen_wb(n, res *Node, wb bool) { var n1 Node var n2 Node - if Ctxt.Arch.Thechar == '5' { + if Ctxt.Arch.Family == sys.ARM { if nl.Addable && !Is64(nl.Type) { Regalloc(&n1, nl.Type, res) Thearch.Gmove(nl, &n1) @@ -707,7 +708,7 @@ sbop: // symmetric binary abop: // asymmetric binary var n1 Node var n2 Node - if Ctxt.Arch.Thechar == '8' { + if Ctxt.Arch.Family == sys.I386 { // no registers, sigh if Smallintconst(nr) { var n1 Node @@ -751,14 +752,14 @@ abop: // asymmetric binary Regalloc(&n1, nl.Type, res) Cgen(nl, &n1) - if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm + if Smallintconst(nr) && Ctxt.Arch.Family != sys.MIPS64 && Ctxt.Arch.Family != sys.ARM && Ctxt.Arch.Family != sys.ARM64 && Ctxt.Arch.Family != sys.PPC64 { // TODO(rsc): Check opcode for arm n2 = *nr } else { Regalloc(&n2, nr.Type, nil) Cgen(nr, &n2) } } else { - if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { // TODO(rsc): Check opcode for arm + if Smallintconst(nr) && Ctxt.Arch.Family != sys.MIPS64 && Ctxt.Arch.Family != sys.ARM && Ctxt.Arch.Family != sys.ARM64 && Ctxt.Arch.Family != sys.PPC64 { // TODO(rsc): Check opcode for arm n2 = *nr } else { Regalloc(&n2, nr.Type, res) @@ -876,8 +877,8 @@ func cgen_wbfat(n, res *Node) { // cgen_norm moves n1 to res, truncating to expected type if necessary. // n1 is a register, and cgen_norm frees it. func cgen_norm(n, n1, res *Node) { - switch Ctxt.Arch.Thechar { - case '6', '8': + switch Ctxt.Arch.Family { + case sys.AMD64, sys.I386: // We use sized math, so the result is already truncated. default: switch n.Op { @@ -980,7 +981,7 @@ func Agenr(n *Node, a *Node, res *Node) { Cgen_checknil(a) case OINDEX: - if Ctxt.Arch.Thechar == '5' { + if Ctxt.Arch.Family == sys.ARM { var p2 *obj.Prog // to be patched to panicindex. w := uint32(n.Type.Width) bounded := Debug['B'] != 0 || n.Bounded @@ -1127,7 +1128,7 @@ func Agenr(n *Node, a *Node, res *Node) { Regfree(&n2) break } - if Ctxt.Arch.Thechar == '8' { + if Ctxt.Arch.Family == sys.I386 { var p2 *obj.Prog // to be patched to panicindex. w := uint32(n.Type.Width) bounded := Debug['B'] != 0 || n.Bounded @@ -1604,7 +1605,7 @@ func Agen(n *Node, res *Node) { } func addOffset(res *Node, offset int64) { - if Ctxt.Arch.Thechar == '6' || Ctxt.Arch.Thechar == '8' { + if Ctxt.Arch.InFamily(sys.AMD64, sys.I386) { Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), Nodintconst(offset), res) return } @@ -1825,13 +1826,14 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { return case ONAME: + // Some architectures might need a temporary or other help here, + // but they don't support direct generation of a bool value yet. + // We can fix that as we go. + mayNeedTemp := Ctxt.Arch.InFamily(sys.ARM, sys.ARM64, sys.MIPS64, sys.PPC64) + if genval { - // 5g, 7g, and 9g might need a temporary or other help here, - // but they don't support direct generation of a bool value yet. - // We can fix that as we go. - switch Ctxt.Arch.Thechar { - case '0', '5', '7', '9': - Fatalf("genval 0g, 5g, 7g, 9g ONAMES not fully implemented") + if mayNeedTemp { + Fatalf("genval ONAMES not fully implemented") } Cgen(n, res) if !wantTrue { @@ -1840,7 +1842,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { return } - if n.Addable && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' { + if n.Addable && !mayNeedTemp { // no need for a temporary bgenNonZero(n, nil, wantTrue, likely, to) return @@ -1977,7 +1979,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { return } - if Ctxt.Arch.Regsize == 4 && Is64(nr.Type) { + if Ctxt.Arch.RegSize == 4 && Is64(nr.Type) { if genval { // TODO: Teach Cmp64 to generate boolean values and remove this. bvgenjump(n, res, wantTrue, false) @@ -2015,7 +2017,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { Regfree(&n2) } else { var n1 Node - if !nl.Addable && Ctxt.Arch.Thechar == '8' { + if !nl.Addable && Ctxt.Arch.Family == sys.I386 { Tempname(&n1, nl.Type) } else { Regalloc(&n1, nl.Type, nil) @@ -2024,13 +2026,13 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { Cgen(nl, &n1) nl = &n1 - if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '9' { + if Smallintconst(nr) && Ctxt.Arch.Family != sys.MIPS64 && Ctxt.Arch.Family != sys.PPC64 { Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), nl, nr) bins(nr.Type, res, op, likely, to) return } - if !nr.Addable && Ctxt.Arch.Thechar == '8' { + if !nr.Addable && Ctxt.Arch.Family == sys.I386 { nr = CgenTemp(nr) } @@ -2044,13 +2046,13 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { l, r := nl, nr // On x86, only < and <= work right with NaN; reverse if needed - if Ctxt.Arch.Thechar == '6' && nl.Type.IsFloat() && (op == OGT || op == OGE) { + if Ctxt.Arch.Family == sys.AMD64 && nl.Type.IsFloat() && (op == OGT || op == OGE) { l, r = r, l op = Brrev(op) } // MIPS does not have CMP instruction - if Ctxt.Arch.Thechar == '0' { + if Ctxt.Arch.Family == sys.MIPS64 { p := Thearch.Ginscmp(op, nr.Type, l, r, likely) Patch(p, to) return @@ -2062,8 +2064,8 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { // Handle floating point special cases. // Note that 8g has Bgen_float and is handled above. if nl.Type.IsFloat() { - switch Ctxt.Arch.Thechar { - case '5': + switch Ctxt.Arch.Family { + case sys.ARM: if genval { Fatalf("genval 5g Isfloat special cases not implemented") } @@ -2077,7 +2079,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { Patch(p, Pc) } return - case '6': + case sys.AMD64: switch n.Op { case OEQ: // neither NE nor P @@ -2111,7 +2113,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { } return } - case '7', '9': + case sys.ARM64, sys.PPC64: if genval { Fatalf("genval 7g, 9g Isfloat special cases not implemented") } @@ -2143,7 +2145,7 @@ func bgenNonZero(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { } // MIPS does not have CMP instruction - if Thearch.Thechar == '0' { + if Thearch.LinkArch.Family == sys.MIPS64 { p := Gbranch(Thearch.Optoas(op, n.Type), n.Type, likely) Naddr(&p.From, n) Patch(p, to) @@ -2352,7 +2354,7 @@ func Ginscall(f *Node, proc int) { // into the instruction stream. Thearch.Ginsnop() - if Thearch.Thechar == '9' { + if Thearch.LinkArch.Family == sys.PPC64 { // On ppc64, when compiling Go into position // independent code on ppc64le we insert an // instruction to reload the TOC pointer from the @@ -2630,7 +2632,7 @@ func cgen_div(op Op, nl *Node, nr *Node, res *Node) { // in peep and optoas in order to enable this. // TODO(rsc): ppc64 needs to support the relevant instructions // in peep and optoas in order to enable this. - if nr.Op != OLITERAL || Ctxt.Arch.Thechar == '0' || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' { + if nr.Op != OLITERAL || Ctxt.Arch.Family == sys.MIPS64 || Ctxt.Arch.Family == sys.ARM64 || Ctxt.Arch.Family == sys.PPC64 { goto longdiv } w = int(nl.Type.Width * 8) @@ -2995,7 +2997,7 @@ func cgen_slice(n, res *Node, wb bool) { regalloc := Regalloc ginscon := Thearch.Ginscon gins := Thearch.Gins - if Thearch.Thechar == '8' { + if Thearch.LinkArch.Family == sys.I386 { regalloc = func(n *Node, t *Type, reuse *Node) { Tempname(n, t) } @@ -3238,7 +3240,7 @@ func cgen_slice(n, res *Node, wb bool) { compare := func(n1, n2 *Node) { // n1 might be a 64-bit constant, even on 32-bit architectures, // but it will be represented in 32 bits. - if Ctxt.Arch.Regsize == 4 && Is64(n1.Type) { + if Ctxt.Arch.RegSize == 4 && Is64(n1.Type) { if n1.Val().U.(*Mpint).CmpInt64(1<<31) >= 0 { Fatalf("missed slice out of bounds check") } diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go index 4a98f41bcb..7527452c93 100644 --- a/src/cmd/compile/internal/gc/gen.go +++ b/src/cmd/compile/internal/gc/gen.go @@ -8,6 +8,7 @@ package gc import ( "cmd/internal/obj" + "cmd/internal/sys" "fmt" ) @@ -1174,7 +1175,7 @@ func visitComponents(t *Type, startOffset int64, f func(elem *Type, elemOffset i } // NOTE: Assuming little endian (signed top half at offset 4). // We don't have any 32-bit big-endian systems. - if Thearch.Thechar != '5' && Thearch.Thechar != '8' { + if !Thearch.LinkArch.InFamily(sys.ARM, sys.I386) { Fatalf("unknown 32-bit architecture") } return f(Types[TUINT32], startOffset) && diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index 4cb985b1be..ef8b516ea5 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -360,9 +360,8 @@ const ( ) type Arch struct { - Thechar int - Thestring string - Thelinkarch *obj.LinkArch + LinkArch *obj.LinkArch + REGSP int REGCTXT int REGCALLX int // BX diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go index a2fa5f8b31..63a8e969c3 100644 --- a/src/cmd/compile/internal/gc/gsubr.go +++ b/src/cmd/compile/internal/gc/gsubr.go @@ -32,6 +32,7 @@ package gc import ( "cmd/internal/obj" + "cmd/internal/sys" "fmt" "runtime" "strings" @@ -57,7 +58,7 @@ func Ismem(n *Node) bool { return true case OADDR: - return Thearch.Thechar == '6' || Thearch.Thechar == '9' // because 6g uses PC-relative addressing; TODO(rsc): not sure why 9g too + return Thearch.LinkArch.InFamily(sys.AMD64, sys.PPC64) // because 6g uses PC-relative addressing; TODO(rsc): not sure why 9g too } return false @@ -83,7 +84,7 @@ func Gbranch(as obj.As, t *Type, likely int) *obj.Prog { p := Prog(as) p.To.Type = obj.TYPE_BRANCH p.To.Val = nil - if as != obj.AJMP && likely != 0 && Thearch.Thechar != '9' && Thearch.Thechar != '7' && Thearch.Thechar != '0' { + if as != obj.AJMP && likely != 0 && Thearch.LinkArch.Family != sys.PPC64 && Thearch.LinkArch.Family != sys.ARM64 && Thearch.LinkArch.Family != sys.MIPS64 { p.From.Type = obj.TYPE_CONST if likely > 0 { p.From.Offset = 1 @@ -330,7 +331,7 @@ func Naddr(a *obj.Addr, n *Node) { a.Type = obj.TYPE_REG a.Reg = n.Reg a.Sym = nil - if Thearch.Thechar == '8' { // TODO(rsc): Never clear a->width. + if Thearch.LinkArch.Family == sys.I386 { // TODO(rsc): Never clear a->width. a.Width = 0 } @@ -342,7 +343,7 @@ func Naddr(a *obj.Addr, n *Node) { if a.Offset != int64(int32(a.Offset)) { Yyerror("offset %d too large for OINDREG", a.Offset) } - if Thearch.Thechar == '8' { // TODO(rsc): Never clear a->width. + if Thearch.LinkArch.Family == sys.I386 { // TODO(rsc): Never clear a->width. a.Width = 0 } @@ -424,7 +425,7 @@ func Naddr(a *obj.Addr, n *Node) { Naddr(a, n.Left) case OLITERAL: - if Thearch.Thechar == '8' { + if Thearch.LinkArch.Family == sys.I386 { a.Width = 0 } switch n.Val().Ctype() { @@ -457,7 +458,7 @@ func Naddr(a *obj.Addr, n *Node) { case OADDR: Naddr(a, n.Left) a.Etype = uint8(Tptr) - if Thearch.Thechar != '0' && Thearch.Thechar != '5' && Thearch.Thechar != '7' && Thearch.Thechar != '9' { // TODO(rsc): Do this even for arm, ppc64. + if !Thearch.LinkArch.InFamily(sys.MIPS64, sys.ARM, sys.ARM64, sys.PPC64) { // TODO(rsc): Do this even for arm, ppc64. a.Width = int64(Widthptr) } if a.Type != obj.TYPE_MEM { @@ -496,7 +497,7 @@ func Naddr(a *obj.Addr, n *Node) { } a.Etype = uint8(Simtype[TUINT]) a.Offset += int64(Array_nel) - if Thearch.Thechar != '5' { // TODO(rsc): Do this even on arm. + if Thearch.LinkArch.Family != sys.ARM { // TODO(rsc): Do this even on arm. a.Width = int64(Widthint) } @@ -509,7 +510,7 @@ func Naddr(a *obj.Addr, n *Node) { } a.Etype = uint8(Simtype[TUINT]) a.Offset += int64(Array_cap) - if Thearch.Thechar != '5' { // TODO(rsc): Do this even on arm. + if Thearch.LinkArch.Family != sys.ARM { // TODO(rsc): Do this even on arm. a.Width = int64(Widthint) } } @@ -695,7 +696,7 @@ func Regalloc(n *Node, t *Type, o *Node) { Fatalf("regalloc: t nil") } et := Simtype[t.Etype] - if Ctxt.Arch.Regsize == 4 && (et == TINT64 || et == TUINT64) { + if Ctxt.Arch.RegSize == 4 && (et == TINT64 || et == TUINT64) { Fatalf("regalloc 64bit") } diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 73ecb09fa5..72e6478afe 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -10,6 +10,7 @@ import ( "bufio" "cmd/compile/internal/ssa" "cmd/internal/obj" + "cmd/internal/sys" "flag" "fmt" "io" @@ -96,12 +97,12 @@ func Main() { // but not other values. p := obj.Getgoarch() - if !strings.HasPrefix(p, Thearch.Thestring) { - log.Fatalf("cannot use %cg with GOARCH=%s", Thearch.Thechar, p) + if !strings.HasPrefix(p, Thearch.LinkArch.Name) { + log.Fatalf("cannot use %cg with GOARCH=%s", Thearch.LinkArch.Family, p) } goarch = p - Ctxt = obj.Linknew(Thearch.Thelinkarch) + Ctxt = obj.Linknew(Thearch.LinkArch) Ctxt.DiagFunc = Yyerror Ctxt.Bso = &bstdout bstdout = *obj.Binitw(os.Stdout) @@ -200,15 +201,13 @@ func Main() { obj.Flagcount("y", "debug declarations in canned imports (with -d)", &Debug['y']) var flag_shared int var flag_dynlink bool - switch Thearch.Thechar { - case '5', '6', '7', '8', '9': + if Thearch.LinkArch.InFamily(sys.ARM, sys.AMD64, sys.ARM64, sys.I386, sys.PPC64) { obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared) } - if Thearch.Thechar == '6' { + if Thearch.LinkArch.Family == sys.AMD64 { obj.Flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel) } - switch Thearch.Thechar { - case '5', '6', '7', '8', '9': + if Thearch.LinkArch.InFamily(sys.ARM, sys.AMD64, sys.ARM64, sys.I386, sys.PPC64) { flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries") } obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile) @@ -301,9 +300,9 @@ func Main() { } Thearch.Betypeinit() - if Widthptr == 0 { - Fatalf("betypeinit failed") - } + Widthint = Thearch.LinkArch.IntSize + Widthptr = Thearch.LinkArch.PtrSize + Widthreg = Thearch.LinkArch.RegSize initUniverse() diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go index 63f7bf825e..bfb65ade38 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -7,6 +7,7 @@ package gc import ( "cmd/compile/internal/ssa" "cmd/internal/obj" + "cmd/internal/sys" "crypto/md5" "fmt" "sort" @@ -286,7 +287,7 @@ func allocauto(ptxt *obj.Prog) { if haspointers(n.Type) { stkptrsize = Stksize } - if Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' { + if Thearch.LinkArch.InFamily(sys.MIPS64, sys.ARM, sys.ARM64, sys.PPC64) { Stksize = Rnd(Stksize, int64(Widthptr)) } if Stksize >= 1<<31 { @@ -323,7 +324,7 @@ func Cgen_checknil(n *Node) { Fatalf("bad checknil") } - if ((Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && n.Op != OREGISTER) || !n.Addable || n.Op == OLITERAL { + if (Thearch.LinkArch.InFamily(sys.MIPS64, sys.ARM, sys.ARM64, sys.PPC64) && n.Op != OREGISTER) || !n.Addable || n.Op == OLITERAL { var reg Node Regalloc(®, Types[Tptr], n) Cgen(n, ®) diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index 43f594e2ea..6e43d3133f 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -17,6 +17,7 @@ package gc import ( "cmd/internal/obj" + "cmd/internal/sys" "fmt" "sort" "strings" @@ -1396,7 +1397,7 @@ func livenessepilogue(lv *Liveness) { // The instruction before a call to deferreturn is always a // no-op, to keep PC-specific data unambiguous. prev := p.Opt.(*obj.Prog) - if Ctxt.Arch.Thechar == '9' { + if Ctxt.Arch.Family == sys.PPC64 { // On ppc64 there is an additional instruction // (another no-op or reload of toc pointer) before // the call. diff --git a/src/cmd/compile/internal/gc/reg.go b/src/cmd/compile/internal/gc/reg.go index 26746a5bcf..8705d6dfa4 100644 --- a/src/cmd/compile/internal/gc/reg.go +++ b/src/cmd/compile/internal/gc/reg.go @@ -33,6 +33,7 @@ package gc import ( "bytes" "cmd/internal/obj" + "cmd/internal/sys" "fmt" "sort" "strings" @@ -249,7 +250,7 @@ func addmove(r *Flow, bn int, rn int, f int) { p1.As = Thearch.Optoas(OAS, Types[uint8(v.etype)]) // TODO(rsc): Remove special case here. - if (Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && v.etype == TBOOL { + if Thearch.LinkArch.InFamily(sys.MIPS64, sys.ARM, sys.ARM64, sys.PPC64) && v.etype == TBOOL { p1.As = Thearch.Optoas(OAS, Types[TUINT8]) } p1.From.Type = obj.TYPE_REG @@ -302,7 +303,7 @@ func mkvar(f *Flow, a *obj.Addr) Bits { // TODO(rsc): Remove special case here. case obj.TYPE_ADDR: var bit Bits - if Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' { + if Thearch.LinkArch.InFamily(sys.MIPS64, sys.ARM, sys.ARM64, sys.PPC64) { goto memcase } a.Type = obj.TYPE_MEM @@ -368,7 +369,7 @@ func mkvar(f *Flow, a *obj.Addr) Bits { if v.etype == et { if int64(v.width) == w { // TODO(rsc): Remove special case for arm here. - if flag == 0 || Thearch.Thechar != '5' { + if flag == 0 || Thearch.LinkArch.Family != sys.ARM { return blsh(uint(i)) } } diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 127a7c4698..90c4d4e95e 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -13,6 +13,7 @@ import ( "cmd/compile/internal/ssa" "cmd/internal/obj" + "cmd/internal/sys" ) var ssaEnabled = true @@ -24,13 +25,13 @@ func initssa() *ssa.Config { ssaExp.unimplemented = false ssaExp.mustImplement = true if ssaConfig == nil { - ssaConfig = ssa.NewConfig(Thearch.Thestring, &ssaExp, Ctxt, Debug['N'] == 0) + ssaConfig = ssa.NewConfig(Thearch.LinkArch.Name, &ssaExp, Ctxt, Debug['N'] == 0) } return ssaConfig } func shouldssa(fn *Node) bool { - switch Thearch.Thestring { + switch Thearch.LinkArch.Name { default: // Only available for testing. if os.Getenv("SSATEST") == "" { @@ -2409,7 +2410,7 @@ func isSSAIntrinsic1(s *Sym) bool { // so far has only been noticed for Bswap32 and the 16-bit count // leading/trailing instructions, but heuristics might change // in the future or on different architectures). - if !ssaEnabled || ssa.IntrinsicsDisable || Thearch.Thechar != '6' { + if !ssaEnabled || ssa.IntrinsicsDisable || Thearch.LinkArch.Family != sys.AMD64 { return false } if s != nil && s.Pkg != nil && s.Pkg.Path == "runtime/internal/sys" { diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index ff8ddea7f6..586a8e9c4f 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -6,6 +6,7 @@ package gc import ( "cmd/internal/obj" + "cmd/internal/sys" "fmt" "strings" ) @@ -672,8 +673,7 @@ opswitch: walkexprlist(n.List.Slice(), init) if n.Left.Op == ONAME && n.Left.Sym.Name == "Sqrt" && n.Left.Sym.Pkg.Path == "math" { - switch Thearch.Thechar { - case '5', '6', '7', '9': + if Thearch.LinkArch.InFamily(sys.AMD64, sys.ARM, sys.ARM64, sys.PPC64) { n.Op = OSQRT n.Left = n.List.First() n.List.Set(nil) @@ -1056,7 +1056,7 @@ opswitch: n = walkexpr(n, init) case OCONV, OCONVNOP: - if Thearch.Thechar == '5' { + if Thearch.LinkArch.Family == sys.ARM { if n.Left.Type.IsFloat() { if n.Type.Etype == TINT64 { n = mkcall("float64toint64", n.Type, init, conv(n.Left, Types[TFLOAT64])) @@ -3274,7 +3274,7 @@ func samecheap(a *Node, b *Node) bool { // The result of walkrotate MUST be assigned back to n, e.g. // n.Left = walkrotate(n.Left) func walkrotate(n *Node) *Node { - if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' { + if Thearch.LinkArch.InFamily(sys.MIPS64, sys.ARM64, sys.PPC64) { return n } @@ -3401,7 +3401,7 @@ func walkdiv(n *Node, init *Nodes) *Node { // if >= 0, nr is 1<= 32678 { ld.Diag("TLS offset out of range %d", v) } diff --git a/src/cmd/link/internal/arm64/l.go b/src/cmd/link/internal/arm64/l.go index b9b7ea50e3..67ad5c977f 100644 --- a/src/cmd/link/internal/arm64/l.go +++ b/src/cmd/link/internal/arm64/l.go @@ -62,11 +62,9 @@ package arm64 // THE SOFTWARE. const ( - thechar = '7' MaxAlign = 32 // max data alignment MinAlign = 1 // min data alignment FuncAlign = 8 - MINLC = 4 ) /* Used by ../internal/ld/dwarf.go */ diff --git a/src/cmd/link/internal/arm64/obj.go b/src/cmd/link/internal/arm64/obj.go index 693e106ff1..1169e79a58 100644 --- a/src/cmd/link/internal/arm64/obj.go +++ b/src/cmd/link/internal/arm64/obj.go @@ -32,6 +32,7 @@ package arm64 import ( "cmd/internal/obj" + "cmd/internal/sys" "cmd/link/internal/ld" "fmt" "log" @@ -45,17 +46,11 @@ func Main() { } func linkarchinit() { - ld.Thestring = obj.Getgoarch() - ld.Thelinkarch = &ld.Linkarm64 + ld.SysArch = sys.ArchARM64 - ld.Thearch.Thechar = thechar - ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize - ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize - ld.Thearch.Regsize = ld.Thelinkarch.Regsize ld.Thearch.Funcalign = FuncAlign ld.Thearch.Maxalign = MaxAlign ld.Thearch.Minalign = MinAlign - ld.Thearch.Minlc = MINLC ld.Thearch.Dwarfregsp = DWARFREGSP ld.Thearch.Dwarfreglr = DWARFREGLR diff --git a/src/cmd/link/internal/ld/arch.go b/src/cmd/link/internal/ld/arch.go deleted file mode 100644 index d28f37fa02..0000000000 --- a/src/cmd/link/internal/ld/arch.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ld - -import "encoding/binary" - -var Linkarm = LinkArch{ - ByteOrder: binary.LittleEndian, - Name: "arm", - Thechar: '5', - Minlc: 4, - Ptrsize: 4, - Regsize: 4, -} - -var Linkarm64 = LinkArch{ - ByteOrder: binary.LittleEndian, - Name: "arm64", - Thechar: '7', - Minlc: 4, - Ptrsize: 8, - Regsize: 8, -} - -var Linkamd64 = LinkArch{ - ByteOrder: binary.LittleEndian, - Name: "amd64", - Thechar: '6', - Minlc: 1, - Ptrsize: 8, - Regsize: 8, -} - -var Linkamd64p32 = LinkArch{ - ByteOrder: binary.LittleEndian, - Name: "amd64p32", - Thechar: '6', - Minlc: 1, - Ptrsize: 4, - Regsize: 8, -} - -var Link386 = LinkArch{ - ByteOrder: binary.LittleEndian, - Name: "386", - Thechar: '8', - Minlc: 1, - Ptrsize: 4, - Regsize: 4, -} - -var Linkppc64 = LinkArch{ - ByteOrder: binary.BigEndian, - Name: "ppc64", - Thechar: '9', - Minlc: 4, - Ptrsize: 8, - Regsize: 8, -} - -var Linkppc64le = LinkArch{ - ByteOrder: binary.LittleEndian, - Name: "ppc64le", - Thechar: '9', - Minlc: 4, - Ptrsize: 8, - Regsize: 8, -} - -var Linkmips64 = LinkArch{ - ByteOrder: binary.BigEndian, - Name: "mips64", - Thechar: '0', - Minlc: 4, - Ptrsize: 8, - Regsize: 8, -} - -var Linkmips64le = LinkArch{ - ByteOrder: binary.LittleEndian, - Name: "mips64le", - Thechar: '0', - Minlc: 4, - Ptrsize: 8, - Regsize: 8, -} - -var Links390x = LinkArch{ - ByteOrder: binary.BigEndian, - Name: "s390x", - Thechar: 'z', - Minlc: 2, - Ptrsize: 8, - Regsize: 8, -} diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 6bbd6c7d5c..ae430b4e45 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -34,6 +34,7 @@ package ld import ( "cmd/internal/gcprog" "cmd/internal/obj" + "cmd/internal/sys" "fmt" "log" "os" @@ -121,7 +122,7 @@ func Adduint64(ctxt *Link, s *LSym, v uint64) int64 { } func adduint(ctxt *Link, s *LSym, v uint64) int64 { - return adduintxx(ctxt, s, v, Thearch.Intsize) + return adduintxx(ctxt, s, v, SysArch.IntSize) } func setuint8(ctxt *Link, s *LSym, r int64, v uint8) int64 { @@ -138,12 +139,12 @@ func Addaddrplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 { } s.Attr |= AttrReachable i := s.Size - s.Size += int64(ctxt.Arch.Ptrsize) + s.Size += int64(ctxt.Arch.PtrSize) Symgrow(ctxt, s, s.Size) r := Addrel(s) r.Sym = t r.Off = int32(i) - r.Siz = uint8(ctxt.Arch.Ptrsize) + r.Siz = uint8(ctxt.Arch.PtrSize) r.Type = obj.R_ADDR r.Add = add return i + int64(r.Siz) @@ -163,7 +164,7 @@ func Addpcrelplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 { r.Add = add r.Type = obj.R_PCREL r.Siz = 4 - if Thearch.Thechar == 'z' { + if SysArch.Family == sys.S390X { r.Variant = RV_390_DBL } return i + int64(r.Siz) @@ -178,15 +179,15 @@ func setaddrplus(ctxt *Link, s *LSym, off int64, t *LSym, add int64) int64 { s.Type = obj.SDATA } s.Attr |= AttrReachable - if off+int64(ctxt.Arch.Ptrsize) > s.Size { - s.Size = off + int64(ctxt.Arch.Ptrsize) + if off+int64(ctxt.Arch.PtrSize) > s.Size { + s.Size = off + int64(ctxt.Arch.PtrSize) Symgrow(ctxt, s, s.Size) } r := Addrel(s) r.Sym = t r.Off = int32(off) - r.Siz = uint8(ctxt.Arch.Ptrsize) + r.Siz = uint8(ctxt.Arch.PtrSize) r.Type = obj.R_ADDR r.Add = add return off + int64(r.Siz) @@ -202,12 +203,12 @@ func addsize(ctxt *Link, s *LSym, t *LSym) int64 { } s.Attr |= AttrReachable i := s.Size - s.Size += int64(ctxt.Arch.Ptrsize) + s.Size += int64(ctxt.Arch.PtrSize) Symgrow(ctxt, s, s.Size) r := Addrel(s) r.Sym = t r.Off = int32(i) - r.Siz = uint8(ctxt.Arch.Ptrsize) + r.Siz = uint8(ctxt.Arch.PtrSize) r.Type = obj.R_SIZE return i + int64(r.Siz) } @@ -356,7 +357,7 @@ func relocsym(s *LSym) { // We need to be able to reference dynimport symbols when linking against // shared libraries, and Solaris needs it always if HEADTYPE != obj.Hsolaris && r.Sym != nil && r.Sym.Type == obj.SDYNIMPORT && !DynlinkingGo() { - if !(Thearch.Thechar == '9' && Linkmode == LinkExternal && r.Sym.Name == ".TOC.") { + if !(SysArch.Family == sys.PPC64 && Linkmode == LinkExternal && r.Sym.Name == ".TOC.") { Diag("unhandled relocation for %s (type %d rtype %d)", r.Sym.Name, r.Sym.Type, r.Type) } } @@ -365,7 +366,7 @@ func relocsym(s *LSym) { } // TODO(mundaym): remove this special case - see issue 14218. - if Thearch.Thechar == 'z' { + if SysArch.Family == sys.S390X { switch r.Type { case obj.R_PCRELDBL: r.Type = obj.R_PCREL @@ -394,7 +395,7 @@ func relocsym(s *LSym) { } case obj.R_TLS_LE: - isAndroidX86 := goos == "android" && (Thearch.Thechar == '6' || Thearch.Thechar == '8') + isAndroidX86 := goos == "android" && (SysArch.InFamily(sys.AMD64, sys.I386)) if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd && !isAndroidX86 { r.Done = 0 @@ -404,13 +405,13 @@ func relocsym(s *LSym) { r.Xsym = r.Sym r.Xadd = r.Add o = 0 - if Thearch.Thechar != '6' { + if SysArch.Family != sys.AMD64 { o = r.Add } break } - if Iself && Thearch.Thechar == '5' { + if Iself && SysArch.Family == sys.ARM { // On ELF ARM, the thread pointer is 8 bytes before // the start of the thread-local data block, so add 8 // to the actual TLS offset (r->sym->value). @@ -428,7 +429,7 @@ func relocsym(s *LSym) { } case obj.R_TLS_IE: - isAndroidX86 := goos == "android" && (Thearch.Thechar == '6' || Thearch.Thechar == '8') + isAndroidX86 := goos == "android" && (SysArch.InFamily(sys.AMD64, sys.I386)) if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd && !isAndroidX86 { r.Done = 0 @@ -438,7 +439,7 @@ func relocsym(s *LSym) { r.Xsym = r.Sym r.Xadd = r.Add o = 0 - if Thearch.Thechar != '6' { + if SysArch.Family != sys.AMD64 { o = r.Add } break @@ -465,7 +466,7 @@ func relocsym(s *LSym) { o = r.Xadd if Iself { - if Thearch.Thechar == '6' { + if SysArch.Family == sys.AMD64 { o = 0 } } else if HEADTYPE == obj.Hdarwin { @@ -475,10 +476,10 @@ func relocsym(s *LSym) { // The workaround is that on arm64 don't ever add symaddr to o and always use // extern relocation by requiring rs->dynid >= 0. if rs.Type != obj.SHOSTOBJ { - if Thearch.Thechar == '7' && rs.Dynid < 0 { + if SysArch.Family == sys.ARM64 && rs.Dynid < 0 { Diag("R_ADDR reloc to %s+%d is not supported on darwin/arm64", rs.Name, o) } - if Thearch.Thechar != '7' { + if SysArch.Family != sys.ARM64 { o += Symaddr(rs) } } @@ -498,7 +499,7 @@ func relocsym(s *LSym) { // fail at runtime. See https://golang.org/issue/7980. // Instead of special casing only amd64, we treat this as an error on all // 64-bit architectures so as to be future-proof. - if int32(o) < 0 && Thearch.Ptrsize > 4 && siz == 4 { + if int32(o) < 0 && SysArch.PtrSize > 4 && siz == 4 { Diag("non-pc-relative relocation address is too big: %#x (%#x + %#x)", uint64(o), Symaddr(r.Sym), r.Add) errorexit() } @@ -515,7 +516,7 @@ func relocsym(s *LSym) { r.Xadd = r.Add + Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr) o = r.Xadd rs = r.Xsym - if Iself && Thearch.Thechar == '6' { + if Iself && SysArch.Family == sys.AMD64 { o = 0 } break @@ -544,7 +545,7 @@ func relocsym(s *LSym) { o = r.Xadd if Iself { - if Thearch.Thechar == '6' { + if SysArch.Family == sys.AMD64 { o = 0 } } else if HEADTYPE == obj.Hdarwin { @@ -556,7 +557,7 @@ func relocsym(s *LSym) { } else { o += int64(r.Siz) } - } else if HEADTYPE == obj.Hwindows && Thearch.Thechar == '6' { // only amd64 needs PCREL + } else if HEADTYPE == obj.Hwindows && SysArch.Family == sys.AMD64 { // only amd64 needs PCREL // PE/COFF's PC32 relocation uses the address after the relocated // bytes as the base. Compensate by skewing the addend. o += int64(r.Siz) @@ -675,7 +676,7 @@ func dynrelocsym(s *LSym) { r.Add = int64(targ.Plt) // jmp *addr - if Thearch.Thechar == '8' { + if SysArch.Family == sys.I386 { Adduint8(Ctxt, rel, 0xff) Adduint8(Ctxt, rel, 0x25) Addaddr(Ctxt, rel, targ) @@ -982,7 +983,7 @@ func addstrdata(name string, value string) { s.Attr |= AttrDuplicateOK reachable := s.Attr.Reachable() Addaddr(Ctxt, s, sp) - adduintxx(Ctxt, s, uint64(len(value)), Thearch.Ptrsize) + adduintxx(Ctxt, s, uint64(len(value)), SysArch.PtrSize) // addstring, addaddr, etc., mark the symbols as reachable. // In this case that is not necessarily true, so stick to what @@ -1128,7 +1129,7 @@ func (p *GCProg) writeByte(x byte) { } func (p *GCProg) End(size int64) { - p.w.ZeroUntil(size / int64(Thearch.Ptrsize)) + p.w.ZeroUntil(size / int64(SysArch.PtrSize)) p.w.End() if debugGCProg { fmt.Fprintf(os.Stderr, "ld: end GCProg\n") @@ -1144,7 +1145,7 @@ func (p *GCProg) AddSym(s *LSym) { return } - ptrsize := int64(Thearch.Ptrsize) + ptrsize := int64(SysArch.PtrSize) nptr := decodetype_ptrdata(typ) / ptrsize if debugGCProg { @@ -1532,7 +1533,7 @@ func dodata() { if s != nil && s.Type == obj.STLSBSS { if Iself && (Linkmode == LinkExternal || Debug['d'] == 0) && HEADTYPE != obj.Hopenbsd { sect = addsection(&Segdata, ".tbss", 06) - sect.Align = int32(Thearch.Ptrsize) + sect.Align = int32(SysArch.PtrSize) sect.Vaddr = 0 } else { sect = nil diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index 56c4370bcc..b17b96001e 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -6,6 +6,7 @@ package ld import ( "cmd/internal/obj" + "cmd/internal/sys" "fmt" "strings" "unicode" @@ -227,7 +228,7 @@ func (d *deadcodepass) markMethod(m methodref) { func (d *deadcodepass) init() { var names []string - if Thearch.Thechar == '5' { + if SysArch.Family == sys.ARM { // mark some functions that are only referenced after linker code editing if d.ctxt.Goarm == 5 { names = append(names, "_sfloat") diff --git a/src/cmd/link/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go index 0a6bf094aa..bc29938590 100644 --- a/src/cmd/link/internal/ld/decodesym.go +++ b/src/cmd/link/internal/ld/decodesym.go @@ -7,6 +7,7 @@ package ld import ( "bytes" "cmd/internal/obj" + "cmd/internal/sys" "debug/elf" "fmt" ) @@ -46,39 +47,39 @@ func decode_inuxi(p []byte, sz int) uint64 { } } -func commonsize() int { return 6*Thearch.Ptrsize + 8 } // runtime._type -func structfieldSize() int { return 3 * Thearch.Ptrsize } // runtime.structfield -func uncommonSize() int { return 2*Thearch.Ptrsize + 2*Thearch.Intsize } // runtime.uncommontype +func commonsize() int { return 6*SysArch.PtrSize + 8 } // runtime._type +func structfieldSize() int { return 3 * SysArch.PtrSize } // runtime.structfield +func uncommonSize() int { return 2*SysArch.PtrSize + 2*SysArch.IntSize } // runtime.uncommontype // Type.commonType.kind func decodetype_kind(s *LSym) uint8 { - return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindMask) // 0x13 / 0x1f + return uint8(s.P[2*SysArch.PtrSize+7] & obj.KindMask) // 0x13 / 0x1f } // Type.commonType.kind func decodetype_noptr(s *LSym) uint8 { - return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindNoPointers) // 0x13 / 0x1f + return uint8(s.P[2*SysArch.PtrSize+7] & obj.KindNoPointers) // 0x13 / 0x1f } // Type.commonType.kind func decodetype_usegcprog(s *LSym) uint8 { - return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindGCProg) // 0x13 / 0x1f + return uint8(s.P[2*SysArch.PtrSize+7] & obj.KindGCProg) // 0x13 / 0x1f } // Type.commonType.size func decodetype_size(s *LSym) int64 { - return int64(decode_inuxi(s.P, Thearch.Ptrsize)) // 0x8 / 0x10 + return int64(decode_inuxi(s.P, SysArch.PtrSize)) // 0x8 / 0x10 } // Type.commonType.ptrdata func decodetype_ptrdata(s *LSym) int64 { - return int64(decode_inuxi(s.P[Thearch.Ptrsize:], Thearch.Ptrsize)) // 0x8 / 0x10 + return int64(decode_inuxi(s.P[SysArch.PtrSize:], SysArch.PtrSize)) // 0x8 / 0x10 } // Type.commonType.tflag func decodetype_hasUncommon(s *LSym) bool { const tflagUncommon = 1 // see ../../../../reflect/type.go:/^type.tflag - return s.P[2*Thearch.Ptrsize+4]&tflagUncommon != 0 + return s.P[2*SysArch.PtrSize+4]&tflagUncommon != 0 } // Find the elf.Section of a given shared library that contains a given address. @@ -112,11 +113,11 @@ func decodetype_gcprog(s *LSym) []byte { Exitf("cannot find gcprog for %s", s.Name) return nil } - return decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize)).P + return decode_reloc_sym(s, 2*int32(SysArch.PtrSize)+8+1*int32(SysArch.PtrSize)).P } func decodetype_gcprog_shlib(s *LSym) uint64 { - if Thearch.Thechar == '7' { + if SysArch.Family == sys.ARM64 { for _, shlib := range Ctxt.Shlibs { if shlib.Path == s.File { return shlib.gcdata_addresses[s] @@ -124,7 +125,7 @@ func decodetype_gcprog_shlib(s *LSym) uint64 { } return 0 } - return decode_inuxi(s.P[2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize):], Thearch.Ptrsize) + return decode_inuxi(s.P[2*int32(SysArch.PtrSize)+8+1*int32(SysArch.PtrSize):], SysArch.PtrSize) } func decodetype_gcmask(s *LSym) []byte { @@ -133,14 +134,14 @@ func decodetype_gcmask(s *LSym) []byte { ptrdata := decodetype_ptrdata(s) sect := findShlibSection(s.File, addr) if sect != nil { - r := make([]byte, ptrdata/int64(Thearch.Ptrsize)) + r := make([]byte, ptrdata/int64(SysArch.PtrSize)) sect.ReadAt(r, int64(addr-sect.Addr)) return r } Exitf("cannot find gcmask for %s", s.Name) return nil } - mask := decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize)) + mask := decode_reloc_sym(s, 2*int32(SysArch.PtrSize)+8+1*int32(SysArch.PtrSize)) return mask.P } @@ -150,7 +151,7 @@ func decodetype_arrayelem(s *LSym) *LSym { } func decodetype_arraylen(s *LSym) int64 { - return int64(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Ptrsize)) + return int64(decode_inuxi(s.P[commonsize()+2*SysArch.PtrSize:], SysArch.PtrSize)) } // Type.PtrType.elem @@ -164,7 +165,7 @@ func decodetype_mapkey(s *LSym) *LSym { } func decodetype_mapvalue(s *LSym) *LSym { - return decode_reloc_sym(s, int32(commonsize())+int32(Thearch.Ptrsize)) // 0x20 / 0x38 + return decode_reloc_sym(s, int32(commonsize())+int32(SysArch.PtrSize)) // 0x20 / 0x38 } // Type.ChanType.elem @@ -188,13 +189,13 @@ func decodetype_funcoutcount(s *LSym) int { func decodetype_funcintype(s *LSym, i int) *LSym { uadd := commonsize() + 4 - if Thearch.Ptrsize == 8 { + if SysArch.PtrSize == 8 { uadd += 4 } if decodetype_hasUncommon(s) { uadd += uncommonSize() } - return decode_reloc_sym(s, int32(uadd+i*Thearch.Ptrsize)) + return decode_reloc_sym(s, int32(uadd+i*SysArch.PtrSize)) } func decodetype_funcouttype(s *LSym, i int) *LSym { @@ -203,11 +204,11 @@ func decodetype_funcouttype(s *LSym, i int) *LSym { // Type.StructType.fields.Slice::length func decodetype_structfieldcount(s *LSym) int { - return int(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Intsize)) + return int(decode_inuxi(s.P[commonsize()+2*SysArch.PtrSize:], SysArch.IntSize)) } func decodetype_structfieldarrayoff(s *LSym, i int) int { - off := commonsize() + 2*Thearch.Ptrsize + 2*Thearch.Intsize + off := commonsize() + 2*SysArch.PtrSize + 2*SysArch.IntSize if decodetype_hasUncommon(s) { off += uncommonSize() } @@ -224,7 +225,7 @@ func decodetype_stringptr(s *LSym, off int) string { if r == nil { // shouldn't happen. return "" } - strlen := int64(decode_inuxi(s.P[Thearch.Ptrsize:], Thearch.Intsize)) + strlen := int64(decode_inuxi(s.P[SysArch.PtrSize:], SysArch.IntSize)) return string(r.Sym.P[r.Add : r.Add+strlen]) } @@ -248,17 +249,17 @@ func decodetype_structfieldname(s *LSym, i int) string { func decodetype_structfieldtype(s *LSym, i int) *LSym { off := decodetype_structfieldarrayoff(s, i) - return decode_reloc_sym(s, int32(off+Thearch.Ptrsize)) + return decode_reloc_sym(s, int32(off+SysArch.PtrSize)) } func decodetype_structfieldoffs(s *LSym, i int) int64 { off := decodetype_structfieldarrayoff(s, i) - return int64(decode_inuxi(s.P[off+2*Thearch.Ptrsize:], Thearch.Intsize)) + return int64(decode_inuxi(s.P[off+2*SysArch.PtrSize:], SysArch.IntSize)) } // InterfaceType.methods.length func decodetype_ifacemethodcount(s *LSym) int64 { - return int64(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Intsize)) + return int64(decode_inuxi(s.P[commonsize()+2*SysArch.PtrSize:], SysArch.IntSize)) } // methodsig is a fully qualified typed method signature, like @@ -288,7 +289,7 @@ func decode_methodsig(s *LSym, off, size, count int) []methodsig { var methods []methodsig for i := 0; i < count; i++ { buf.WriteString(decodetype_name(s, off)) - mtypSym := decode_reloc_sym(s, int32(off+Thearch.Ptrsize)) + mtypSym := decode_reloc_sym(s, int32(off+SysArch.PtrSize)) buf.WriteRune('(') inCount := decodetype_funcincount(mtypSym) @@ -319,7 +320,7 @@ func decodetype_ifacemethods(s *LSym) []methodsig { if decodetype_kind(s)&kindMask != kindInterface { panic(fmt.Sprintf("symbol %q is not an interface", s.Name)) } - r := decode_reloc(s, int32(commonsize()+Thearch.Ptrsize)) + r := decode_reloc(s, int32(commonsize()+SysArch.PtrSize)) if r == nil { return nil } @@ -328,7 +329,7 @@ func decodetype_ifacemethods(s *LSym) []methodsig { } off := int(r.Add) // array of reflect.imethod values numMethods := int(decodetype_ifacemethodcount(s)) - sizeofIMethod := 2 * Thearch.Ptrsize + sizeofIMethod := 2 * SysArch.PtrSize return decode_methodsig(s, off, sizeofIMethod, numMethods) } @@ -339,31 +340,31 @@ func decodetype_methods(s *LSym) []methodsig { off := commonsize() // reflect.rtype switch decodetype_kind(s) & kindMask { case kindStruct: // reflect.structType - off += 2*Thearch.Ptrsize + 2*Thearch.Intsize + off += 2*SysArch.PtrSize + 2*SysArch.IntSize case kindPtr: // reflect.ptrType - off += Thearch.Ptrsize + off += SysArch.PtrSize case kindFunc: // reflect.funcType - off += Thearch.Ptrsize // 4 bytes, pointer aligned + off += SysArch.PtrSize // 4 bytes, pointer aligned case kindSlice: // reflect.sliceType - off += Thearch.Ptrsize + off += SysArch.PtrSize case kindArray: // reflect.arrayType - off += 3 * Thearch.Ptrsize + off += 3 * SysArch.PtrSize case kindChan: // reflect.chanType - off += 2 * Thearch.Ptrsize + off += 2 * SysArch.PtrSize case kindMap: // reflect.mapType - off += 4*Thearch.Ptrsize + 8 + off += 4*SysArch.PtrSize + 8 case kindInterface: // reflect.interfaceType - off += Thearch.Ptrsize + 2*Thearch.Intsize + off += SysArch.PtrSize + 2*SysArch.IntSize default: // just Sizeof(rtype) } - numMethods := int(decode_inuxi(s.P[off+2*Thearch.Ptrsize:], Thearch.Intsize)) - r := decode_reloc(s, int32(off+Thearch.Ptrsize)) + numMethods := int(decode_inuxi(s.P[off+2*SysArch.PtrSize:], SysArch.IntSize)) + r := decode_reloc(s, int32(off+SysArch.PtrSize)) if r.Sym != s { panic(fmt.Sprintf("method slice pointer in %s leads to a different symbol %s", s, r.Sym)) } off = int(r.Add) // array of reflect.method values - sizeofMethod := 4 * Thearch.Ptrsize // sizeof reflect.method in program + sizeofMethod := 4 * SysArch.PtrSize // sizeof reflect.method in program return decode_methodsig(s, off, sizeofMethod, numMethods) } diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index eaa0bdbb41..230d146877 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -39,7 +39,7 @@ var gdbscript string * Basic I/O */ func addrput(s *LSym, addr int64) { - switch Thearch.Ptrsize { + switch SysArch.PtrSize { case 4: Adduint32(Ctxt, s, uint32(addr)) @@ -569,7 +569,7 @@ func adddwarfref(ctxt *Link, s *LSym, t *LSym, size int) int64 { default: Diag("invalid size %d in adddwarfref\n", size) fallthrough - case Thearch.Ptrsize: + case SysArch.PtrSize: result = Addaddr(ctxt, s, t) case 4: result = addaddrplus4(ctxt, s, t, 0) @@ -599,7 +599,7 @@ func putattr(s *LSym, abbrev int, form int, cls int, value int64, data interface case DW_FORM_block1: // block if cls == DW_CLS_ADDRESS { - Adduint8(Ctxt, s, uint8(1+Thearch.Ptrsize)) + Adduint8(Ctxt, s, uint8(1+SysArch.PtrSize)) Adduint8(Ctxt, s, DW_OP_addr) Addaddr(Ctxt, s, data.(*LSym)) break @@ -682,14 +682,14 @@ func putattr(s *LSym, abbrev int, form int, cls int, value int64, data interface case DW_FORM_ref_addr: // reference to a DIE in the .info section if data == nil { Diag("dwarf: null reference in %d", abbrev) - if Thearch.Ptrsize == 8 { + if SysArch.PtrSize == 8 { Adduint64(Ctxt, s, 0) // invalid dwarf, gdb will complain. } else { Adduint32(Ctxt, s, 0) // invalid dwarf, gdb will complain. } } else { dsym := data.(*LSym) - adddwarfref(Ctxt, s, dsym, Thearch.Ptrsize) + adddwarfref(Ctxt, s, dsym, SysArch.PtrSize) } case DW_FORM_ref1, // reference within the compilation unit @@ -1161,11 +1161,11 @@ func synthesizemaptypes(die *DWDie) { // compute size info like hashmap.c does. indirect_key, indirect_val := false, false if keysize > MaxKeySize { - keysize = int64(Thearch.Ptrsize) + keysize = int64(SysArch.PtrSize) indirect_key = true } if valsize > MaxValSize { - valsize = int64(Thearch.Ptrsize) + valsize = int64(SysArch.PtrSize) indirect_val = true } @@ -1212,13 +1212,13 @@ func synthesizemaptypes(die *DWDie) { fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "overflow", 0) newrefattr(fld, DW_AT_type, defptrto(dwhb.sym)) newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))) - if Thearch.Regsize > Thearch.Ptrsize { + if SysArch.RegSize > SysArch.PtrSize { fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "pad", 0) newrefattr(fld, DW_AT_type, mustFind("uintptr")) - newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(Thearch.Ptrsize)) + newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(SysArch.PtrSize)) } - newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize+BucketSize*int64(keysize)+BucketSize*int64(valsize)+int64(Thearch.Regsize), 0) + newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize+BucketSize*int64(keysize)+BucketSize*int64(valsize)+int64(SysArch.RegSize), 0) }) // Construct hash @@ -1481,7 +1481,7 @@ func writelines(prev *LSym) *LSym { headerend = ls.Size Adduint8(Ctxt, ls, 0) // start extended opcode - uleb128put(ls, 1+int64(Thearch.Ptrsize)) + uleb128put(ls, 1+int64(SysArch.PtrSize)) Adduint8(Ctxt, ls, DW_LNE_set_address) pc := s.Value @@ -1555,7 +1555,7 @@ func writelines(prev *LSym) *LSym { dt = DW_ABRV_AUTO offs = int64(a.Aoffset) if !haslinkregister() { - offs -= int64(Thearch.Ptrsize) + offs -= int64(SysArch.PtrSize) } case obj.A_PARAM: @@ -1667,7 +1667,7 @@ func writeframes(prev *LSym) *LSym { if haslinkregister() { uleb128put(fs, int64(0)) // offset } else { - uleb128put(fs, int64(Thearch.Ptrsize)) // offset + uleb128put(fs, int64(SysArch.PtrSize)) // offset } Adduint8(Ctxt, fs, DW_CFA_offset_extended) @@ -1675,7 +1675,7 @@ func writeframes(prev *LSym) *LSym { if haslinkregister() { uleb128put(fs, int64(0)/DATAALIGNMENTFACTOR) // at cfa - 0 } else { - uleb128put(fs, int64(-Thearch.Ptrsize)/DATAALIGNMENTFACTOR) // at cfa - x*4 + uleb128put(fs, int64(-SysArch.PtrSize)/DATAALIGNMENTFACTOR) // at cfa - x*4 } // 4 is to exclude the length field. @@ -1713,10 +1713,10 @@ func writeframes(prev *LSym) *LSym { if haslinkregister() { deltaBuf = appendPCDeltaCFA(deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(pcsp.value)) } else { - deltaBuf = appendPCDeltaCFA(deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(Thearch.Ptrsize)+int64(pcsp.value)) + deltaBuf = appendPCDeltaCFA(deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(SysArch.PtrSize)+int64(pcsp.value)) } } - pad := int(Rnd(int64(len(deltaBuf)), int64(Thearch.Ptrsize))) - len(deltaBuf) + pad := int(Rnd(int64(len(deltaBuf)), int64(SysArch.PtrSize))) - len(deltaBuf) deltaBuf = append(deltaBuf, zeros[:pad]...) // Emit the FDE header, Section 6.4.1. @@ -1724,7 +1724,7 @@ func writeframes(prev *LSym) *LSym { // 4 bytes: Pointer to the CIE above, at offset 0 // ptrsize: initial location // ptrsize: address range - Adduint32(Ctxt, fs, uint32(4+2*Thearch.Ptrsize+len(deltaBuf))) // length (excludes itself) + Adduint32(Ctxt, fs, uint32(4+2*SysArch.PtrSize+len(deltaBuf))) // length (excludes itself) if Linkmode == LinkExternal { adddwarfref(Ctxt, fs, framesec, 4) } else { @@ -1771,7 +1771,7 @@ func writeinfo(prev *LSym) *LSym { // debug_abbrev_offset (*) adddwarfref(Ctxt, s, abbrevsym, 4) - Adduint8(Ctxt, s, uint8(Thearch.Ptrsize)) // address_size + Adduint8(Ctxt, s, uint8(SysArch.PtrSize)) // address_size prev = putdie(prev, compunit) cusize := s.Size - 4 // exclude the length field. @@ -1848,7 +1848,7 @@ func writearanges(prev *LSym) *LSym { s.Type = obj.SDWARFSECT // The first tuple is aligned to a multiple of the size of a single tuple // (twice the size of an address) - headersize := int(Rnd(4+2+4+1+1, int64(Thearch.Ptrsize*2))) // don't count unit_length field itself + headersize := int(Rnd(4+2+4+1+1, int64(SysArch.PtrSize*2))) // don't count unit_length field itself for compunit := dwroot.child; compunit != nil; compunit = compunit.link { b := getattr(compunit, DW_AT_low_pc) @@ -1861,13 +1861,13 @@ func writearanges(prev *LSym) *LSym { } // Write .debug_aranges Header + entry (sec 6.1.2) - unitlength := uint32(headersize) + 4*uint32(Thearch.Ptrsize) - 4 + unitlength := uint32(headersize) + 4*uint32(SysArch.PtrSize) - 4 Adduint32(Ctxt, s, unitlength) // unit_length (*) Adduint16(Ctxt, s, 2) // dwarf version (appendix F) adddwarfref(Ctxt, s, compunit.sym, 4) - Adduint8(Ctxt, s, uint8(Thearch.Ptrsize)) // address_size + Adduint8(Ctxt, s, uint8(SysArch.PtrSize)) // address_size Adduint8(Ctxt, s, 0) // segment_size padding := headersize - (4 + 2 + 4 + 1 + 1) for i := 0; i < padding; i++ { @@ -1940,7 +1940,7 @@ func dwarfgeneratedebugsyms() { die := newdie(&dwtypes, DW_ABRV_BASETYPE, "uintptr", 0) // needed for array size newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0) - newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, int64(Thearch.Ptrsize), 0) + newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, int64(SysArch.PtrSize), 0) newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, obj.KindUintptr, 0) // Prototypes needed for type synthesis. diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index 035826df7c..7c760775b5 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -6,6 +6,7 @@ package ld import ( "cmd/internal/obj" + "cmd/internal/sys" "crypto/sha1" "encoding/binary" "encoding/hex" @@ -866,25 +867,23 @@ var buildinfo []byte func Elfinit() { Iself = true - switch Thearch.Thechar { - case '0', '6', '7', '9', 'z': + if SysArch.InFamily(sys.AMD64, sys.ARM64, sys.MIPS64, sys.PPC64, sys.S390X) { elfRelType = ".rela" - default: + } else { elfRelType = ".rel" } - switch Thearch.Thechar { + switch SysArch.Family { // 64-bit architectures - case '9', 'z': + case sys.PPC64, sys.S390X: if Ctxt.Arch.ByteOrder == binary.BigEndian { ehdr.flags = 1 /* Version 1 ABI */ } else { ehdr.flags = 2 /* Version 2 ABI */ } fallthrough - - case '0', '6', '7': - if Thearch.Thechar == '0' { + case sys.AMD64, sys.ARM64, sys.MIPS64: + if SysArch.Family == sys.MIPS64 { ehdr.flags = 0x20000000 /* MIPS 3 */ } elf64 = true @@ -897,7 +896,7 @@ func Elfinit() { // we use EABI on both linux/arm and freebsd/arm. // 32-bit architectures - case '5': + case sys.ARM: // we use EABI on both linux/arm and freebsd/arm. if HEADTYPE == obj.Hlinux || HEADTYPE == obj.Hfreebsd { // We set a value here that makes no indication of which @@ -911,7 +910,6 @@ func Elfinit() { ehdr.flags = 0x5000002 // has entry point, Version5 EABI } fallthrough - default: ehdr.phoff = ELF32HDRSIZE /* Must be be ELF32HDRSIZE: first PHdr must follow ELF header */ @@ -1432,7 +1430,7 @@ func elfdynhash() { } // s390x (ELF64) hash table entries are 8 bytes - if Thearch.Thechar == 'z' { + if SysArch.Family == sys.S390X { Adduint64(Ctxt, s, uint64(nbucket)) Adduint64(Ctxt, s, uint64(nsym)) for i := 0; i < nbucket; i++ { @@ -1660,15 +1658,15 @@ func elfshreloc(sect *Section) *ElfShdr { sh := elfshname(elfRelType + sect.Name) sh.type_ = uint32(typ) - sh.entsize = uint64(Thearch.Regsize) * 2 + sh.entsize = uint64(SysArch.RegSize) * 2 if typ == SHT_RELA { - sh.entsize += uint64(Thearch.Regsize) + sh.entsize += uint64(SysArch.RegSize) } sh.link = uint32(elfshname(".symtab").shnum) sh.info = uint32(sect.Elfsect.shnum) sh.off = sect.Reloff sh.size = sect.Rellen - sh.addralign = uint64(Thearch.Regsize) + sh.addralign = uint64(SysArch.RegSize) return sh } @@ -1872,7 +1870,7 @@ func doelf() { Addstring(shstrtab, ".interp") Addstring(shstrtab, ".hash") Addstring(shstrtab, ".got") - if Thearch.Thechar == '9' { + if SysArch.Family == sys.PPC64 { Addstring(shstrtab, ".glink") } Addstring(shstrtab, ".got.plt") @@ -1919,7 +1917,7 @@ func doelf() { s.Type = obj.SELFGOT // writable /* ppc64 glink resolver */ - if Thearch.Thechar == '9' { + if SysArch.Family == sys.PPC64 { s := Linklookup(Ctxt, ".glink", 0) s.Attr |= AttrReachable s.Type = obj.SELFRXSECT @@ -1938,7 +1936,7 @@ func doelf() { s = Linklookup(Ctxt, ".plt", 0) s.Attr |= AttrReachable - if Thearch.Thechar == '9' { + if SysArch.Family == sys.PPC64 { // In the ppc64 ABI, .plt is a data section // written by the dynamic linker. s.Type = obj.SELFSECT @@ -1993,15 +1991,15 @@ func doelf() { Elfwritedynent(s, DT_RUNPATH, uint64(Addstring(dynstr, rpath.val))) } - if Thearch.Thechar == '9' { + if SysArch.Family == sys.PPC64 { elfwritedynentsym(s, DT_PLTGOT, Linklookup(Ctxt, ".plt", 0)) - } else if Thearch.Thechar == 'z' { + } else if SysArch.Family == sys.S390X { elfwritedynentsym(s, DT_PLTGOT, Linklookup(Ctxt, ".got", 0)) } else { elfwritedynentsym(s, DT_PLTGOT, Linklookup(Ctxt, ".got.plt", 0)) } - if Thearch.Thechar == '9' { + if SysArch.Family == sys.PPC64 { Elfwritedynent(s, DT_PPC64_OPT, 0) } @@ -2080,22 +2078,22 @@ func Asmbelfsetup() { func Asmbelf(symo int64) { eh := getElfEhdr() - switch Thearch.Thechar { + switch SysArch.Family { default: - Exitf("unknown architecture in asmbelf: %v", Thearch.Thechar) - case '0': + Exitf("unknown architecture in asmbelf: %v", SysArch.Family) + case sys.MIPS64: eh.machine = EM_MIPS - case '5': + case sys.ARM: eh.machine = EM_ARM - case '6': + case sys.AMD64: eh.machine = EM_X86_64 - case '7': + case sys.ARM64: eh.machine = EM_AARCH64 - case '8': + case sys.I386: eh.machine = EM_386 - case '9': + case sys.PPC64: eh.machine = EM_PPC64 - case 'z': + case sys.S390X: eh.machine = EM_S390 } @@ -2251,7 +2249,7 @@ func Asmbelf(symo int64) { } else { sh.entsize = ELF32SYMSIZE } - sh.addralign = uint64(Thearch.Regsize) + sh.addralign = uint64(SysArch.RegSize) sh.link = uint32(elfshname(".dynstr").shnum) // sh->info = index of first non-local symbol (number of local symbols) @@ -2275,7 +2273,7 @@ func Asmbelf(symo int64) { sh = elfshname(".gnu.version_r") sh.type_ = SHT_GNU_VERNEED sh.flags = SHF_ALLOC - sh.addralign = uint64(Thearch.Regsize) + sh.addralign = uint64(SysArch.RegSize) sh.info = uint32(elfverneed) sh.link = uint32(elfshname(".dynstr").shnum) shsym(sh, Linklookup(Ctxt, ".gnu.version_r", 0)) @@ -2286,7 +2284,7 @@ func Asmbelf(symo int64) { sh.type_ = SHT_RELA sh.flags = SHF_ALLOC sh.entsize = ELF64RELASIZE - sh.addralign = uint64(Thearch.Regsize) + sh.addralign = uint64(SysArch.RegSize) sh.link = uint32(elfshname(".dynsym").shnum) sh.info = uint32(elfshname(".plt").shnum) shsym(sh, Linklookup(Ctxt, ".rela.plt", 0)) @@ -2350,15 +2348,15 @@ func Asmbelf(symo int64) { sh := elfshname(".got") sh.type_ = SHT_PROGBITS sh.flags = SHF_ALLOC + SHF_WRITE - sh.entsize = uint64(Thearch.Regsize) - sh.addralign = uint64(Thearch.Regsize) + sh.entsize = uint64(SysArch.RegSize) + sh.addralign = uint64(SysArch.RegSize) shsym(sh, Linklookup(Ctxt, ".got", 0)) sh = elfshname(".got.plt") sh.type_ = SHT_PROGBITS sh.flags = SHF_ALLOC + SHF_WRITE - sh.entsize = uint64(Thearch.Regsize) - sh.addralign = uint64(Thearch.Regsize) + sh.entsize = uint64(SysArch.RegSize) + sh.addralign = uint64(SysArch.RegSize) shsym(sh, Linklookup(Ctxt, ".got.plt", 0)) } @@ -2366,7 +2364,7 @@ func Asmbelf(symo int64) { sh.type_ = SHT_HASH sh.flags = SHF_ALLOC sh.entsize = 4 - sh.addralign = uint64(Thearch.Regsize) + sh.addralign = uint64(SysArch.RegSize) sh.link = uint32(elfshname(".dynsym").shnum) shsym(sh, Linklookup(Ctxt, ".hash", 0)) @@ -2375,8 +2373,8 @@ func Asmbelf(symo int64) { sh.type_ = SHT_DYNAMIC sh.flags = SHF_ALLOC + SHF_WRITE - sh.entsize = 2 * uint64(Thearch.Regsize) - sh.addralign = uint64(Thearch.Regsize) + sh.entsize = 2 * uint64(SysArch.RegSize) + sh.addralign = uint64(SysArch.RegSize) sh.link = uint32(elfshname(".dynstr").shnum) shsym(sh, Linklookup(Ctxt, ".dynamic", 0)) ph := newElfPhdr() @@ -2402,7 +2400,7 @@ func Asmbelf(symo int64) { ph.type_ = PT_TLS ph.flags = PF_R ph.memsz = tlssize - ph.align = uint64(Thearch.Regsize) + ph.align = uint64(SysArch.RegSize) } } } @@ -2411,12 +2409,12 @@ func Asmbelf(symo int64) { ph := newElfPhdr() ph.type_ = PT_GNU_STACK ph.flags = PF_W + PF_R - ph.align = uint64(Thearch.Regsize) + ph.align = uint64(SysArch.RegSize) ph = newElfPhdr() ph.type_ = PT_PAX_FLAGS ph.flags = 0x2a00 // mprotect, randexec, emutramp disabled - ph.align = uint64(Thearch.Regsize) + ph.align = uint64(SysArch.RegSize) } elfobj: @@ -2476,8 +2474,8 @@ elfobj: sh.type_ = SHT_SYMTAB sh.off = uint64(symo) sh.size = uint64(Symsize) - sh.addralign = uint64(Thearch.Regsize) - sh.entsize = 8 + 2*uint64(Thearch.Regsize) + sh.addralign = uint64(SysArch.RegSize) + sh.entsize = 8 + 2*uint64(SysArch.RegSize) sh.link = uint32(elfshname(".strtab").shnum) sh.info = uint32(elfglobalsymndx) @@ -2600,7 +2598,7 @@ func Elfadddynsym(ctxt *Link, s *LSym) { /* size of object */ Adduint64(ctxt, d, uint64(s.Size)) - if Thearch.Thechar == '6' && !s.Attr.CgoExportDynamic() && s.Dynimplib != "" && !seenlib[s.Dynimplib] { + if SysArch.Family == sys.AMD64 && !s.Attr.CgoExportDynamic() && s.Dynimplib != "" && !seenlib[s.Dynimplib] { Elfwritedynent(Linklookup(ctxt, ".dynamic", 0), DT_NEEDED, uint64(Addstring(Linklookup(ctxt, ".dynstr", 0), s.Dynimplib))) } } else { @@ -2628,9 +2626,9 @@ func Elfadddynsym(ctxt *Link, s *LSym) { t := STB_GLOBAL << 4 // TODO(mwhudson): presumably the behaviour should actually be the same on both arm and 386. - if Thearch.Thechar == '8' && s.Attr.CgoExport() && s.Type&obj.SMASK == obj.STEXT { + if SysArch.Family == sys.I386 && s.Attr.CgoExport() && s.Type&obj.SMASK == obj.STEXT { t |= STT_FUNC - } else if Thearch.Thechar == '5' && s.Attr.CgoExportDynamic() && s.Type&obj.SMASK == obj.STEXT { + } else if SysArch.Family == sys.ARM && s.Attr.CgoExportDynamic() && s.Type&obj.SMASK == obj.STEXT { t |= STT_FUNC } else { t |= STT_OBJECT diff --git a/src/cmd/link/internal/ld/ldelf.go b/src/cmd/link/internal/ld/ldelf.go index 0255331ac6..3aee2d5ece 100644 --- a/src/cmd/link/internal/ld/ldelf.go +++ b/src/cmd/link/internal/ld/ldelf.go @@ -3,6 +3,7 @@ package ld import ( "bytes" "cmd/internal/obj" + "cmd/internal/sys" "encoding/binary" "fmt" "io" @@ -546,47 +547,48 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) { return } - switch Thearch.Thechar { + switch SysArch.Family { default: - Diag("%s: elf %s unimplemented", pn, Thestring) + Diag("%s: elf %s unimplemented", pn, SysArch.Name) return - case '0': + case sys.MIPS64: if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 { Diag("%s: elf object but not mips64", pn) return } - case '5': + case sys.ARM: if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 { Diag("%s: elf object but not arm", pn) return } - case '6': + case sys.AMD64: if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 { Diag("%s: elf object but not amd64", pn) return } - case '7': + case sys.ARM64: if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 { Diag("%s: elf object but not arm64", pn) return } - case '8': + case sys.I386: if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 { Diag("%s: elf object but not 386", pn) return } - case '9': + case sys.PPC64: if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 { Diag("%s: elf object but not ppc64", pn) return } - case 'z': + + case sys.S390X: if elfobj.machine != ElfMachS390 || hdr.Ident[4] != ElfClass64 { Diag("%s: elf object but not s390x", pn) return @@ -1056,7 +1058,7 @@ func readelfsym(elfobj *ElfObj, i int, sym *ElfSym, needSym int) (err error) { } case ElfSymBindLocal: - if Thearch.Thechar == '5' && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) { + if SysArch.Family == sys.ARM && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) { // binutils for arm generate these mapping // symbols, ignore these break @@ -1127,7 +1129,9 @@ func (x rbyoff) Less(i, j int) bool { } func reltype(pn string, elftype int, siz *uint8) int { - switch uint32(Thearch.Thechar) | uint32(elftype)<<24 { + // TODO(mdempsky): Remove dependency on ArchFamily char values. + + switch uint32(SysArch.Family) | uint32(elftype)<<24 { default: Diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype) fallthrough diff --git a/src/cmd/link/internal/ld/ldmacho.go b/src/cmd/link/internal/ld/ldmacho.go index c4c13f13b9..9fbb2123af 100644 --- a/src/cmd/link/internal/ld/ldmacho.go +++ b/src/cmd/link/internal/ld/ldmacho.go @@ -2,6 +2,7 @@ package ld import ( "cmd/internal/obj" + "cmd/internal/sys" "encoding/binary" "fmt" "log" @@ -471,18 +472,18 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) { m.length = length m.name = pn - switch Thearch.Thechar { + switch SysArch.Family { default: - Diag("%s: mach-o %s unimplemented", pn, Thestring) + Diag("%s: mach-o %s unimplemented", pn, SysArch.Name) return - case '6': + case sys.AMD64: if e != binary.LittleEndian || m.cputype != LdMachoCpuAmd64 { Diag("%s: mach-o object but not amd64", pn) return } - case '8': + case sys.I386: if e != binary.LittleEndian || m.cputype != LdMachoCpu386 { Diag("%s: mach-o object but not 386", pn) return @@ -724,10 +725,9 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) { rp = &r[rpi] rel = §.rel[j] if rel.scattered != 0 { - if Thearch.Thechar != '8' { + if SysArch.Family != sys.I386 { // mach-o only uses scattered relocation on 32-bit platforms Diag("unexpected scattered relocation") - continue } @@ -821,7 +821,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) { rp.Off = int32(rel.addr) // Handle X86_64_RELOC_SIGNED referencing a section (rel->extrn == 0). - if Thearch.Thechar == '6' && rel.extrn == 0 && rel.type_ == 1 { + if SysArch.Family == sys.AMD64 && rel.extrn == 0 && rel.type_ == 1 { // Calculate the addend as the offset into the section. // // The rip-relative offset stored in the object file is encoded @@ -847,7 +847,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) { // For i386 Mach-O PC-relative, the addend is written such that // it *is* the PC being subtracted. Use that to make // it match our version of PC-relative. - if rel.pcrel != 0 && Thearch.Thechar == '8' { + if rel.pcrel != 0 && SysArch.Family == sys.I386 { rp.Add += int64(rp.Off) + int64(rp.Siz) } if rel.extrn == 0 { @@ -866,7 +866,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) { // include that information in the addend. // We only care about the delta from the // section base. - if Thearch.Thechar == '8' { + if SysArch.Family == sys.I386 { rp.Add -= int64(c.seg.sect[rel.symnum-1].addr) } } else { diff --git a/src/cmd/link/internal/ld/ldpe.go b/src/cmd/link/internal/ld/ldpe.go index 5c3e99c44f..ea0c482838 100644 --- a/src/cmd/link/internal/ld/ldpe.go +++ b/src/cmd/link/internal/ld/ldpe.go @@ -6,6 +6,7 @@ package ld import ( "cmd/internal/obj" + "cmd/internal/sys" "encoding/binary" "fmt" "log" @@ -492,7 +493,7 @@ func readpesym(peobj *PeObj, i int, y **PeSym) (err error) { if strings.HasPrefix(name, "__imp_") { name = name[6:] // __imp_Name => Name } - if Thearch.Thechar == '8' && name[0] == '_' { + if SysArch.Family == sys.I386 && name[0] == '_' { name = name[1:] // _Name => Name } } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 5616700445..3e0bd8ebc4 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -34,6 +34,7 @@ import ( "bufio" "bytes" "cmd/internal/obj" + "cmd/internal/sys" "crypto/sha1" "debug/elf" "encoding/binary" @@ -82,14 +83,9 @@ import ( // THE SOFTWARE. type Arch struct { - Thechar int - Ptrsize int - Intsize int - Regsize int Funcalign int Maxalign int Minalign int - Minlc int Dwarfregsp int Dwarfreglr int Linuxdynld string @@ -191,8 +187,7 @@ func UseRelro() bool { } var ( - Thestring string - Thelinkarch *LinkArch + SysArch *sys.Arch outfile string dynexp []*LSym dynlib []string @@ -509,7 +504,7 @@ func loadlib() { } loadinternal("runtime") - if Thearch.Thechar == '5' { + if SysArch.Family == sys.ARM { loadinternal("math") } if flag_race != 0 { @@ -562,7 +557,7 @@ func loadlib() { // dependency problems when compiling natively (external linking requires // runtime/cgo, runtime/cgo requires cmd/cgo, but cmd/cgo needs to be // compiled using external linking.) - if (Thearch.Thechar == '5' || Thearch.Thechar == '7') && HEADTYPE == obj.Hdarwin && iscgo { + if SysArch.InFamily(sys.ARM, sys.ARM64) && HEADTYPE == obj.Hdarwin && iscgo { Linkmode = LinkExternal } @@ -621,7 +616,7 @@ func loadlib() { // a variable to hold g in assembly (currently only intel). if tlsg.Type == 0 { tlsg.Type = obj.STLSBSS - tlsg.Size = int64(Thearch.Ptrsize) + tlsg.Size = int64(SysArch.PtrSize) } else if tlsg.Type != obj.SDYNIMPORT { Diag("internal error: runtime declared tlsg variable %d", tlsg.Type) } @@ -639,7 +634,7 @@ func loadlib() { // In addition, on ARM, the runtime depends on the linker // recording the value of GOARM. - if Thearch.Thechar == '5' { + if SysArch.Family == sys.ARM { s := Linklookup(Ctxt, "runtime.goarm", 0) s.Type = obj.SRODATA @@ -1226,7 +1221,7 @@ func hostlink() { if Debug['s'] == 0 && debug_s == 0 && HEADTYPE == obj.Hdarwin { // Skip combining dwarf on arm. - if Thearch.Thechar != '5' && Thearch.Thechar != '7' { + if !SysArch.InFamily(sys.ARM, sys.ARM64) { dsym := filepath.Join(tmpdir, "go.dwarf") if out, err := exec.Command("dsymutil", "-f", outfile, "-o", dsym).CombinedOutput(); err != nil { Ctxt.Cursym = nil @@ -1254,14 +1249,14 @@ func hostlink() { // hostlinkArchArgs returns arguments to pass to the external linker // based on the architecture. func hostlinkArchArgs() []string { - switch Thearch.Thechar { - case '8': + switch SysArch.Family { + case sys.I386: return []string{"-m32"} - case '6', '9', 'z': + case sys.AMD64, sys.PPC64, sys.S390X: return []string{"-m64"} - case '5': + case sys.ARM: return []string{"-marm"} - case '7': + case sys.ARM64: // nothing needed } return nil @@ -1306,10 +1301,10 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when if !strings.HasPrefix(line, "go object ") { if strings.HasSuffix(pn, ".go") { - Exitf("%cl: input %s is not .%c file (use %cg to compile .go files)", Thearch.Thechar, pn, Thearch.Thechar, Thearch.Thechar) + Exitf("%cl: input %s is not .%c file (use %cg to compile .go files)", SysArch.Family, pn, SysArch.Family, SysArch.Family) } - if line == Thestring { + if line == SysArch.Name { // old header format: just $GOOS Diag("%s: stale object file", pn) return nil @@ -1500,12 +1495,12 @@ func ldshlibsyms(shlib string) { // the type data. if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") { lsym.P = readelfsymboldata(f, &elfsym) - gcdata_locations[elfsym.Value+2*uint64(Thearch.Ptrsize)+8+1*uint64(Thearch.Ptrsize)] = lsym + gcdata_locations[elfsym.Value+2*uint64(SysArch.PtrSize)+8+1*uint64(SysArch.PtrSize)] = lsym } } } gcdata_addresses := make(map[*LSym]uint64) - if Thearch.Thechar == '7' { + if SysArch.Family == sys.ARM64 { for _, sect := range f.Sections { if sect.Type == elf.SHT_RELA { var rela elf.Rela64 @@ -1565,8 +1560,8 @@ func mywhatsys() { goos = obj.Getgoos() goarch = obj.Getgoarch() - if !strings.HasPrefix(goarch, Thestring) { - log.Fatalf("cannot use %cc with GOARCH=%s", Thearch.Thechar, goarch) + if !strings.HasPrefix(goarch, SysArch.Name) { + log.Fatalf("cannot use %cc with GOARCH=%s", SysArch.Family, goarch) } } @@ -1608,7 +1603,7 @@ func addsection(seg *Segment, name string, rwx int) *Section { sect.Rwx = uint8(rwx) sect.Name = name sect.Seg = seg - sect.Align = int32(Thearch.Ptrsize) // everything is at least pointer-aligned + sect.Align = int32(SysArch.PtrSize) // everything is at least pointer-aligned *l = sect return sect } @@ -1652,7 +1647,7 @@ func callsize() int { if haslinkregister() { return 0 } - return Thearch.Regsize + return SysArch.RegSize } func dostkcheck() { @@ -1986,7 +1981,7 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) { put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), s.Gotype) // NOTE(ality): acid can't produce a stack trace without .frame symbols - put(nil, ".frame", 'm', int64(s.Locals)+int64(Thearch.Ptrsize), 0, 0, nil) + put(nil, ".frame", 'm', int64(s.Locals)+int64(SysArch.PtrSize), 0, 0, nil) for _, a := range s.Autom { // Emit a or p according to actual offset, even if label is wrong. @@ -1999,7 +1994,7 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) { if a.Name == obj.A_PARAM { off = a.Aoffset } else { - off = a.Aoffset - int32(Thearch.Ptrsize) + off = a.Aoffset - int32(SysArch.PtrSize) } // FP @@ -2009,8 +2004,8 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) { } // SP - if off <= int32(-Thearch.Ptrsize) { - put(nil, a.Asym.Name, 'a', -(int64(off) + int64(Thearch.Ptrsize)), 0, 0, a.Gotype) + if off <= int32(-SysArch.PtrSize) { + put(nil, a.Asym.Name, 'a', -(int64(off) + int64(SysArch.PtrSize)), 0, 0, a.Gotype) continue } } diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go index 67a855933e..f0811389d2 100644 --- a/src/cmd/link/internal/ld/link.go +++ b/src/cmd/link/internal/ld/link.go @@ -32,8 +32,8 @@ package ld import ( "cmd/internal/obj" + "cmd/internal/sys" "debug/elf" - "encoding/binary" "fmt" ) @@ -161,11 +161,9 @@ type Shlib struct { } type Link struct { - Thechar int32 - Thestring string Goarm int32 Headtype int - Arch *LinkArch + Arch *sys.Arch Debugvlog int32 Bso *obj.Biobuf Windows int32 @@ -196,15 +194,15 @@ type Link struct { // on the stack in the function prologue and so always have a pointer between // the hardware stack pointer and the local variable area. func (ctxt *Link) FixedFrameSize() int64 { - switch ctxt.Arch.Thechar { - case '6', '8': + switch ctxt.Arch.Family { + case sys.AMD64, sys.I386: return 0 - case '9': + case sys.PPC64: // PIC code on ppc64le requires 32 bytes of stack, and it's easier to // just use that much stack always on ppc64x. - return int64(4 * ctxt.Arch.Ptrsize) + return int64(4 * ctxt.Arch.PtrSize) default: - return int64(ctxt.Arch.Ptrsize) + return int64(ctxt.Arch.PtrSize) } } @@ -213,15 +211,6 @@ func (l *Link) IncVersion() { l.Hash = append(l.Hash, make(map[string]*LSym)) } -type LinkArch struct { - ByteOrder binary.ByteOrder - Name string - Thechar int - Minlc int - Ptrsize int - Regsize int -} - type Library struct { Objref string Srcref string diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index cafc6b0382..25d48fbf22 100644 --- a/src/cmd/link/internal/ld/macho.go +++ b/src/cmd/link/internal/ld/macho.go @@ -6,6 +6,7 @@ package ld import ( "cmd/internal/obj" + "cmd/internal/sys" "sort" "strings" ) @@ -131,15 +132,7 @@ var nsortsym int var load_budget int = INITIAL_MACHO_HEADR - 2*1024 func Machoinit() { - switch Thearch.Thechar { - // 64-bit architectures - case '6', '7', '9': - macho64 = true - - // 32-bit architectures - default: - break - } + macho64 = SysArch.RegSize == 8 } func getMachoHdr() *MachoHdr { @@ -356,8 +349,8 @@ func machoshbits(mseg *MachoSeg, sect *Section, segname string) { buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1) var msect *MachoSect - if sect.Rwx&1 == 0 && segname != "__DWARF" && (Thearch.Thechar == '7' || // arm64 - (Thearch.Thechar == '6' && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive))) { // amd64 + if sect.Rwx&1 == 0 && segname != "__DWARF" && (SysArch.Family == sys.ARM64 || + (SysArch.Family == sys.AMD64 && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive))) { // Darwin external linker on arm64 and on amd64 in c-shared/c-archive buildmode // complains about absolute relocs in __TEXT, so if the section is not // executable, put it in __DATA segment. @@ -422,23 +415,23 @@ func Asmbmacho() { va := INITTEXT - int64(HEADR) mh := getMachoHdr() - switch Thearch.Thechar { + switch SysArch.Family { default: - Exitf("unknown macho architecture: %v", Thearch.Thechar) + Exitf("unknown macho architecture: %v", SysArch.Family) - case '5': + case sys.ARM: mh.cpu = MACHO_CPU_ARM mh.subcpu = MACHO_SUBCPU_ARMV7 - case '6': + case sys.AMD64: mh.cpu = MACHO_CPU_AMD64 mh.subcpu = MACHO_SUBCPU_X86 - case '7': + case sys.ARM64: mh.cpu = MACHO_CPU_ARM64 mh.subcpu = MACHO_SUBCPU_ARM64_ALL - case '8': + case sys.I386: mh.cpu = MACHO_CPU_386 mh.subcpu = MACHO_SUBCPU_X86 } @@ -449,7 +442,7 @@ func Asmbmacho() { ms = newMachoSeg("", 40) ms.fileoffset = Segtext.Fileoff - if Thearch.Thechar == '5' || Buildmode == BuildmodeCArchive { + if SysArch.Family == sys.ARM || Buildmode == BuildmodeCArchive { ms.filesize = Segdata.Fileoff + Segdata.Filelen - Segtext.Fileoff } else { ms.filesize = Segdwarf.Fileoff + Segdwarf.Filelen - Segtext.Fileoff @@ -511,31 +504,31 @@ func Asmbmacho() { } if Linkmode != LinkExternal { - switch Thearch.Thechar { + switch SysArch.Family { default: - Exitf("unknown macho architecture: %v", Thearch.Thechar) + Exitf("unknown macho architecture: %v", SysArch.Family) - case '5': + case sys.ARM: ml := newMachoLoad(5, 17+2) /* unix thread */ ml.data[0] = 1 /* thread type */ ml.data[1] = 17 /* word count */ ml.data[2+15] = uint32(Entryvalue()) /* start pc */ - case '6': + case sys.AMD64: ml := newMachoLoad(5, 42+2) /* unix thread */ ml.data[0] = 4 /* thread type */ ml.data[1] = 42 /* word count */ ml.data[2+32] = uint32(Entryvalue()) /* start pc */ ml.data[2+32+1] = uint32(Entryvalue() >> 32) - case '7': + case sys.ARM64: ml := newMachoLoad(5, 68+2) /* unix thread */ ml.data[0] = 6 /* thread type */ ml.data[1] = 68 /* word count */ ml.data[2+64] = uint32(Entryvalue()) /* start pc */ ml.data[2+64+1] = uint32(Entryvalue() >> 32) - case '8': + case sys.I386: ml := newMachoLoad(5, 16+2) /* unix thread */ ml.data[0] = 1 /* thread type */ ml.data[1] = 16 /* word count */ @@ -546,7 +539,6 @@ func Asmbmacho() { if Debug['d'] == 0 { // must match domacholink below s1 := Linklookup(Ctxt, ".machosymtab", 0) - s2 := Linklookup(Ctxt, ".linkedit.plt", 0) s3 := Linklookup(Ctxt, ".linkedit.got", 0) s4 := Linklookup(Ctxt, ".machosymstr", 0) @@ -729,7 +721,7 @@ func machosymtab() { Adduint8(Ctxt, symtab, 0x01) // type N_EXT, external symbol Adduint8(Ctxt, symtab, 0) // no section Adduint16(Ctxt, symtab, 0) // desc - adduintxx(Ctxt, symtab, 0, Thearch.Ptrsize) // no value + adduintxx(Ctxt, symtab, 0, SysArch.PtrSize) // no value } else { if s.Attr.CgoExport() { Adduint8(Ctxt, symtab, 0x0f) @@ -747,7 +739,7 @@ func machosymtab() { Adduint8(Ctxt, symtab, uint8(o.Sect.Extnum)) } Adduint16(Ctxt, symtab, 0) // desc - adduintxx(Ctxt, symtab, uint64(Symaddr(s)), Thearch.Ptrsize) + adduintxx(Ctxt, symtab, uint64(Symaddr(s)), SysArch.PtrSize) } } } diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index ff29ce2d70..471dda712f 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -93,7 +93,7 @@ func pciterinit(ctxt *Link, it *Pciter, d *Pcdata) { it.value = -1 it.start = 1 it.done = 0 - it.pcscale = uint32(ctxt.Arch.Minlc) + it.pcscale = uint32(ctxt.Arch.MinLC) pciternext(it) } @@ -242,12 +242,12 @@ func pclntab() { } pclntabNfunc = nfunc - Symgrow(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize)+int64(Thearch.Ptrsize)+4) + Symgrow(Ctxt, ftab, 8+int64(SysArch.PtrSize)+int64(nfunc)*2*int64(SysArch.PtrSize)+int64(SysArch.PtrSize)+4) setuint32(Ctxt, ftab, 0, 0xfffffffb) - setuint8(Ctxt, ftab, 6, uint8(Thearch.Minlc)) - setuint8(Ctxt, ftab, 7, uint8(Thearch.Ptrsize)) - setuintxx(Ctxt, ftab, 8, uint64(nfunc), int64(Thearch.Ptrsize)) - pclntabPclntabOffset = int32(8 + Thearch.Ptrsize) + setuint8(Ctxt, ftab, 6, uint8(SysArch.MinLC)) + setuint8(Ctxt, ftab, 7, uint8(SysArch.PtrSize)) + setuintxx(Ctxt, ftab, 8, uint64(nfunc), int64(SysArch.PtrSize)) + pclntabPclntabOffset = int32(8 + SysArch.PtrSize) nfunc = 0 var last *LSym @@ -272,16 +272,16 @@ func pclntab() { } funcstart = int32(len(ftab.P)) - funcstart += int32(-len(ftab.P)) & (int32(Thearch.Ptrsize) - 1) + funcstart += int32(-len(ftab.P)) & (int32(SysArch.PtrSize) - 1) - setaddr(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize), Ctxt.Cursym) - setuintxx(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize)+int64(Thearch.Ptrsize), uint64(funcstart), int64(Thearch.Ptrsize)) + setaddr(Ctxt, ftab, 8+int64(SysArch.PtrSize)+int64(nfunc)*2*int64(SysArch.PtrSize), Ctxt.Cursym) + setuintxx(Ctxt, ftab, 8+int64(SysArch.PtrSize)+int64(nfunc)*2*int64(SysArch.PtrSize)+int64(SysArch.PtrSize), uint64(funcstart), int64(SysArch.PtrSize)) // fixed size of struct, checked below off = funcstart - end = funcstart + int32(Thearch.Ptrsize) + 3*4 + 5*4 + int32(len(pcln.Pcdata))*4 + int32(len(pcln.Funcdata))*int32(Thearch.Ptrsize) - if len(pcln.Funcdata) > 0 && (end&int32(Thearch.Ptrsize-1) != 0) { + end = funcstart + int32(SysArch.PtrSize) + 3*4 + 5*4 + int32(len(pcln.Pcdata))*4 + int32(len(pcln.Funcdata))*int32(SysArch.PtrSize) + if len(pcln.Funcdata) > 0 && (end&int32(SysArch.PtrSize-1) != 0) { end += 4 } Symgrow(Ctxt, ftab, int64(end)) @@ -330,25 +330,25 @@ func pclntab() { // funcdata, must be pointer-aligned and we're only int32-aligned. // Missing funcdata will be 0 (nil pointer). if len(pcln.Funcdata) > 0 { - if off&int32(Thearch.Ptrsize-1) != 0 { + if off&int32(SysArch.PtrSize-1) != 0 { off += 4 } for i = 0; i < int32(len(pcln.Funcdata)); i++ { if pcln.Funcdata[i] == nil { - setuintxx(Ctxt, ftab, int64(off)+int64(Thearch.Ptrsize)*int64(i), uint64(pcln.Funcdataoff[i]), int64(Thearch.Ptrsize)) + setuintxx(Ctxt, ftab, int64(off)+int64(SysArch.PtrSize)*int64(i), uint64(pcln.Funcdataoff[i]), int64(SysArch.PtrSize)) } else { // TODO: Dedup. funcdata_bytes += pcln.Funcdata[i].Size - setaddrplus(Ctxt, ftab, int64(off)+int64(Thearch.Ptrsize)*int64(i), pcln.Funcdata[i], pcln.Funcdataoff[i]) + setaddrplus(Ctxt, ftab, int64(off)+int64(SysArch.PtrSize)*int64(i), pcln.Funcdata[i], pcln.Funcdataoff[i]) } } - off += int32(len(pcln.Funcdata)) * int32(Thearch.Ptrsize) + off += int32(len(pcln.Funcdata)) * int32(SysArch.PtrSize) } if off != end { - Diag("bad math in functab: funcstart=%d off=%d but end=%d (npcdata=%d nfuncdata=%d ptrsize=%d)", funcstart, off, end, len(pcln.Pcdata), len(pcln.Funcdata), Thearch.Ptrsize) + Diag("bad math in functab: funcstart=%d off=%d but end=%d (npcdata=%d nfuncdata=%d ptrsize=%d)", funcstart, off, end, len(pcln.Pcdata), len(pcln.Funcdata), SysArch.PtrSize) errorexit() } @@ -357,14 +357,14 @@ func pclntab() { pclntabLastFunc = last // Final entry of table is just end pc. - setaddrplus(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize), last, last.Size) + setaddrplus(Ctxt, ftab, 8+int64(SysArch.PtrSize)+int64(nfunc)*2*int64(SysArch.PtrSize), last, last.Size) // Start file table. start := int32(len(ftab.P)) - start += int32(-len(ftab.P)) & (int32(Thearch.Ptrsize) - 1) + start += int32(-len(ftab.P)) & (int32(SysArch.PtrSize) - 1) pclntabFiletabOffset = start - setuint32(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize)+int64(Thearch.Ptrsize), uint32(start)) + setuint32(Ctxt, ftab, 8+int64(SysArch.PtrSize)+int64(nfunc)*2*int64(SysArch.PtrSize)+int64(SysArch.PtrSize), uint32(start)) Symgrow(Ctxt, ftab, int64(start)+(int64(Ctxt.Nhistfile)+1)*4) setuint32(Ctxt, ftab, int64(start), uint32(Ctxt.Nhistfile)) diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 56698361d0..0204b8c8c2 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -6,6 +6,7 @@ package ld import ( "cmd/internal/obj" + "cmd/internal/sys" "encoding/binary" "fmt" "os" @@ -419,9 +420,9 @@ func chksectseg(h *IMAGE_SECTION_HEADER, s *Segment) { func Peinit() { var l int - switch Thearch.Thechar { + switch SysArch.Family { // 64-bit architectures - case '6': + case sys.AMD64: pe64 = 1 l = binary.Size(&oh64) @@ -506,7 +507,7 @@ func initdynimport() *Dll { if err != nil { Diag("failed to parse stdcall decoration: %v", err) } - m.argsize *= Thearch.Ptrsize + m.argsize *= SysArch.PtrSize s.Extname = s.Extname[:i] } @@ -520,10 +521,10 @@ func initdynimport() *Dll { for d := dr; d != nil; d = d.next { for m = d.ms; m != nil; m = m.next { m.s.Type = obj.SDATA - Symgrow(Ctxt, m.s, int64(Thearch.Ptrsize)) + Symgrow(Ctxt, m.s, int64(SysArch.PtrSize)) dynName := m.s.Extname // only windows/386 requires stdcall decoration - if Thearch.Thechar == '8' && m.argsize >= 0 { + if SysArch.Family == sys.I386 && m.argsize >= 0 { dynName += fmt.Sprintf("@%d", m.argsize) } dynSym := Linklookup(Ctxt, dynName, 0) @@ -532,7 +533,7 @@ func initdynimport() *Dll { r := Addrel(m.s) r.Sym = dynSym r.Off = 0 - r.Siz = uint8(Thearch.Ptrsize) + r.Siz = uint8(SysArch.PtrSize) r.Type = obj.R_ADDR } } @@ -546,10 +547,10 @@ func initdynimport() *Dll { m.s.Sub = dynamic.Sub dynamic.Sub = m.s m.s.Value = dynamic.Size - dynamic.Size += int64(Thearch.Ptrsize) + dynamic.Size += int64(SysArch.PtrSize) } - dynamic.Size += int64(Thearch.Ptrsize) + dynamic.Size += int64(SysArch.PtrSize) } } @@ -946,7 +947,7 @@ func writePESymTableRecords() int { } // only windows/386 requires underscore prefix on external symbols - if Thearch.Thechar == '8' && + if SysArch.Family == sys.I386 && Linkmode == LinkExternal && (s.Type != obj.SDYNIMPORT || s.Attr.CgoExport()) && s.Name == s.Extname && @@ -1002,7 +1003,7 @@ func writePESymTableRecords() int { for d := dr; d != nil; d = d.next { for m := d.ms; m != nil; m = m.next { s := m.s.R[0].Xsym - put(s, s.Name, 'U', 0, int64(Thearch.Ptrsize), 0, nil) + put(s, s.Name, 'U', 0, int64(SysArch.PtrSize), 0, nil) } } @@ -1129,12 +1130,12 @@ func addinitarray() (c *IMAGE_SECTION_HEADER) { } func Asmbpe() { - switch Thearch.Thechar { + switch SysArch.Family { default: - Exitf("unknown PE architecture: %v", Thearch.Thechar) - case '6': + Exitf("unknown PE architecture: %v", SysArch.Family) + case sys.AMD64: fh.Machine = IMAGE_FILE_MACHINE_AMD64 - case '8': + case sys.I386: fh.Machine = IMAGE_FILE_MACHINE_I386 } diff --git a/src/cmd/link/internal/ld/pobj.go b/src/cmd/link/internal/ld/pobj.go index f48b54efda..b9902a5e5e 100644 --- a/src/cmd/link/internal/ld/pobj.go +++ b/src/cmd/link/internal/ld/pobj.go @@ -32,6 +32,7 @@ package ld import ( "cmd/internal/obj" + "cmd/internal/sys" "flag" "fmt" "os" @@ -44,9 +45,7 @@ var ( ) func Ldmain() { - Ctxt = linknew(Thelinkarch) - Ctxt.Thechar = int32(Thearch.Thechar) - Ctxt.Thestring = Thestring + Ctxt = linknew(SysArch) Ctxt.Diag = Diag Ctxt.Bso = &Bso @@ -70,7 +69,7 @@ func Ldmain() { } } - if Thearch.Thechar == '6' && obj.Getgoos() == "plan9" { + if SysArch.Family == sys.AMD64 && obj.Getgoos() == "plan9" { obj.Flagcount("8", "use 64-bit addresses in symbol table", &Debug['8']) } obj.Flagfn1("B", "add an ELF NT_GNU_BUILD_ID `note` when using ELF", addbuildinfo) @@ -107,7 +106,7 @@ func Ldmain() { obj.Flagcount("race", "enable race detector", &flag_race) obj.Flagcount("s", "disable symbol table", &Debug['s']) var flagShared int - if Thearch.Thechar == '5' || Thearch.Thechar == '6' { + if SysArch.InFamily(sys.ARM, sys.AMD64) { obj.Flagcount("shared", "generate shared object (implies -linkmode external)", &flagShared) } obj.Flagstr("tmpdir", "use `directory` for temporary files", &tmpdir) diff --git a/src/cmd/link/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go index 3deb94644e..76fe7dab79 100644 --- a/src/cmd/link/internal/ld/sym.go +++ b/src/cmd/link/internal/ld/sym.go @@ -33,6 +33,7 @@ package ld import ( "cmd/internal/obj" + "cmd/internal/sys" "log" "strconv" ) @@ -55,7 +56,7 @@ var headers = []struct { {"windowsgui", obj.Hwindows}, } -func linknew(arch *LinkArch) *Link { +func linknew(arch *sys.Arch) *Link { ctxt := &Link{ Hash: []map[string]*LSym{ // preallocate about 2mb for hash of @@ -98,33 +99,33 @@ func linknew(arch *LinkArch) *Link { obj.Hdragonfly, obj.Hsolaris: if obj.Getgoos() == "android" { - switch ctxt.Arch.Thechar { - case '6': + switch ctxt.Arch.Family { + case sys.AMD64: // Android/amd64 constant - offset from 0(FS) to our TLS slot. // Explained in src/runtime/cgo/gcc_android_*.c ctxt.Tlsoffset = 0x1d0 - case '8': + case sys.I386: // Android/386 constant - offset from 0(GS) to our TLS slot. ctxt.Tlsoffset = 0xf8 default: - ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize + ctxt.Tlsoffset = -1 * ctxt.Arch.PtrSize } } else { - ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize + ctxt.Tlsoffset = -1 * ctxt.Arch.PtrSize } case obj.Hnacl: - switch ctxt.Arch.Thechar { + switch ctxt.Arch.Family { default: log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name) - case '5': + case sys.ARM: ctxt.Tlsoffset = 0 - case '6': + case sys.AMD64: ctxt.Tlsoffset = 0 - case '8': + case sys.I386: ctxt.Tlsoffset = -8 } @@ -133,26 +134,26 @@ func linknew(arch *LinkArch) *Link { * Explained in src/runtime/cgo/gcc_darwin_*.c. */ case obj.Hdarwin: - switch ctxt.Arch.Thechar { + switch ctxt.Arch.Family { default: log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name) - case '5': + case sys.ARM: ctxt.Tlsoffset = 0 // dummy value, not needed - case '6': + case sys.AMD64: ctxt.Tlsoffset = 0x8a0 - case '7': + case sys.ARM64: ctxt.Tlsoffset = 0 // dummy value, not needed - case '8': + case sys.I386: ctxt.Tlsoffset = 0x468 } } // On arm, record goarm. - if ctxt.Arch.Thechar == '5' { + if ctxt.Arch.Family == sys.ARM { ctxt.Goarm = obj.Getgoarm() } diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 167176cc2d..ecd5c741bb 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -32,6 +32,7 @@ package ld import ( "cmd/internal/obj" + "cmd/internal/sys" "fmt" "path/filepath" "strings" @@ -160,7 +161,7 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L if x.Type&obj.SHIDDEN != 0 { other = STV_HIDDEN } - if (Buildmode == BuildmodePIE || DynlinkingGo()) && Thearch.Thechar == '9' && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" { + if (Buildmode == BuildmodePIE || DynlinkingGo()) && SysArch.Family == sys.PPC64 && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" { // On ppc64 the top three bits of the st_other field indicate how // many instructions separate the global and local entry points. In // our case it is two instructions, indicated by the value 3. @@ -229,7 +230,7 @@ func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ 'Z', 'm': l := 4 - if HEADTYPE == obj.Hplan9 && Thearch.Thechar == '6' && Debug['8'] == 0 { + if HEADTYPE == obj.Hplan9 && SysArch.Family == sys.AMD64 && Debug['8'] == 0 { Lputb(uint32(addr >> 32)) l = 8 } diff --git a/src/cmd/link/internal/mips64/asm.go b/src/cmd/link/internal/mips64/asm.go index d0977e9b00..9a145e373a 100644 --- a/src/cmd/link/internal/mips64/asm.go +++ b/src/cmd/link/internal/mips64/asm.go @@ -32,6 +32,7 @@ package mips64 import ( "cmd/internal/obj" + "cmd/internal/sys" "cmd/link/internal/ld" "encoding/binary" "fmt" @@ -82,8 +83,8 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { // the first instruction is always at the lower address, this is endian neutral; // but note that o1 and o2 should still use the target endian. - o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off:]) - o2 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4:]) + o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:]) + o2 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off+4:]) o1 = o1&0xffff0000 | uint32(t>>16)&0xffff o2 = o2&0xffff0000 | uint32(t)&0xffff @@ -99,7 +100,7 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { obj.R_JMPMIPS: // Low 26 bits = (S + A) >> 2 t := ld.Symaddr(r.Sym) + r.Add - o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off:]) + o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:]) *val = int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000) return 0 } @@ -214,7 +215,7 @@ func asmb() { default: case obj.Hplan9: /* plan 9 */ magic := uint32(4*18*18 + 7) - if ld.Thestring == "mips64le" { + if ld.SysArch == sys.ArchMIPS64LE { magic = uint32(4*26*26 + 7) } ld.Thearch.Lput(uint32(magic)) /* magic */ diff --git a/src/cmd/link/internal/mips64/l.go b/src/cmd/link/internal/mips64/l.go index 003ee5ce71..f4191e69ab 100644 --- a/src/cmd/link/internal/mips64/l.go +++ b/src/cmd/link/internal/mips64/l.go @@ -62,11 +62,9 @@ package mips64 // THE SOFTWARE. const ( - thechar = '0' MaxAlign = 32 // max data alignment MinAlign = 1 // min data alignment FuncAlign = 8 - MINLC = 4 ) /* Used by ../internal/ld/dwarf.go */ diff --git a/src/cmd/link/internal/mips64/obj.go b/src/cmd/link/internal/mips64/obj.go index 57a1b2ab14..87bb3a079b 100644 --- a/src/cmd/link/internal/mips64/obj.go +++ b/src/cmd/link/internal/mips64/obj.go @@ -32,6 +32,7 @@ package mips64 import ( "cmd/internal/obj" + "cmd/internal/sys" "cmd/link/internal/ld" "fmt" "log" @@ -45,21 +46,15 @@ func Main() { } func linkarchinit() { - ld.Thestring = obj.Getgoarch() - if ld.Thestring == "mips64le" { - ld.Thelinkarch = &ld.Linkmips64le + if obj.Getgoarch() == "mips64le" { + ld.SysArch = sys.ArchMIPS64LE } else { - ld.Thelinkarch = &ld.Linkmips64 + ld.SysArch = sys.ArchMIPS64 } - ld.Thearch.Thechar = thechar - ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize - ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize - ld.Thearch.Regsize = ld.Thelinkarch.Regsize ld.Thearch.Funcalign = FuncAlign ld.Thearch.Maxalign = MaxAlign ld.Thearch.Minalign = MinAlign - ld.Thearch.Minlc = MINLC ld.Thearch.Dwarfregsp = DWARFREGSP ld.Thearch.Dwarfreglr = DWARFREGLR @@ -72,7 +67,7 @@ func linkarchinit() { ld.Thearch.Elfsetupplt = elfsetupplt ld.Thearch.Gentext = gentext ld.Thearch.Machoreloc1 = machoreloc1 - if ld.Thelinkarch == &ld.Linkmips64le { + if ld.SysArch == sys.ArchMIPS64LE { ld.Thearch.Lput = ld.Lputl ld.Thearch.Wput = ld.Wputl ld.Thearch.Vput = ld.Vputl diff --git a/src/cmd/link/internal/ppc64/l.go b/src/cmd/link/internal/ppc64/l.go index 622d6bb12e..a720993fbc 100644 --- a/src/cmd/link/internal/ppc64/l.go +++ b/src/cmd/link/internal/ppc64/l.go @@ -62,11 +62,9 @@ package ppc64 // THE SOFTWARE. const ( - thechar = '9' MaxAlign = 32 // max data alignment MinAlign = 1 // min data alignment FuncAlign = 8 - MINLC = 4 ) /* Used by ../internal/ld/dwarf.go */ diff --git a/src/cmd/link/internal/ppc64/obj.go b/src/cmd/link/internal/ppc64/obj.go index 539ab1ac02..a540ab85b5 100644 --- a/src/cmd/link/internal/ppc64/obj.go +++ b/src/cmd/link/internal/ppc64/obj.go @@ -32,6 +32,7 @@ package ppc64 import ( "cmd/internal/obj" + "cmd/internal/sys" "cmd/link/internal/ld" "fmt" "log" @@ -45,21 +46,15 @@ func Main() { } func linkarchinit() { - ld.Thestring = obj.Getgoarch() - if ld.Thestring == "ppc64le" { - ld.Thelinkarch = &ld.Linkppc64le + if obj.Getgoarch() == "ppc64le" { + ld.SysArch = sys.ArchPPC64LE } else { - ld.Thelinkarch = &ld.Linkppc64 + ld.SysArch = sys.ArchPPC64 } - ld.Thearch.Thechar = thechar - ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize - ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize - ld.Thearch.Regsize = ld.Thelinkarch.Regsize ld.Thearch.Funcalign = FuncAlign ld.Thearch.Maxalign = MaxAlign ld.Thearch.Minalign = MinAlign - ld.Thearch.Minlc = MINLC ld.Thearch.Dwarfregsp = DWARFREGSP ld.Thearch.Dwarfreglr = DWARFREGLR @@ -72,7 +67,7 @@ func linkarchinit() { ld.Thearch.Elfsetupplt = elfsetupplt ld.Thearch.Gentext = gentext ld.Thearch.Machoreloc1 = machoreloc1 - if ld.Thelinkarch == &ld.Linkppc64le { + if ld.SysArch == sys.ArchPPC64LE { ld.Thearch.Lput = ld.Lputl ld.Thearch.Wput = ld.Wputl ld.Thearch.Vput = ld.Vputl @@ -150,7 +145,7 @@ func archinit() { } case obj.Hlinux: /* ppc64 elf */ - if ld.Thestring == "ppc64" { + if ld.SysArch == sys.ArchPPC64 { ld.Debug['d'] = 1 // TODO(austin): ELF ABI v1 not supported yet } ld.Elfinit() diff --git a/src/cmd/link/internal/s390x/l.go b/src/cmd/link/internal/s390x/l.go index 839a9849c8..42cf15ee85 100644 --- a/src/cmd/link/internal/s390x/l.go +++ b/src/cmd/link/internal/s390x/l.go @@ -62,14 +62,9 @@ package s390x // THE SOFTWARE. const ( - thechar = 'z' - PtrSize = 8 - IntSize = 8 - RegSize = 8 MaxAlign = 32 // max data alignment MinAlign = 2 // min data alignment FuncAlign = 16 - MINLC = 2 ) /* Used by ../internal/ld/dwarf.go */ diff --git a/src/cmd/link/internal/s390x/obj.go b/src/cmd/link/internal/s390x/obj.go index ef88d22bbd..fdb9898181 100644 --- a/src/cmd/link/internal/s390x/obj.go +++ b/src/cmd/link/internal/s390x/obj.go @@ -32,6 +32,7 @@ package s390x import ( "cmd/internal/obj" + "cmd/internal/sys" "cmd/link/internal/ld" "fmt" ) @@ -44,17 +45,11 @@ func Main() { } func linkarchinit() { - ld.Thestring = obj.Getgoarch() - ld.Thelinkarch = &ld.Links390x + ld.SysArch = sys.ArchS390X - ld.Thearch.Thechar = thechar - ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize - ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize - ld.Thearch.Regsize = ld.Thelinkarch.Regsize ld.Thearch.Funcalign = FuncAlign ld.Thearch.Maxalign = MaxAlign ld.Thearch.Minalign = MinAlign - ld.Thearch.Minlc = MINLC ld.Thearch.Dwarfregsp = DWARFREGSP ld.Thearch.Dwarfreglr = DWARFREGLR diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go index 7da5dd02be..91251de15e 100644 --- a/src/cmd/link/internal/x86/asm.go +++ b/src/cmd/link/internal/x86/asm.go @@ -292,7 +292,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) { return } - if ld.HEADTYPE == obj.Hdarwin && s.Size == PtrSize && r.Off == 0 { + if ld.HEADTYPE == obj.Hdarwin && s.Size == int64(ld.SysArch.PtrSize) && r.Off == 0 { // Mach-O relocations are a royal pain to lay out. // They use a compact stateful bytecode representation // that is too much bother to deal with. @@ -317,7 +317,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) { return } - if ld.HEADTYPE == obj.Hwindows && s.Size == PtrSize { + if ld.HEADTYPE == obj.Hwindows && s.Size == int64(ld.SysArch.PtrSize) { // nothing to do, the relocation will be laid out in pereloc1 return } diff --git a/src/cmd/link/internal/x86/l.go b/src/cmd/link/internal/x86/l.go index 068fed9c8d..2043f9bb4e 100644 --- a/src/cmd/link/internal/x86/l.go +++ b/src/cmd/link/internal/x86/l.go @@ -31,12 +31,9 @@ package x86 const ( - thechar = '8' - PtrSize = 4 MaxAlign = 32 // max data alignment MinAlign = 1 // min data alignment FuncAlign = 16 - MINLC = 1 ) /* Used by ../internal/ld/dwarf.go */ diff --git a/src/cmd/link/internal/x86/obj.go b/src/cmd/link/internal/x86/obj.go index 4380c41ebb..574c0dad2d 100644 --- a/src/cmd/link/internal/x86/obj.go +++ b/src/cmd/link/internal/x86/obj.go @@ -32,6 +32,7 @@ package x86 import ( "cmd/internal/obj" + "cmd/internal/sys" "cmd/link/internal/ld" "fmt" "log" @@ -45,17 +46,11 @@ func Main() { } func linkarchinit() { - ld.Thestring = "386" - ld.Thelinkarch = &ld.Link386 + ld.SysArch = sys.Arch386 - ld.Thearch.Thechar = thechar - ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize - ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize - ld.Thearch.Regsize = ld.Thelinkarch.Regsize ld.Thearch.Funcalign = FuncAlign ld.Thearch.Maxalign = MaxAlign ld.Thearch.Minalign = MinAlign - ld.Thearch.Minlc = MINLC ld.Thearch.Dwarfregsp = DWARFREGSP ld.Thearch.Dwarfreglr = DWARFREGLR -- cgit v1.3 From 4b7e36cdfe8e0c3579a2503a81474fe43db4db69 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 6 Apr 2016 21:45:29 -0700 Subject: cmd: extract obj's Biobuf code into new bio package API could still be made more Go-ey. Updates #15165. Change-Id: I514ffceffa43c293ae5d7e5f1e9193fda0098865 Reviewed-on: https://go-review.googlesource.com/21644 Reviewed-by: Brad Fitzpatrick Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot --- src/cmd/asm/internal/asm/endtoend_test.go | 5 +- src/cmd/asm/main.go | 5 +- src/cmd/compile/internal/gc/bexport.go | 10 +- src/cmd/compile/internal/gc/export.go | 8 +- src/cmd/compile/internal/gc/go.go | 5 +- src/cmd/compile/internal/gc/main.go | 5 +- src/cmd/compile/internal/gc/obj.go | 31 +++--- src/cmd/dist/buildtool.go | 1 + src/cmd/internal/bio/buf.go | 150 ++++++++++++++++++++++++++++++ src/cmd/internal/obj/link.go | 7 +- src/cmd/internal/obj/objfile.go | 9 +- src/cmd/internal/obj/util.go | 140 ---------------------------- src/cmd/link/internal/ld/ar.go | 15 +-- src/cmd/link/internal/ld/go.go | 5 +- src/cmd/link/internal/ld/ldelf.go | 13 +-- src/cmd/link/internal/ld/ldmacho.go | 23 ++--- src/cmd/link/internal/ld/ldpe.go | 27 +++--- src/cmd/link/internal/ld/lib.go | 83 ++++++++--------- src/cmd/link/internal/ld/link.go | 4 +- src/cmd/link/internal/ld/objfile.go | 9 +- src/cmd/link/internal/ld/pobj.go | 3 +- 21 files changed, 291 insertions(+), 267 deletions(-) create mode 100644 src/cmd/internal/bio/buf.go (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/asm/internal/asm/endtoend_test.go b/src/cmd/asm/internal/asm/endtoend_test.go index 1307c4243f..8986281f10 100644 --- a/src/cmd/asm/internal/asm/endtoend_test.go +++ b/src/cmd/asm/internal/asm/endtoend_test.go @@ -17,6 +17,7 @@ import ( "testing" "cmd/asm/internal/lex" + "cmd/internal/bio" "cmd/internal/obj" ) @@ -33,7 +34,7 @@ func testEndToEnd(t *testing.T, goarch, file string) { pList := obj.Linknewplist(ctxt) var ok bool testOut = new(bytes.Buffer) // The assembler writes test output to this buffer. - ctxt.Bso = obj.Binitw(os.Stdout) + ctxt.Bso = bio.BufWriter(os.Stdout) defer ctxt.Bso.Flush() failed := false ctxt.DiagFunc = func(format string, args ...interface{}) { @@ -271,7 +272,7 @@ func testErrors(t *testing.T, goarch, file string) { pList := obj.Linknewplist(ctxt) var ok bool testOut = new(bytes.Buffer) // The assembler writes test output to this buffer. - ctxt.Bso = obj.Binitw(os.Stdout) + ctxt.Bso = bio.BufWriter(os.Stdout) defer ctxt.Bso.Flush() failed := false var errBuf bytes.Buffer diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go index 4e450bec98..75cb8f75d3 100644 --- a/src/cmd/asm/main.go +++ b/src/cmd/asm/main.go @@ -15,6 +15,7 @@ import ( "cmd/asm/internal/flags" "cmd/asm/internal/lex" + "cmd/internal/bio" "cmd/internal/obj" ) @@ -45,9 +46,9 @@ func main() { if *flags.Shared || *flags.Dynlink { ctxt.Flag_shared = 1 } - ctxt.Bso = obj.Binitw(os.Stdout) + ctxt.Bso = bio.BufWriter(os.Stdout) defer ctxt.Bso.Flush() - output := obj.Binitw(fd) + output := bio.BufWriter(fd) fmt.Fprintf(output, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion()) fmt.Fprintf(output, "!\n") diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index 092cdac2f6..702090280f 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -92,7 +92,7 @@ package gc import ( "bytes" "cmd/compile/internal/big" - "cmd/internal/obj" + "cmd/internal/bio" "encoding/binary" "fmt" "sort" @@ -124,7 +124,7 @@ const exportVersion = "v0" const exportInlined = true // default: true type exporter struct { - out *obj.Biobuf + out *bio.Buf pkgIndex map[*Pkg]int typIndex map[*Type]int inlined []*Func @@ -136,7 +136,7 @@ type exporter struct { } // Export writes the exportlist for localpkg to out and returns the number of bytes written. -func Export(out *obj.Biobuf, trace bool) int { +func Export(out *bio.Buf, trace bool) int { p := exporter{ out: out, pkgIndex: make(map[*Pkg]int), @@ -1531,10 +1531,10 @@ func (p *exporter) byte(b byte) { fallthrough case '|': // write '|' as '|' '|' - obj.Bputc(p.out, '|') + p.out.WriteByte('|') p.written++ } - obj.Bputc(p.out, b) + p.out.WriteByte(b) p.written++ } diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index 17311cf6af..5d4add8ff4 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -7,7 +7,7 @@ package gc import ( "bufio" "bytes" - "cmd/internal/obj" + "cmd/internal/bio" "fmt" "sort" "unicode" @@ -384,7 +384,7 @@ func dumpexport() { if debugFormat { // save a copy of the export data var copy bytes.Buffer - bcopy := obj.Binitw(©) + bcopy := bio.BufWriter(©) size = Export(bcopy, Debug_export != 0) bcopy.Flush() // flushing to bytes.Buffer cannot fail if n, err := bout.Write(copy.Bytes()); n != size || err != nil { @@ -577,7 +577,7 @@ func importtype(pt *Type, t *Type) { } func dumpasmhdr() { - b, err := obj.Bopenw(asmhdr) + b, err := bio.Create(asmhdr) if err != nil { Fatalf("%v", err) } @@ -604,5 +604,5 @@ func dumpasmhdr() { } } - obj.Bterm(b) + b.Close() } diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index ef8b516ea5..cd9db38fb4 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -6,6 +6,7 @@ package gc import ( "cmd/compile/internal/ssa" + "cmd/internal/bio" "cmd/internal/obj" ) @@ -132,7 +133,7 @@ var infile string var outfile string -var bout *obj.Biobuf +var bout *bio.Buf var nerrors int @@ -287,7 +288,7 @@ var Ctxt *obj.Link var writearchive int -var bstdout obj.Biobuf +var bstdout *bio.Buf var Nacl bool diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 079f4916c7..c8a778c34a 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -9,6 +9,7 @@ package gc import ( "bufio" "cmd/compile/internal/ssa" + "cmd/internal/bio" "cmd/internal/obj" "cmd/internal/sys" "flag" @@ -97,8 +98,8 @@ func Main() { Ctxt = obj.Linknew(Thearch.LinkArch) Ctxt.DiagFunc = Yyerror - Ctxt.Bso = &bstdout - bstdout = *obj.Binitw(os.Stdout) + bstdout = bio.BufWriter(os.Stdout) + Ctxt.Bso = bstdout localpkg = mkpkg("") localpkg.Prefix = "\"\"" diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 99eb73bd94..3920e25224 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -5,6 +5,7 @@ package gc import ( + "cmd/internal/bio" "cmd/internal/obj" "crypto/sha256" "fmt" @@ -23,7 +24,7 @@ func formathdr(arhdr []byte, name string, size int64) { func dumpobj() { var err error - bout, err = obj.Bopenw(outfile) + bout, err = bio.Create(outfile) if err != nil { Flusherrors() fmt.Printf("can't create %s: %v\n", outfile, err) @@ -33,10 +34,10 @@ func dumpobj() { startobj := int64(0) var arhdr [ArhdrSize]byte if writearchive != 0 { - obj.Bwritestring(bout, "!\n") + bout.WriteString("!\n") arhdr = [ArhdrSize]byte{} bout.Write(arhdr[:]) - startobj = obj.Boffset(bout) + startobj = bio.Boffset(bout) } fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) @@ -44,19 +45,19 @@ func dumpobj() { if writearchive != 0 { bout.Flush() - size := obj.Boffset(bout) - startobj + size := bio.Boffset(bout) - startobj if size&1 != 0 { - obj.Bputc(bout, 0) + bout.WriteByte(0) } - obj.Bseek(bout, startobj-ArhdrSize, 0) + bio.Bseek(bout, startobj-ArhdrSize, 0) formathdr(arhdr[:], "__.PKGDEF", size) bout.Write(arhdr[:]) bout.Flush() - obj.Bseek(bout, startobj+size+(size&1), 0) + bio.Bseek(bout, startobj+size+(size&1), 0) arhdr = [ArhdrSize]byte{} bout.Write(arhdr[:]) - startobj = obj.Boffset(bout) + startobj = bio.Boffset(bout) fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) } @@ -91,16 +92,16 @@ func dumpobj() { if writearchive != 0 { bout.Flush() - size := obj.Boffset(bout) - startobj + size := bio.Boffset(bout) - startobj if size&1 != 0 { - obj.Bputc(bout, 0) + bout.WriteByte(0) } - obj.Bseek(bout, startobj-ArhdrSize, 0) + bio.Bseek(bout, startobj-ArhdrSize, 0) formathdr(arhdr[:], "_go_.o", size) bout.Write(arhdr[:]) } - obj.Bterm(bout) + bout.Close() } func dumpglobls() { @@ -132,9 +133,9 @@ func dumpglobls() { funcsyms = nil } -func Bputname(b *obj.Biobuf, s *obj.LSym) { - obj.Bwritestring(b, s.Name) - obj.Bputc(b, 0) +func Bputname(b *bio.Buf, s *obj.LSym) { + b.WriteString(s.Name) + b.WriteByte(0) } func Linksym(s *Sym) *obj.LSym { diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 123d5ccf82..777c92c726 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -38,6 +38,7 @@ var bootstrapDirs = []string{ "compile/internal/ppc64", "compile/internal/ssa", "compile/internal/x86", + "internal/bio", "internal/gcprog", "internal/obj", "internal/obj/arm", diff --git a/src/cmd/internal/bio/buf.go b/src/cmd/internal/bio/buf.go new file mode 100644 index 0000000000..a1df26ca9c --- /dev/null +++ b/src/cmd/internal/bio/buf.go @@ -0,0 +1,150 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package bio implements seekable buffered I/O. +package bio + +import ( + "bufio" + "io" + "log" + "os" +) + +const EOF = -1 + +// Buf implements a seekable buffered I/O abstraction. +type Buf struct { + f *os.File + r *bufio.Reader + w *bufio.Writer +} + +func (b *Buf) Reader() *bufio.Reader { return b.r } +func (b *Buf) Writer() *bufio.Writer { return b.w } + +func Create(name string) (*Buf, error) { + f, err := os.Create(name) + if err != nil { + return nil, err + } + return &Buf{f: f, w: bufio.NewWriter(f)}, nil +} + +func Open(name string) (*Buf, error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + return &Buf{f: f, r: bufio.NewReader(f)}, nil +} + +func BufWriter(w io.Writer) *Buf { + return &Buf{w: bufio.NewWriter(w)} +} + +func BufReader(r io.Reader) *Buf { + return &Buf{r: bufio.NewReader(r)} +} + +func (b *Buf) Write(p []byte) (int, error) { + return b.w.Write(p) +} + +func (b *Buf) WriteString(p string) (int, error) { + return b.w.WriteString(p) +} + +func Bseek(b *Buf, offset int64, whence int) int64 { + if b.w != nil { + if err := b.w.Flush(); err != nil { + log.Fatalf("writing output: %v", err) + } + } else if b.r != nil { + if whence == 1 { + offset -= int64(b.r.Buffered()) + } + } + off, err := b.f.Seek(offset, whence) + if err != nil { + log.Fatalf("seeking in output: %v", err) + } + if b.r != nil { + b.r.Reset(b.f) + } + return off +} + +func Boffset(b *Buf) int64 { + if b.w != nil { + if err := b.w.Flush(); err != nil { + log.Fatalf("writing output: %v", err) + } + } + off, err := b.f.Seek(0, 1) + if err != nil { + log.Fatalf("seeking in output [0, 1]: %v", err) + } + if b.r != nil { + off -= int64(b.r.Buffered()) + } + return off +} + +func (b *Buf) Flush() error { + return b.w.Flush() +} + +func (b *Buf) WriteByte(c byte) error { + return b.w.WriteByte(c) +} + +func Bread(b *Buf, p []byte) int { + n, err := io.ReadFull(b.r, p) + if n == 0 { + if err != nil && err != io.EOF { + n = -1 + } + } + return n +} + +func Bgetc(b *Buf) int { + c, err := b.r.ReadByte() + if err != nil { + if err != io.EOF { + log.Fatalf("reading input: %v", err) + } + return EOF + } + return int(c) +} + +func (b *Buf) Read(p []byte) (int, error) { + return b.r.Read(p) +} + +func (b *Buf) Peek(n int) ([]byte, error) { + return b.r.Peek(n) +} + +func Brdline(b *Buf, delim int) string { + s, err := b.r.ReadBytes(byte(delim)) + if err != nil { + log.Fatalf("reading input: %v", err) + } + return string(s) +} + +func (b *Buf) Close() error { + var err error + if b.w != nil { + err = b.w.Flush() + } + err1 := b.f.Close() + if err == nil { + err = err1 + } + return err +} diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 81a5689aef..2c81ca2f08 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -30,7 +30,10 @@ package obj -import "cmd/internal/sys" +import ( + "cmd/internal/bio" + "cmd/internal/sys" +) // An Addr is an argument to an instruction. // The general forms and their encodings are: @@ -626,7 +629,7 @@ type Link struct { Flag_shared int32 Flag_dynlink bool Flag_optimize bool - Bso *Biobuf + Bso *bio.Buf Pathname string Goroot string Goroot_final string diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index bdd3bfc826..405cbf446a 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -109,6 +109,7 @@ package obj import ( "bufio" + "cmd/internal/bio" "cmd/internal/sys" "fmt" "log" @@ -120,7 +121,7 @@ import ( // The Go and C compilers, and the assembler, call writeobj to write // out a Go object file. The linker does not call this; the linker // does not write out object files. -func Writeobjdirect(ctxt *Link, b *Biobuf) { +func Writeobjdirect(ctxt *Link, b *bio.Buf) { Flushplist(ctxt) WriteObjFile(ctxt, b) } @@ -373,16 +374,16 @@ func (w *objWriter) writeLengths() { w.writeInt(int64(w.nFile)) } -func newObjWriter(ctxt *Link, b *Biobuf) *objWriter { +func newObjWriter(ctxt *Link, b *bio.Buf) *objWriter { return &objWriter{ ctxt: ctxt, - wr: b.w, + wr: b.Writer(), vrefIdx: make(map[string]int), refIdx: make(map[string]int), } } -func WriteObjFile(ctxt *Link, b *Biobuf) { +func WriteObjFile(ctxt *Link, b *bio.Buf) { w := newObjWriter(ctxt, b) // Magic header diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go index 245fab9690..04e6a76e1a 100644 --- a/src/cmd/internal/obj/util.go +++ b/src/cmd/internal/obj/util.go @@ -5,10 +5,8 @@ package obj import ( - "bufio" "bytes" "fmt" - "io" "log" "os" "strings" @@ -26,144 +24,6 @@ func Cputime() float64 { return time.Since(start).Seconds() } -type Biobuf struct { - f *os.File - r *bufio.Reader - w *bufio.Writer - linelen int -} - -func (b *Biobuf) Reader() *bufio.Reader { return b.r } - -func Bopenw(name string) (*Biobuf, error) { - f, err := os.Create(name) - if err != nil { - return nil, err - } - return &Biobuf{f: f, w: bufio.NewWriter(f)}, nil -} - -func Bopenr(name string) (*Biobuf, error) { - f, err := os.Open(name) - if err != nil { - return nil, err - } - return &Biobuf{f: f, r: bufio.NewReader(f)}, nil -} - -func Binitw(w io.Writer) *Biobuf { - return &Biobuf{w: bufio.NewWriter(w)} -} - -func Binitr(r io.Reader) *Biobuf { - return &Biobuf{r: bufio.NewReader(r)} -} - -func (b *Biobuf) Write(p []byte) (int, error) { - return b.w.Write(p) -} - -func Bwritestring(b *Biobuf, p string) (int, error) { - return b.w.WriteString(p) -} - -func Bseek(b *Biobuf, offset int64, whence int) int64 { - if b.w != nil { - if err := b.w.Flush(); err != nil { - log.Fatalf("writing output: %v", err) - } - } else if b.r != nil { - if whence == 1 { - offset -= int64(b.r.Buffered()) - } - } - off, err := b.f.Seek(offset, whence) - if err != nil { - log.Fatalf("seeking in output: %v", err) - } - if b.r != nil { - b.r.Reset(b.f) - } - return off -} - -func Boffset(b *Biobuf) int64 { - if b.w != nil { - if err := b.w.Flush(); err != nil { - log.Fatalf("writing output: %v", err) - } - } - off, err := b.f.Seek(0, 1) - if err != nil { - log.Fatalf("seeking in output [0, 1]: %v", err) - } - if b.r != nil { - off -= int64(b.r.Buffered()) - } - return off -} - -func (b *Biobuf) Flush() error { - return b.w.Flush() -} - -func Bputc(b *Biobuf, c byte) { - b.w.WriteByte(c) -} - -const Beof = -1 - -func Bread(b *Biobuf, p []byte) int { - n, err := io.ReadFull(b.r, p) - if n == 0 { - if err != nil && err != io.EOF { - n = -1 - } - } - return n -} - -func Bgetc(b *Biobuf) int { - c, err := b.r.ReadByte() - if err != nil { - return -1 - } - return int(c) -} - -func (b *Biobuf) Read(p []byte) (int, error) { - return b.r.Read(p) -} - -func (b *Biobuf) Peek(n int) ([]byte, error) { - return b.r.Peek(n) -} - -func Brdline(b *Biobuf, delim int) string { - s, err := b.r.ReadBytes(byte(delim)) - if err != nil { - log.Fatalf("reading input: %v", err) - } - b.linelen = len(s) - return string(s) -} - -func Blinelen(b *Biobuf) int { - return b.linelen -} - -func Bterm(b *Biobuf) error { - var err error - if b.w != nil { - err = b.w.Flush() - } - err1 := b.f.Close() - if err == nil { - err = err1 - } - return err -} - func envOr(key, value string) string { if x := os.Getenv(key); x != "" { return x diff --git a/src/cmd/link/internal/ld/ar.go b/src/cmd/link/internal/ld/ar.go index d07756071d..205773c7f8 100644 --- a/src/cmd/link/internal/ld/ar.go +++ b/src/cmd/link/internal/ld/ar.go @@ -31,6 +31,7 @@ package ld import ( + "cmd/internal/bio" "cmd/internal/obj" "encoding/binary" "fmt" @@ -62,7 +63,7 @@ type ArHdr struct { // define them. This is used for the compiler support library // libgcc.a. func hostArchive(name string) { - f, err := obj.Bopenr(name) + f, err := bio.Open(name) if err != nil { if os.IsNotExist(err) { // It's OK if we don't have a libgcc file at all. @@ -73,15 +74,15 @@ func hostArchive(name string) { } Exitf("cannot open file %s: %v", name, err) } - defer obj.Bterm(f) + defer f.Close() magbuf := make([]byte, len(ARMAG)) - if obj.Bread(f, magbuf) != len(magbuf) { + if bio.Bread(f, magbuf) != len(magbuf) { Exitf("file %s too short", name) } var arhdr ArHdr - l := nextar(f, obj.Boffset(f), &arhdr) + l := nextar(f, bio.Boffset(f), &arhdr) if l <= 0 { Exitf("%s missing armap", name) } @@ -117,7 +118,7 @@ func hostArchive(name string) { l = atolwhex(arhdr.size) h := ldobj(f, "libgcc", l, pname, name, ArchiveObj) - obj.Bseek(f, h.off, 0) + bio.Bseek(f, h.off, 0) h.ld(f, h.pkg, h.length, h.pn) } @@ -130,7 +131,7 @@ func hostArchive(name string) { type archiveMap map[string]uint64 // readArmap reads the archive symbol map. -func readArmap(filename string, f *obj.Biobuf, arhdr ArHdr) archiveMap { +func readArmap(filename string, f *bio.Buf, arhdr ArHdr) archiveMap { is64 := arhdr.name == "/SYM64/" wordSize := 4 if is64 { @@ -139,7 +140,7 @@ func readArmap(filename string, f *obj.Biobuf, arhdr ArHdr) archiveMap { l := atolwhex(arhdr.size) contents := make([]byte, l) - if obj.Bread(f, contents) != int(l) { + if bio.Bread(f, contents) != int(l) { Exitf("short read from %s", filename) } diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go index 027e05d845..8bafaffd7c 100644 --- a/src/cmd/link/internal/ld/go.go +++ b/src/cmd/link/internal/ld/go.go @@ -8,6 +8,7 @@ package ld import ( "bytes" + "cmd/internal/bio" "cmd/internal/obj" "fmt" "os" @@ -26,7 +27,7 @@ func expandpkg(t0 string, pkg string) string { // once the dust settles, try to move some code to // libmach, so that other linkers and ar can share. -func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int) { +func ldpkg(f *bio.Buf, pkg string, length int64, filename string, whence int) { var p0, p1 int if Debug['g'] != 0 { @@ -48,7 +49,7 @@ func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int) } bdata := make([]byte, length) - if int64(obj.Bread(f, bdata)) != length { + if int64(bio.Bread(f, bdata)) != length { fmt.Fprintf(os.Stderr, "%s: short pkg read %s\n", os.Args[0], filename) if Debug['u'] != 0 { errorexit() diff --git a/src/cmd/link/internal/ld/ldelf.go b/src/cmd/link/internal/ld/ldelf.go index 485599be62..eafc6930d5 100644 --- a/src/cmd/link/internal/ld/ldelf.go +++ b/src/cmd/link/internal/ld/ldelf.go @@ -2,6 +2,7 @@ package ld import ( "bytes" + "cmd/internal/bio" "cmd/internal/obj" "cmd/internal/sys" "encoding/binary" @@ -267,7 +268,7 @@ type ElfSect struct { } type ElfObj struct { - f *obj.Biobuf + f *bio.Buf base int64 // offset in f where ELF begins length int64 // length of ELF is64 int @@ -446,13 +447,13 @@ func parseArmAttributes(e binary.ByteOrder, data []byte) { } } -func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) { +func ldelf(f *bio.Buf, pkg string, length int64, pn string) { if Debug['v'] != 0 { fmt.Fprintf(&Bso, "%5.2f ldelf %s\n", obj.Cputime(), pn) } Ctxt.IncVersion() - base := int32(obj.Boffset(f)) + base := int32(bio.Boffset(f)) var add uint64 var e binary.ByteOrder @@ -475,7 +476,7 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) { var sect *ElfSect var sym ElfSym var symbols []*LSym - if obj.Bread(f, hdrbuf[:]) != len(hdrbuf) { + if bio.Bread(f, hdrbuf[:]) != len(hdrbuf) { goto bad } hdr = new(ElfHdrBytes) @@ -600,7 +601,7 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) { elfobj.nsect = uint(elfobj.shnum) for i := 0; uint(i) < elfobj.nsect; i++ { - if obj.Bseek(f, int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 { + if bio.Bseek(f, int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 { goto bad } sect = &elfobj.sect[i] @@ -986,7 +987,7 @@ func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) { sect.base = make([]byte, sect.size) err = fmt.Errorf("short read") - if obj.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || obj.Bread(elfobj.f, sect.base) != len(sect.base) { + if bio.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || bio.Bread(elfobj.f, sect.base) != len(sect.base) { return err } diff --git a/src/cmd/link/internal/ld/ldmacho.go b/src/cmd/link/internal/ld/ldmacho.go index 9fbb2123af..6376116d04 100644 --- a/src/cmd/link/internal/ld/ldmacho.go +++ b/src/cmd/link/internal/ld/ldmacho.go @@ -1,6 +1,7 @@ package ld import ( + "cmd/internal/bio" "cmd/internal/obj" "cmd/internal/sys" "encoding/binary" @@ -42,7 +43,7 @@ const ( ) type LdMachoObj struct { - f *obj.Biobuf + f *bio.Buf base int64 // off in f where Mach-O begins length int64 // length of Mach-O is64 bool @@ -298,7 +299,7 @@ func macholoadrel(m *LdMachoObj, sect *LdMachoSect) int { rel := make([]LdMachoRel, sect.nreloc) n := int(sect.nreloc * 8) buf := make([]byte, n) - if obj.Bseek(m.f, m.base+int64(sect.reloff), 0) < 0 || obj.Bread(m.f, buf) != n { + if bio.Bseek(m.f, m.base+int64(sect.reloff), 0) < 0 || bio.Bread(m.f, buf) != n { return -1 } var p []byte @@ -344,7 +345,7 @@ func macholoaddsym(m *LdMachoObj, d *LdMachoDysymtab) int { n := int(d.nindirectsyms) p := make([]byte, n*4) - if obj.Bseek(m.f, m.base+int64(d.indirectsymoff), 0) < 0 || obj.Bread(m.f, p) != len(p) { + if bio.Bseek(m.f, m.base+int64(d.indirectsymoff), 0) < 0 || bio.Bread(m.f, p) != len(p) { return -1 } @@ -361,7 +362,7 @@ func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int { } strbuf := make([]byte, symtab.strsize) - if obj.Bseek(m.f, m.base+int64(symtab.stroff), 0) < 0 || obj.Bread(m.f, strbuf) != len(strbuf) { + if bio.Bseek(m.f, m.base+int64(symtab.stroff), 0) < 0 || bio.Bread(m.f, strbuf) != len(strbuf) { return -1 } @@ -371,7 +372,7 @@ func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int { } n := int(symtab.nsym * uint32(symsize)) symbuf := make([]byte, n) - if obj.Bseek(m.f, m.base+int64(symtab.symoff), 0) < 0 || obj.Bread(m.f, symbuf) != len(symbuf) { + if bio.Bseek(m.f, m.base+int64(symtab.symoff), 0) < 0 || bio.Bread(m.f, symbuf) != len(symbuf) { return -1 } sym := make([]LdMachoSym, symtab.nsym) @@ -401,7 +402,7 @@ func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int { return 0 } -func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) { +func ldmacho(f *bio.Buf, pkg string, length int64, pn string) { var err error var j int var is64 bool @@ -431,8 +432,8 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) { var name string Ctxt.IncVersion() - base := obj.Boffset(f) - if obj.Bread(f, hdr[:]) != len(hdr) { + base := bio.Boffset(f) + if bio.Bread(f, hdr[:]) != len(hdr) { goto bad } @@ -455,7 +456,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) { if is64 { var tmp [4]uint8 - obj.Bread(f, tmp[:4]) // skip reserved word in header + bio.Bread(f, tmp[:4]) // skip reserved word in header } m = new(LdMachoObj) @@ -493,7 +494,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) { m.cmd = make([]LdMachoCmd, ncmd) off = uint32(len(hdr)) cmdp = make([]byte, cmdsz) - if obj.Bread(f, cmdp) != len(cmdp) { + if bio.Bread(f, cmdp) != len(cmdp) { err = fmt.Errorf("reading cmds: %v", err) goto bad } @@ -556,7 +557,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) { } dat = make([]byte, c.seg.filesz) - if obj.Bseek(f, m.base+int64(c.seg.fileoff), 0) < 0 || obj.Bread(f, dat) != len(dat) { + if bio.Bseek(f, m.base+int64(c.seg.fileoff), 0) < 0 || bio.Bread(f, dat) != len(dat) { err = fmt.Errorf("cannot load object data: %v", err) goto bad } diff --git a/src/cmd/link/internal/ld/ldpe.go b/src/cmd/link/internal/ld/ldpe.go index ea0c482838..e97e842e7f 100644 --- a/src/cmd/link/internal/ld/ldpe.go +++ b/src/cmd/link/internal/ld/ldpe.go @@ -5,6 +5,7 @@ package ld import ( + "cmd/internal/bio" "cmd/internal/obj" "cmd/internal/sys" "encoding/binary" @@ -117,7 +118,7 @@ type PeSect struct { } type PeObj struct { - f *obj.Biobuf + f *bio.Buf name string base uint32 sect []PeSect @@ -128,14 +129,14 @@ type PeObj struct { snames []byte } -func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) { +func ldpe(f *bio.Buf, pkg string, length int64, pn string) { if Debug['v'] != 0 { fmt.Fprintf(&Bso, "%5.2f ldpe %s\n", obj.Cputime(), pn) } var sect *PeSect Ctxt.IncVersion() - base := int32(obj.Boffset(f)) + base := int32(bio.Boffset(f)) peobj := new(PeObj) peobj.f = f @@ -173,15 +174,15 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) { // TODO return error if found .cormeta // load string table - obj.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) + bio.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) - if obj.Bread(f, symbuf[:4]) != 4 { + if bio.Bread(f, symbuf[:4]) != 4 { goto bad } l = Le32(symbuf[:]) peobj.snames = make([]byte, l) - obj.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) - if obj.Bread(f, peobj.snames) != len(peobj.snames) { + bio.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) + if bio.Bread(f, peobj.snames) != len(peobj.snames) { goto bad } @@ -201,10 +202,10 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) { peobj.pesym = make([]PeSym, peobj.fh.NumberOfSymbols) peobj.npesym = uint(peobj.fh.NumberOfSymbols) - obj.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable), 0) + bio.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable), 0) for i := 0; uint32(i) < peobj.fh.NumberOfSymbols; i += numaux + 1 { - obj.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(i), 0) - if obj.Bread(f, symbuf[:]) != len(symbuf) { + bio.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(i), 0) + if bio.Bread(f, symbuf[:]) != len(symbuf) { goto bad } @@ -289,10 +290,10 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) { } r = make([]Reloc, rsect.sh.NumberOfRelocations) - obj.Bseek(f, int64(peobj.base)+int64(rsect.sh.PointerToRelocations), 0) + bio.Bseek(f, int64(peobj.base)+int64(rsect.sh.PointerToRelocations), 0) for j = 0; j < int(rsect.sh.NumberOfRelocations); j++ { rp = &r[j] - if obj.Bread(f, symbuf[:10]) != 10 { + if bio.Bread(f, symbuf[:10]) != 10 { goto bad } rva := Le32(symbuf[0:]) @@ -465,7 +466,7 @@ func pemap(peobj *PeObj, sect *PeSect) int { if sect.sh.PointerToRawData == 0 { // .bss doesn't have data in object file return 0 } - if obj.Bseek(peobj.f, int64(peobj.base)+int64(sect.sh.PointerToRawData), 0) < 0 || obj.Bread(peobj.f, sect.base) != len(sect.base) { + if bio.Bseek(peobj.f, int64(peobj.base)+int64(sect.sh.PointerToRawData), 0) < 0 || bio.Bread(peobj.f, sect.base) != len(sect.base) { return -1 } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 305a3bc0db..789eaef1a5 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -33,6 +33,7 @@ package ld import ( "bufio" "bytes" + "cmd/internal/bio" "cmd/internal/obj" "cmd/internal/sys" "crypto/sha1" @@ -240,7 +241,7 @@ const ( var ( headstring string // buffered output - Bso obj.Biobuf + Bso bio.Buf ) type outBuf struct { @@ -738,13 +739,13 @@ func loadlib() { * look for the next file in an archive. * adapted from libmach. */ -func nextar(bp *obj.Biobuf, off int64, a *ArHdr) int64 { +func nextar(bp *bio.Buf, off int64, a *ArHdr) int64 { if off&1 != 0 { off++ } - obj.Bseek(bp, off, 0) + bio.Bseek(bp, off, 0) buf := make([]byte, SAR_HDR) - if n := obj.Bread(bp, buf); n < len(buf) { + if n := bio.Bread(bp, buf); n < len(buf) { if n >= 0 { return 0 } @@ -773,25 +774,25 @@ func objfile(lib *Library) { fmt.Fprintf(&Bso, "%5.2f ldobj: %s (%s)\n", obj.Cputime(), lib.File, pkg) } Bso.Flush() - f, err := obj.Bopenr(lib.File) + f, err := bio.Open(lib.File) if err != nil { Exitf("cannot open file %s: %v", lib.File, err) } magbuf := make([]byte, len(ARMAG)) - if obj.Bread(f, magbuf) != len(magbuf) || !strings.HasPrefix(string(magbuf), ARMAG) { + if bio.Bread(f, magbuf) != len(magbuf) || !strings.HasPrefix(string(magbuf), ARMAG) { /* load it as a regular file */ - l := obj.Bseek(f, 0, 2) + l := bio.Bseek(f, 0, 2) - obj.Bseek(f, 0, 0) + bio.Bseek(f, 0, 0) ldobj(f, pkg, l, lib.File, lib.File, FileObj) - obj.Bterm(f) + f.Close() return } /* process __.PKGDEF */ - off := obj.Boffset(f) + off := bio.Boffset(f) var arhdr ArHdr l := nextar(f, off, &arhdr) @@ -807,12 +808,12 @@ func objfile(lib *Library) { } if Buildmode == BuildmodeShared { - before := obj.Boffset(f) + before := bio.Boffset(f) pkgdefBytes := make([]byte, atolwhex(arhdr.size)) - obj.Bread(f, pkgdefBytes) + bio.Bread(f, pkgdefBytes) hash := sha1.Sum(pkgdefBytes) lib.hash = hash[:] - obj.Bseek(f, before, 0) + bio.Bseek(f, before, 0) } off += l @@ -848,11 +849,11 @@ func objfile(lib *Library) { } out: - obj.Bterm(f) + f.Close() } type Hostobj struct { - ld func(*obj.Biobuf, string, int64, string) + ld func(*bio.Buf, string, int64, string) pkg string pn string file string @@ -873,7 +874,7 @@ var internalpkg = []string{ "runtime/msan", } -func ldhostobj(ld func(*obj.Biobuf, string, int64, string), f *obj.Biobuf, pkg string, length int64, pn string, file string) *Hostobj { +func ldhostobj(ld func(*bio.Buf, string, int64, string), f *bio.Buf, pkg string, length int64, pn string, file string) *Hostobj { isinternal := false for i := 0; i < len(internalpkg); i++ { if pkg == internalpkg[i] { @@ -904,26 +905,26 @@ func ldhostobj(ld func(*obj.Biobuf, string, int64, string), f *obj.Biobuf, pkg s h.pkg = pkg h.pn = pn h.file = file - h.off = obj.Boffset(f) + h.off = bio.Boffset(f) h.length = length return h } func hostobjs() { - var f *obj.Biobuf + var f *bio.Buf var h *Hostobj for i := 0; i < len(hostobj); i++ { h = &hostobj[i] var err error - f, err = obj.Bopenr(h.file) + f, err = bio.Open(h.file) if f == nil { Exitf("cannot reopen %s: %v", h.pn, err) } - obj.Bseek(f, h.off, 0) + bio.Bseek(f, h.off, 0) h.ld(f, h.pkg, h.length, h.pn) - obj.Bterm(f) + f.Close() } } @@ -1265,15 +1266,15 @@ func hostlinkArchArgs() []string { // ldobj loads an input object. If it is a host object (an object // compiled by a non-Go compiler) it returns the Hostobj pointer. If // it is a Go object, it returns nil. -func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, whence int) *Hostobj { - eof := obj.Boffset(f) + length +func ldobj(f *bio.Buf, pkg string, length int64, pn string, file string, whence int) *Hostobj { + eof := bio.Boffset(f) + length - start := obj.Boffset(f) - c1 := obj.Bgetc(f) - c2 := obj.Bgetc(f) - c3 := obj.Bgetc(f) - c4 := obj.Bgetc(f) - obj.Bseek(f, start, 0) + start := bio.Boffset(f) + c1 := bio.Bgetc(f) + c2 := bio.Bgetc(f) + c3 := bio.Bgetc(f) + c4 := bio.Bgetc(f) + bio.Bseek(f, start, 0) magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4) if magic == 0x7f454c46 { // \x7F E L F @@ -1289,12 +1290,8 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when } /* check the header */ - line := obj.Brdline(f, '\n') + line := bio.Brdline(f, '\n') if line == "" { - if obj.Blinelen(f) > 0 { - Diag("%s: not an object file", pn) - return nil - } Diag("truncated object file: %s", pn) return nil } @@ -1337,28 +1334,28 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when } /* skip over exports and other info -- ends with \n!\n */ - import0 := obj.Boffset(f) + import0 := bio.Boffset(f) c1 = '\n' // the last line ended in \n - c2 = obj.Bgetc(f) - c3 = obj.Bgetc(f) + c2 = bio.Bgetc(f) + c3 = bio.Bgetc(f) for c1 != '\n' || c2 != '!' || c3 != '\n' { c1 = c2 c2 = c3 - c3 = obj.Bgetc(f) - if c3 == obj.Beof { + c3 = bio.Bgetc(f) + if c3 == bio.EOF { Diag("truncated object file: %s", pn) return nil } } - import1 := obj.Boffset(f) + import1 := bio.Boffset(f) - obj.Bseek(f, import0, 0) + bio.Bseek(f, import0, 0) ldpkg(f, pkg, import1-import0-2, pn, whence) // -2 for !\n - obj.Bseek(f, import1, 0) + bio.Bseek(f, import1, 0) - LoadObjFile(Ctxt, f, pkg, eof-obj.Boffset(f), pn) + LoadObjFile(Ctxt, f, pkg, eof-bio.Boffset(f), pn) return nil } diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go index f0811389d2..d3f9ed3703 100644 --- a/src/cmd/link/internal/ld/link.go +++ b/src/cmd/link/internal/ld/link.go @@ -31,7 +31,7 @@ package ld import ( - "cmd/internal/obj" + "cmd/internal/bio" "cmd/internal/sys" "debug/elf" "fmt" @@ -165,7 +165,7 @@ type Link struct { Headtype int Arch *sys.Arch Debugvlog int32 - Bso *obj.Biobuf + Bso *bio.Buf Windows int32 Goroot string diff --git a/src/cmd/link/internal/ld/objfile.go b/src/cmd/link/internal/ld/objfile.go index 8a406d17a6..6f177861f0 100644 --- a/src/cmd/link/internal/ld/objfile.go +++ b/src/cmd/link/internal/ld/objfile.go @@ -110,6 +110,7 @@ package ld import ( "bufio" "bytes" + "cmd/internal/bio" "cmd/internal/obj" "io" "log" @@ -146,8 +147,8 @@ type objReader struct { file []*LSym } -func LoadObjFile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) { - start := obj.Boffset(f) +func LoadObjFile(ctxt *Link, f *bio.Buf, pkg string, length int64, pn string) { + start := bio.Boffset(f) r := &objReader{ rd: f.Reader(), pkg: pkg, @@ -156,8 +157,8 @@ func LoadObjFile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) dupSym: &LSym{Name: ".dup"}, } r.loadObjFile() - if obj.Boffset(f) != start+length { - log.Fatalf("%s: unexpected end at %d, want %d", pn, int64(obj.Boffset(f)), int64(start+length)) + if bio.Boffset(f) != start+length { + log.Fatalf("%s: unexpected end at %d, want %d", pn, int64(bio.Boffset(f)), int64(start+length)) } } diff --git a/src/cmd/link/internal/ld/pobj.go b/src/cmd/link/internal/ld/pobj.go index b9902a5e5e..bb48f13185 100644 --- a/src/cmd/link/internal/ld/pobj.go +++ b/src/cmd/link/internal/ld/pobj.go @@ -31,6 +31,7 @@ package ld import ( + "cmd/internal/bio" "cmd/internal/obj" "cmd/internal/sys" "flag" @@ -49,7 +50,7 @@ func Ldmain() { Ctxt.Diag = Diag Ctxt.Bso = &Bso - Bso = *obj.Binitw(os.Stdout) + Bso = *bio.BufWriter(os.Stdout) Debug = [128]int{} nerrors = 0 outfile = "" -- cgit v1.3 From 8f2edf11998a30b497586ac0e9f75036a318280a Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Fri, 8 Apr 2016 19:14:03 +1000 Subject: cmd: replace bio.Buf with bio.Reader and bio.Writer Replace the bidirectional bio.Buf type with a pair of unidirectional buffered seekable Reader and Writers. Change-Id: I86664a06f93c94595dc67c2cbd21356feb6680ef Reviewed-on: https://go-review.googlesource.com/21720 Reviewed-by: Brad Fitzpatrick Run-TryBot: Dave Cheney TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/bexport.go | 4 +- src/cmd/compile/internal/gc/go.go | 4 +- src/cmd/compile/internal/gc/obj.go | 16 ++-- src/cmd/internal/bio/buf.go | 137 +++++++++++++++++++-------------- src/cmd/internal/obj/link.go | 2 +- src/cmd/internal/obj/objfile.go | 6 +- src/cmd/link/internal/ld/ar.go | 6 +- src/cmd/link/internal/ld/go.go | 2 +- src/cmd/link/internal/ld/ldelf.go | 10 +-- src/cmd/link/internal/ld/ldmacho.go | 16 ++-- src/cmd/link/internal/ld/ldpe.go | 18 ++--- src/cmd/link/internal/ld/lib.go | 49 ++++++------ src/cmd/link/internal/ld/link.go | 7 +- src/cmd/link/internal/ld/objfile.go | 8 +- 14 files changed, 154 insertions(+), 131 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index 909ff14982..bb0a34e67b 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -124,7 +124,7 @@ const exportVersion = "v0" const exportInlined = true // default: true type exporter struct { - out *bio.Buf + out *bio.Writer pkgIndex map[*Pkg]int typIndex map[*Type]int inlined []*Func @@ -136,7 +136,7 @@ type exporter struct { } // export writes the exportlist for localpkg to out and returns the number of bytes written. -func export(out *bio.Buf, trace bool) int { +func export(out *bio.Writer, trace bool) int { p := exporter{ out: out, pkgIndex: make(map[*Pkg]int), diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index cd9db38fb4..ec7e219d95 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -133,7 +133,7 @@ var infile string var outfile string -var bout *bio.Buf +var bout *bio.Writer var nerrors int @@ -288,7 +288,7 @@ var Ctxt *obj.Link var writearchive int -var bstdout *bio.Buf +var bstdout *bio.Writer var Nacl bool diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 3920e25224..23c8be645c 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -37,7 +37,7 @@ func dumpobj() { bout.WriteString("!\n") arhdr = [ArhdrSize]byte{} bout.Write(arhdr[:]) - startobj = bio.Boffset(bout) + startobj = bout.Offset() } fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) @@ -45,19 +45,19 @@ func dumpobj() { if writearchive != 0 { bout.Flush() - size := bio.Boffset(bout) - startobj + size := bout.Offset() - startobj if size&1 != 0 { bout.WriteByte(0) } - bio.Bseek(bout, startobj-ArhdrSize, 0) + bout.Seek(startobj-ArhdrSize, 0) formathdr(arhdr[:], "__.PKGDEF", size) bout.Write(arhdr[:]) bout.Flush() - bio.Bseek(bout, startobj+size+(size&1), 0) + bout.Seek(startobj+size+(size&1), 0) arhdr = [ArhdrSize]byte{} bout.Write(arhdr[:]) - startobj = bio.Boffset(bout) + startobj = bout.Offset() fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) } @@ -92,11 +92,11 @@ func dumpobj() { if writearchive != 0 { bout.Flush() - size := bio.Boffset(bout) - startobj + size := bout.Offset() - startobj if size&1 != 0 { bout.WriteByte(0) } - bio.Bseek(bout, startobj-ArhdrSize, 0) + bout.Seek(startobj-ArhdrSize, 0) formathdr(arhdr[:], "_go_.o", size) bout.Write(arhdr[:]) } @@ -133,7 +133,7 @@ func dumpglobls() { funcsyms = nil } -func Bputname(b *bio.Buf, s *obj.LSym) { +func Bputname(b *bio.Writer, s *obj.LSym) { b.WriteString(s.Name) b.WriteByte(0) } diff --git a/src/cmd/internal/bio/buf.go b/src/cmd/internal/bio/buf.go index a1df26ca9c..0bd4658cdd 100644 --- a/src/cmd/internal/bio/buf.go +++ b/src/cmd/internal/bio/buf.go @@ -14,94 +14,116 @@ import ( const EOF = -1 -// Buf implements a seekable buffered I/O abstraction. -type Buf struct { +// Reader implements a seekable buffered io.Reader. +type Reader struct { f *os.File r *bufio.Reader +} + +// Writer implements a seekable buffered io.Writer. +type Writer struct { + f *os.File w *bufio.Writer } -func (b *Buf) Reader() *bufio.Reader { return b.r } -func (b *Buf) Writer() *bufio.Writer { return b.w } +// Reader returns this Reader's underlying bufio.Reader. +func (r *Reader) Reader() *bufio.Reader { return r.r } -func Create(name string) (*Buf, error) { +// Writer returns this Writer's underlying bufio.Writer. +func (w *Writer) Writer() *bufio.Writer { return w.w } + +// Create creates the file named name and returns a Writer +// for that file. +func Create(name string) (*Writer, error) { f, err := os.Create(name) if err != nil { return nil, err } - return &Buf{f: f, w: bufio.NewWriter(f)}, nil + return &Writer{f: f, w: bufio.NewWriter(f)}, nil } -func Open(name string) (*Buf, error) { +// Open returns a Reader for the file named name. +func Open(name string) (*Reader, error) { f, err := os.Open(name) if err != nil { return nil, err } - return &Buf{f: f, r: bufio.NewReader(f)}, nil + return &Reader{f: f, r: bufio.NewReader(f)}, nil } -func BufWriter(w io.Writer) *Buf { - return &Buf{w: bufio.NewWriter(w)} +// BufWriter returns a Writer on top of w. +// TODO(dfc) remove this method and replace caller with bufio.Writer. +func BufWriter(w io.Writer) *Writer { + return &Writer{w: bufio.NewWriter(w)} } -func BufReader(r io.Reader) *Buf { - return &Buf{r: bufio.NewReader(r)} +// BufWriter returns a Reader on top of r. +// TODO(dfc) remove this method and replace caller with bufio.Reader. +func BufReader(r io.Reader) *Reader { + return &Reader{r: bufio.NewReader(r)} } -func (b *Buf) Write(p []byte) (int, error) { - return b.w.Write(p) +func (w *Writer) Write(p []byte) (int, error) { + return w.w.Write(p) } -func (b *Buf) WriteString(p string) (int, error) { - return b.w.WriteString(p) +func (w *Writer) WriteString(p string) (int, error) { + return w.w.WriteString(p) } -func Bseek(b *Buf, offset int64, whence int) int64 { - if b.w != nil { - if err := b.w.Flush(); err != nil { - log.Fatalf("writing output: %v", err) - } - } else if b.r != nil { - if whence == 1 { - offset -= int64(b.r.Buffered()) - } +func (r *Reader) Seek(offset int64, whence int) int64 { + if whence == 1 { + offset -= int64(r.r.Buffered()) } - off, err := b.f.Seek(offset, whence) + off, err := r.f.Seek(offset, whence) if err != nil { log.Fatalf("seeking in output: %v", err) } - if b.r != nil { - b.r.Reset(b.f) - } + r.r.Reset(r.f) return off } -func Boffset(b *Buf) int64 { - if b.w != nil { - if err := b.w.Flush(); err != nil { - log.Fatalf("writing output: %v", err) - } +func (w *Writer) Seek(offset int64, whence int) int64 { + if err := w.w.Flush(); err != nil { + log.Fatalf("writing output: %v", err) } - off, err := b.f.Seek(0, 1) + off, err := w.f.Seek(offset, whence) + if err != nil { + log.Fatalf("seeking in output: %v", err) + } + return off +} + +func (r *Reader) Offset() int64 { + off, err := r.f.Seek(0, 1) if err != nil { log.Fatalf("seeking in output [0, 1]: %v", err) } - if b.r != nil { - off -= int64(b.r.Buffered()) + off -= int64(r.r.Buffered()) + return off +} + +func (w *Writer) Offset() int64 { + if err := w.w.Flush(); err != nil { + log.Fatalf("writing output: %v", err) + } + off, err := w.f.Seek(0, 1) + if err != nil { + log.Fatalf("seeking in output [0, 1]: %v", err) } return off } -func (b *Buf) Flush() error { - return b.w.Flush() +func (w *Writer) Flush() error { + return w.w.Flush() } -func (b *Buf) WriteByte(c byte) error { - return b.w.WriteByte(c) +func (w *Writer) WriteByte(c byte) error { + return w.w.WriteByte(c) } -func Bread(b *Buf, p []byte) int { - n, err := io.ReadFull(b.r, p) +func Bread(r *Reader, p []byte) int { + n, err := io.ReadFull(r.r, p) if n == 0 { if err != nil && err != io.EOF { n = -1 @@ -110,8 +132,8 @@ func Bread(b *Buf, p []byte) int { return n } -func Bgetc(b *Buf) int { - c, err := b.r.ReadByte() +func Bgetc(r *Reader) int { + c, err := r.r.ReadByte() if err != nil { if err != io.EOF { log.Fatalf("reading input: %v", err) @@ -121,28 +143,29 @@ func Bgetc(b *Buf) int { return int(c) } -func (b *Buf) Read(p []byte) (int, error) { - return b.r.Read(p) +func (r *Reader) Read(p []byte) (int, error) { + return r.r.Read(p) } -func (b *Buf) Peek(n int) ([]byte, error) { - return b.r.Peek(n) +func (r *Reader) Peek(n int) ([]byte, error) { + return r.r.Peek(n) } -func Brdline(b *Buf, delim int) string { - s, err := b.r.ReadBytes(byte(delim)) +func Brdline(r *Reader, delim int) string { + s, err := r.r.ReadBytes(byte(delim)) if err != nil { log.Fatalf("reading input: %v", err) } return string(s) } -func (b *Buf) Close() error { - var err error - if b.w != nil { - err = b.w.Flush() - } - err1 := b.f.Close() +func (r *Reader) Close() error { + return r.f.Close() +} + +func (w *Writer) Close() error { + err := w.w.Flush() + err1 := w.f.Close() if err == nil { err = err1 } diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 2c81ca2f08..c48c3d807f 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -629,7 +629,7 @@ type Link struct { Flag_shared int32 Flag_dynlink bool Flag_optimize bool - Bso *bio.Buf + Bso *bio.Writer Pathname string Goroot string Goroot_final string diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 405cbf446a..ed6d75eba3 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -121,7 +121,7 @@ import ( // The Go and C compilers, and the assembler, call writeobj to write // out a Go object file. The linker does not call this; the linker // does not write out object files. -func Writeobjdirect(ctxt *Link, b *bio.Buf) { +func Writeobjdirect(ctxt *Link, b *bio.Writer) { Flushplist(ctxt) WriteObjFile(ctxt, b) } @@ -374,7 +374,7 @@ func (w *objWriter) writeLengths() { w.writeInt(int64(w.nFile)) } -func newObjWriter(ctxt *Link, b *bio.Buf) *objWriter { +func newObjWriter(ctxt *Link, b *bio.Writer) *objWriter { return &objWriter{ ctxt: ctxt, wr: b.Writer(), @@ -383,7 +383,7 @@ func newObjWriter(ctxt *Link, b *bio.Buf) *objWriter { } } -func WriteObjFile(ctxt *Link, b *bio.Buf) { +func WriteObjFile(ctxt *Link, b *bio.Writer) { w := newObjWriter(ctxt, b) // Magic header diff --git a/src/cmd/link/internal/ld/ar.go b/src/cmd/link/internal/ld/ar.go index 205773c7f8..6a0aeb121f 100644 --- a/src/cmd/link/internal/ld/ar.go +++ b/src/cmd/link/internal/ld/ar.go @@ -82,7 +82,7 @@ func hostArchive(name string) { } var arhdr ArHdr - l := nextar(f, bio.Boffset(f), &arhdr) + l := nextar(f, f.Offset(), &arhdr) if l <= 0 { Exitf("%s missing armap", name) } @@ -118,7 +118,7 @@ func hostArchive(name string) { l = atolwhex(arhdr.size) h := ldobj(f, "libgcc", l, pname, name, ArchiveObj) - bio.Bseek(f, h.off, 0) + f.Seek(h.off, 0) h.ld(f, h.pkg, h.length, h.pn) } @@ -131,7 +131,7 @@ func hostArchive(name string) { type archiveMap map[string]uint64 // readArmap reads the archive symbol map. -func readArmap(filename string, f *bio.Buf, arhdr ArHdr) archiveMap { +func readArmap(filename string, f *bio.Reader, arhdr ArHdr) archiveMap { is64 := arhdr.name == "/SYM64/" wordSize := 4 if is64 { diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go index 8bafaffd7c..5dad90dae6 100644 --- a/src/cmd/link/internal/ld/go.go +++ b/src/cmd/link/internal/ld/go.go @@ -27,7 +27,7 @@ func expandpkg(t0 string, pkg string) string { // once the dust settles, try to move some code to // libmach, so that other linkers and ar can share. -func ldpkg(f *bio.Buf, pkg string, length int64, filename string, whence int) { +func ldpkg(f *bio.Reader, pkg string, length int64, filename string, whence int) { var p0, p1 int if Debug['g'] != 0 { diff --git a/src/cmd/link/internal/ld/ldelf.go b/src/cmd/link/internal/ld/ldelf.go index eafc6930d5..55884c07a2 100644 --- a/src/cmd/link/internal/ld/ldelf.go +++ b/src/cmd/link/internal/ld/ldelf.go @@ -268,7 +268,7 @@ type ElfSect struct { } type ElfObj struct { - f *bio.Buf + f *bio.Reader base int64 // offset in f where ELF begins length int64 // length of ELF is64 int @@ -447,13 +447,13 @@ func parseArmAttributes(e binary.ByteOrder, data []byte) { } } -func ldelf(f *bio.Buf, pkg string, length int64, pn string) { +func ldelf(f *bio.Reader, pkg string, length int64, pn string) { if Debug['v'] != 0 { fmt.Fprintf(&Bso, "%5.2f ldelf %s\n", obj.Cputime(), pn) } Ctxt.IncVersion() - base := int32(bio.Boffset(f)) + base := f.Offset() var add uint64 var e binary.ByteOrder @@ -601,7 +601,7 @@ func ldelf(f *bio.Buf, pkg string, length int64, pn string) { elfobj.nsect = uint(elfobj.shnum) for i := 0; uint(i) < elfobj.nsect; i++ { - if bio.Bseek(f, int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 { + if f.Seek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 { goto bad } sect = &elfobj.sect[i] @@ -987,7 +987,7 @@ func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) { sect.base = make([]byte, sect.size) err = fmt.Errorf("short read") - if bio.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || bio.Bread(elfobj.f, sect.base) != len(sect.base) { + if elfobj.f.Seek(int64(uint64(elfobj.base)+sect.off), 0) < 0 || bio.Bread(elfobj.f, sect.base) != len(sect.base) { return err } diff --git a/src/cmd/link/internal/ld/ldmacho.go b/src/cmd/link/internal/ld/ldmacho.go index 6376116d04..dffe6f69ce 100644 --- a/src/cmd/link/internal/ld/ldmacho.go +++ b/src/cmd/link/internal/ld/ldmacho.go @@ -43,7 +43,7 @@ const ( ) type LdMachoObj struct { - f *bio.Buf + f *bio.Reader base int64 // off in f where Mach-O begins length int64 // length of Mach-O is64 bool @@ -299,7 +299,7 @@ func macholoadrel(m *LdMachoObj, sect *LdMachoSect) int { rel := make([]LdMachoRel, sect.nreloc) n := int(sect.nreloc * 8) buf := make([]byte, n) - if bio.Bseek(m.f, m.base+int64(sect.reloff), 0) < 0 || bio.Bread(m.f, buf) != n { + if m.f.Seek(m.base+int64(sect.reloff), 0) < 0 || bio.Bread(m.f, buf) != n { return -1 } var p []byte @@ -345,7 +345,7 @@ func macholoaddsym(m *LdMachoObj, d *LdMachoDysymtab) int { n := int(d.nindirectsyms) p := make([]byte, n*4) - if bio.Bseek(m.f, m.base+int64(d.indirectsymoff), 0) < 0 || bio.Bread(m.f, p) != len(p) { + if m.f.Seek(m.base+int64(d.indirectsymoff), 0) < 0 || bio.Bread(m.f, p) != len(p) { return -1 } @@ -362,7 +362,7 @@ func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int { } strbuf := make([]byte, symtab.strsize) - if bio.Bseek(m.f, m.base+int64(symtab.stroff), 0) < 0 || bio.Bread(m.f, strbuf) != len(strbuf) { + if m.f.Seek(m.base+int64(symtab.stroff), 0) < 0 || bio.Bread(m.f, strbuf) != len(strbuf) { return -1 } @@ -372,7 +372,7 @@ func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int { } n := int(symtab.nsym * uint32(symsize)) symbuf := make([]byte, n) - if bio.Bseek(m.f, m.base+int64(symtab.symoff), 0) < 0 || bio.Bread(m.f, symbuf) != len(symbuf) { + if m.f.Seek(m.base+int64(symtab.symoff), 0) < 0 || bio.Bread(m.f, symbuf) != len(symbuf) { return -1 } sym := make([]LdMachoSym, symtab.nsym) @@ -402,7 +402,7 @@ func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int { return 0 } -func ldmacho(f *bio.Buf, pkg string, length int64, pn string) { +func ldmacho(f *bio.Reader, pkg string, length int64, pn string) { var err error var j int var is64 bool @@ -432,7 +432,7 @@ func ldmacho(f *bio.Buf, pkg string, length int64, pn string) { var name string Ctxt.IncVersion() - base := bio.Boffset(f) + base := f.Offset() if bio.Bread(f, hdr[:]) != len(hdr) { goto bad } @@ -557,7 +557,7 @@ func ldmacho(f *bio.Buf, pkg string, length int64, pn string) { } dat = make([]byte, c.seg.filesz) - if bio.Bseek(f, m.base+int64(c.seg.fileoff), 0) < 0 || bio.Bread(f, dat) != len(dat) { + if f.Seek(m.base+int64(c.seg.fileoff), 0) < 0 || bio.Bread(f, dat) != len(dat) { err = fmt.Errorf("cannot load object data: %v", err) goto bad } diff --git a/src/cmd/link/internal/ld/ldpe.go b/src/cmd/link/internal/ld/ldpe.go index e97e842e7f..ba5b928ea0 100644 --- a/src/cmd/link/internal/ld/ldpe.go +++ b/src/cmd/link/internal/ld/ldpe.go @@ -118,7 +118,7 @@ type PeSect struct { } type PeObj struct { - f *bio.Buf + f *bio.Reader name string base uint32 sect []PeSect @@ -129,14 +129,14 @@ type PeObj struct { snames []byte } -func ldpe(f *bio.Buf, pkg string, length int64, pn string) { +func ldpe(f *bio.Reader, pkg string, length int64, pn string) { if Debug['v'] != 0 { fmt.Fprintf(&Bso, "%5.2f ldpe %s\n", obj.Cputime(), pn) } var sect *PeSect Ctxt.IncVersion() - base := int32(bio.Boffset(f)) + base := f.Offset() peobj := new(PeObj) peobj.f = f @@ -174,14 +174,14 @@ func ldpe(f *bio.Buf, pkg string, length int64, pn string) { // TODO return error if found .cormeta // load string table - bio.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) + f.Seek(int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) if bio.Bread(f, symbuf[:4]) != 4 { goto bad } l = Le32(symbuf[:]) peobj.snames = make([]byte, l) - bio.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) + f.Seek(int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) if bio.Bread(f, peobj.snames) != len(peobj.snames) { goto bad } @@ -202,9 +202,9 @@ func ldpe(f *bio.Buf, pkg string, length int64, pn string) { peobj.pesym = make([]PeSym, peobj.fh.NumberOfSymbols) peobj.npesym = uint(peobj.fh.NumberOfSymbols) - bio.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable), 0) + f.Seek(int64(base)+int64(peobj.fh.PointerToSymbolTable), 0) for i := 0; uint32(i) < peobj.fh.NumberOfSymbols; i += numaux + 1 { - bio.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(i), 0) + f.Seek(int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(i), 0) if bio.Bread(f, symbuf[:]) != len(symbuf) { goto bad } @@ -290,7 +290,7 @@ func ldpe(f *bio.Buf, pkg string, length int64, pn string) { } r = make([]Reloc, rsect.sh.NumberOfRelocations) - bio.Bseek(f, int64(peobj.base)+int64(rsect.sh.PointerToRelocations), 0) + f.Seek(int64(peobj.base)+int64(rsect.sh.PointerToRelocations), 0) for j = 0; j < int(rsect.sh.NumberOfRelocations); j++ { rp = &r[j] if bio.Bread(f, symbuf[:10]) != 10 { @@ -466,7 +466,7 @@ func pemap(peobj *PeObj, sect *PeSect) int { if sect.sh.PointerToRawData == 0 { // .bss doesn't have data in object file return 0 } - if bio.Bseek(peobj.f, int64(peobj.base)+int64(sect.sh.PointerToRawData), 0) < 0 || bio.Bread(peobj.f, sect.base) != len(sect.base) { + if peobj.f.Seek(int64(peobj.base)+int64(sect.sh.PointerToRawData), 0) < 0 || bio.Bread(peobj.f, sect.base) != len(sect.base) { return -1 } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 789eaef1a5..f8cc995c30 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -241,9 +241,10 @@ const ( var ( headstring string // buffered output - Bso bio.Buf + Bso bio.Writer ) +// TODO(dfc) outBuf duplicates bio.Writer type outBuf struct { w *bufio.Writer f *os.File @@ -739,11 +740,11 @@ func loadlib() { * look for the next file in an archive. * adapted from libmach. */ -func nextar(bp *bio.Buf, off int64, a *ArHdr) int64 { +func nextar(bp *bio.Reader, off int64, a *ArHdr) int64 { if off&1 != 0 { off++ } - bio.Bseek(bp, off, 0) + bp.Seek(off, 0) buf := make([]byte, SAR_HDR) if n := bio.Bread(bp, buf); n < len(buf) { if n >= 0 { @@ -782,9 +783,9 @@ func objfile(lib *Library) { magbuf := make([]byte, len(ARMAG)) if bio.Bread(f, magbuf) != len(magbuf) || !strings.HasPrefix(string(magbuf), ARMAG) { /* load it as a regular file */ - l := bio.Bseek(f, 0, 2) + l := f.Seek(0, 2) - bio.Bseek(f, 0, 0) + f.Seek(0, 0) ldobj(f, pkg, l, lib.File, lib.File, FileObj) f.Close() @@ -792,7 +793,7 @@ func objfile(lib *Library) { } /* process __.PKGDEF */ - off := bio.Boffset(f) + off := f.Offset() var arhdr ArHdr l := nextar(f, off, &arhdr) @@ -808,12 +809,12 @@ func objfile(lib *Library) { } if Buildmode == BuildmodeShared { - before := bio.Boffset(f) + before := f.Offset() pkgdefBytes := make([]byte, atolwhex(arhdr.size)) bio.Bread(f, pkgdefBytes) hash := sha1.Sum(pkgdefBytes) lib.hash = hash[:] - bio.Bseek(f, before, 0) + f.Seek(before, 0) } off += l @@ -853,7 +854,7 @@ out: } type Hostobj struct { - ld func(*bio.Buf, string, int64, string) + ld func(*bio.Reader, string, int64, string) pkg string pn string file string @@ -874,7 +875,7 @@ var internalpkg = []string{ "runtime/msan", } -func ldhostobj(ld func(*bio.Buf, string, int64, string), f *bio.Buf, pkg string, length int64, pn string, file string) *Hostobj { +func ldhostobj(ld func(*bio.Reader, string, int64, string), f *bio.Reader, pkg string, length int64, pn string, file string) *Hostobj { isinternal := false for i := 0; i < len(internalpkg); i++ { if pkg == internalpkg[i] { @@ -905,24 +906,22 @@ func ldhostobj(ld func(*bio.Buf, string, int64, string), f *bio.Buf, pkg string, h.pkg = pkg h.pn = pn h.file = file - h.off = bio.Boffset(f) + h.off = f.Offset() h.length = length return h } func hostobjs() { - var f *bio.Buf var h *Hostobj for i := 0; i < len(hostobj); i++ { h = &hostobj[i] - var err error - f, err = bio.Open(h.file) - if f == nil { + f, err := bio.Open(h.file) + if err != nil { Exitf("cannot reopen %s: %v", h.pn, err) } - bio.Bseek(f, h.off, 0) + f.Seek(h.off, 0) h.ld(f, h.pkg, h.length, h.pn) f.Close() } @@ -1266,15 +1265,15 @@ func hostlinkArchArgs() []string { // ldobj loads an input object. If it is a host object (an object // compiled by a non-Go compiler) it returns the Hostobj pointer. If // it is a Go object, it returns nil. -func ldobj(f *bio.Buf, pkg string, length int64, pn string, file string, whence int) *Hostobj { - eof := bio.Boffset(f) + length +func ldobj(f *bio.Reader, pkg string, length int64, pn string, file string, whence int) *Hostobj { + eof := f.Offset() + length - start := bio.Boffset(f) + start := f.Offset() c1 := bio.Bgetc(f) c2 := bio.Bgetc(f) c3 := bio.Bgetc(f) c4 := bio.Bgetc(f) - bio.Bseek(f, start, 0) + f.Seek(start, 0) magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4) if magic == 0x7f454c46 { // \x7F E L F @@ -1334,7 +1333,7 @@ func ldobj(f *bio.Buf, pkg string, length int64, pn string, file string, whence } /* skip over exports and other info -- ends with \n!\n */ - import0 := bio.Boffset(f) + import0 := f.Offset() c1 = '\n' // the last line ended in \n c2 = bio.Bgetc(f) @@ -1349,13 +1348,13 @@ func ldobj(f *bio.Buf, pkg string, length int64, pn string, file string, whence } } - import1 := bio.Boffset(f) + import1 := f.Offset() - bio.Bseek(f, import0, 0) + f.Seek(import0, 0) ldpkg(f, pkg, import1-import0-2, pn, whence) // -2 for !\n - bio.Bseek(f, import1, 0) + f.Seek(import1, 0) - LoadObjFile(Ctxt, f, pkg, eof-bio.Boffset(f), pn) + LoadObjFile(Ctxt, f, pkg, eof-f.Offset(), pn) return nil } diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go index d3f9ed3703..cbcc979c85 100644 --- a/src/cmd/link/internal/ld/link.go +++ b/src/cmd/link/internal/ld/link.go @@ -165,9 +165,10 @@ type Link struct { Headtype int Arch *sys.Arch Debugvlog int32 - Bso *bio.Buf - Windows int32 - Goroot string + + Bso *bio.Writer + Windows int32 + Goroot string // Symbol lookup based on name and indexed by version. Hash []map[string]*LSym diff --git a/src/cmd/link/internal/ld/objfile.go b/src/cmd/link/internal/ld/objfile.go index 6f177861f0..61a67cf94c 100644 --- a/src/cmd/link/internal/ld/objfile.go +++ b/src/cmd/link/internal/ld/objfile.go @@ -147,8 +147,8 @@ type objReader struct { file []*LSym } -func LoadObjFile(ctxt *Link, f *bio.Buf, pkg string, length int64, pn string) { - start := bio.Boffset(f) +func LoadObjFile(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) { + start := f.Offset() r := &objReader{ rd: f.Reader(), pkg: pkg, @@ -157,8 +157,8 @@ func LoadObjFile(ctxt *Link, f *bio.Buf, pkg string, length int64, pn string) { dupSym: &LSym{Name: ".dup"}, } r.loadObjFile() - if bio.Boffset(f) != start+length { - log.Fatalf("%s: unexpected end at %d, want %d", pn, int64(bio.Boffset(f)), int64(start+length)) + if f.Offset() != start+length { + log.Fatalf("%s: unexpected end at %d, want %d", pn, f.Offset(), start+length) } } -- cgit v1.3 From ca397bb68e4b548843d2886e374f96ec3bb0f9c0 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Fri, 8 Apr 2016 19:30:41 +1000 Subject: cmd: remove bio.BufReader and bio.BufWriter bio.BufReader was never used. bio.BufWriter was used to wrap an existing io.Writer, but the bio.Writer returned would not be seekable, so replace all occurences with bufio.Reader instead. Change-Id: I9c6779e35c63178aa4e104c17bb5bb8b52de0359 Reviewed-on: https://go-review.googlesource.com/21722 Reviewed-by: Brad Fitzpatrick Run-TryBot: Dave Cheney TryBot-Result: Gobot Gobot --- src/cmd/asm/internal/asm/endtoend_test.go | 6 +++--- src/cmd/asm/main.go | 15 ++++++++------- src/cmd/compile/internal/gc/bexport.go | 6 +++--- src/cmd/compile/internal/gc/export.go | 4 ++-- src/cmd/compile/internal/gc/go.go | 3 ++- src/cmd/compile/internal/gc/main.go | 3 +-- src/cmd/internal/bio/buf.go | 12 ------------ src/cmd/internal/obj/link.go | 4 ++-- src/cmd/link/internal/ld/lib.go | 2 +- src/cmd/link/internal/ld/link.go | 9 ++++----- src/cmd/link/internal/ld/pobj.go | 4 ++-- 11 files changed, 28 insertions(+), 40 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/asm/internal/asm/endtoend_test.go b/src/cmd/asm/internal/asm/endtoend_test.go index 8986281f10..bc992a7c99 100644 --- a/src/cmd/asm/internal/asm/endtoend_test.go +++ b/src/cmd/asm/internal/asm/endtoend_test.go @@ -5,6 +5,7 @@ package asm import ( + "bufio" "bytes" "fmt" "io/ioutil" @@ -17,7 +18,6 @@ import ( "testing" "cmd/asm/internal/lex" - "cmd/internal/bio" "cmd/internal/obj" ) @@ -34,7 +34,7 @@ func testEndToEnd(t *testing.T, goarch, file string) { pList := obj.Linknewplist(ctxt) var ok bool testOut = new(bytes.Buffer) // The assembler writes test output to this buffer. - ctxt.Bso = bio.BufWriter(os.Stdout) + ctxt.Bso = bufio.NewWriter(os.Stdout) defer ctxt.Bso.Flush() failed := false ctxt.DiagFunc = func(format string, args ...interface{}) { @@ -272,7 +272,7 @@ func testErrors(t *testing.T, goarch, file string) { pList := obj.Linknewplist(ctxt) var ok bool testOut = new(bytes.Buffer) // The assembler writes test output to this buffer. - ctxt.Bso = bio.BufWriter(os.Stdout) + ctxt.Bso = bufio.NewWriter(os.Stdout) defer ctxt.Bso.Flush() failed := false var errBuf bytes.Buffer diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go index 75cb8f75d3..f010ca93f1 100644 --- a/src/cmd/asm/main.go +++ b/src/cmd/asm/main.go @@ -5,6 +5,7 @@ package main import ( + "bufio" "flag" "fmt" "log" @@ -32,11 +33,6 @@ func main() { flags.Parse() - // Create object file, write header. - fd, err := os.Create(*flags.OutputFile) - if err != nil { - log.Fatal(err) - } ctxt := obj.Linknew(architecture.LinkArch) if *flags.PrintOut { ctxt.Debugasm = 1 @@ -46,9 +42,14 @@ func main() { if *flags.Shared || *flags.Dynlink { ctxt.Flag_shared = 1 } - ctxt.Bso = bio.BufWriter(os.Stdout) + ctxt.Bso = bufio.NewWriter(os.Stdout) defer ctxt.Bso.Flush() - output := bio.BufWriter(fd) + + // Create object file, write header. + output, err := bio.Create(*flags.OutputFile) + if err != nil { + log.Fatal(err) + } fmt.Fprintf(output, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion()) fmt.Fprintf(output, "!\n") diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index bb0a34e67b..15e5e3ada6 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -90,9 +90,9 @@ importer. package gc import ( + "bufio" "bytes" "cmd/compile/internal/big" - "cmd/internal/bio" "encoding/binary" "fmt" "sort" @@ -124,7 +124,7 @@ const exportVersion = "v0" const exportInlined = true // default: true type exporter struct { - out *bio.Writer + out *bufio.Writer pkgIndex map[*Pkg]int typIndex map[*Type]int inlined []*Func @@ -136,7 +136,7 @@ type exporter struct { } // export writes the exportlist for localpkg to out and returns the number of bytes written. -func export(out *bio.Writer, trace bool) int { +func export(out *bufio.Writer, trace bool) int { p := exporter{ out: out, pkgIndex: make(map[*Pkg]int), diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index 2f94b9c62f..dc7c0869bf 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -384,7 +384,7 @@ func dumpexport() { if debugFormat { // save a copy of the export data var copy bytes.Buffer - bcopy := bio.BufWriter(©) + bcopy := bufio.NewWriter(©) size = export(bcopy, Debug_export != 0) bcopy.Flush() // flushing to bytes.Buffer cannot fail if n, err := bout.Write(copy.Bytes()); n != size || err != nil { @@ -407,7 +407,7 @@ func dumpexport() { pkgs = savedPkgs pkgMap = savedPkgMap } else { - size = export(bout, Debug_export != 0) + size = export(bout.Writer(), Debug_export != 0) } exportf("\n$$\n") } else { diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index ec7e219d95..d9b28ff8e6 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -5,6 +5,7 @@ package gc import ( + "bufio" "cmd/compile/internal/ssa" "cmd/internal/bio" "cmd/internal/obj" @@ -288,7 +289,7 @@ var Ctxt *obj.Link var writearchive int -var bstdout *bio.Writer +var bstdout *bufio.Writer var Nacl bool diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 03143f5d0a..26acf8861f 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -9,7 +9,6 @@ package gc import ( "bufio" "cmd/compile/internal/ssa" - "cmd/internal/bio" "cmd/internal/obj" "cmd/internal/sys" "flag" @@ -104,7 +103,7 @@ func Main() { Ctxt = obj.Linknew(Thearch.LinkArch) Ctxt.DiagFunc = Yyerror - bstdout = bio.BufWriter(os.Stdout) + bstdout = bufio.NewWriter(os.Stdout) Ctxt.Bso = bstdout localpkg = mkpkg("") diff --git a/src/cmd/internal/bio/buf.go b/src/cmd/internal/bio/buf.go index 0bd4658cdd..983ce46627 100644 --- a/src/cmd/internal/bio/buf.go +++ b/src/cmd/internal/bio/buf.go @@ -51,18 +51,6 @@ func Open(name string) (*Reader, error) { return &Reader{f: f, r: bufio.NewReader(f)}, nil } -// BufWriter returns a Writer on top of w. -// TODO(dfc) remove this method and replace caller with bufio.Writer. -func BufWriter(w io.Writer) *Writer { - return &Writer{w: bufio.NewWriter(w)} -} - -// BufWriter returns a Reader on top of r. -// TODO(dfc) remove this method and replace caller with bufio.Reader. -func BufReader(r io.Reader) *Reader { - return &Reader{r: bufio.NewReader(r)} -} - func (w *Writer) Write(p []byte) (int, error) { return w.w.Write(p) } diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index c48c3d807f..62175f9ed8 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -31,7 +31,7 @@ package obj import ( - "cmd/internal/bio" + "bufio" "cmd/internal/sys" ) @@ -629,7 +629,7 @@ type Link struct { Flag_shared int32 Flag_dynlink bool Flag_optimize bool - Bso *bio.Writer + Bso *bufio.Writer Pathname string Goroot string Goroot_final string diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index e35306dd0e..01dca9fc31 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -241,7 +241,7 @@ const ( var ( headstring string // buffered output - Bso *bio.Writer + Bso *bufio.Writer ) // TODO(dfc) outBuf duplicates bio.Writer diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go index cbcc979c85..52b52f1cc0 100644 --- a/src/cmd/link/internal/ld/link.go +++ b/src/cmd/link/internal/ld/link.go @@ -31,7 +31,7 @@ package ld import ( - "cmd/internal/bio" + "bufio" "cmd/internal/sys" "debug/elf" "fmt" @@ -165,10 +165,9 @@ type Link struct { Headtype int Arch *sys.Arch Debugvlog int32 - - Bso *bio.Writer - Windows int32 - Goroot string + Bso *bufio.Writer + Windows int32 + Goroot string // Symbol lookup based on name and indexed by version. Hash []map[string]*LSym diff --git a/src/cmd/link/internal/ld/pobj.go b/src/cmd/link/internal/ld/pobj.go index 50066d32d7..f4fb4d4845 100644 --- a/src/cmd/link/internal/ld/pobj.go +++ b/src/cmd/link/internal/ld/pobj.go @@ -31,7 +31,7 @@ package ld import ( - "cmd/internal/bio" + "bufio" "cmd/internal/obj" "cmd/internal/sys" "flag" @@ -46,7 +46,7 @@ var ( ) func Ldmain() { - Bso = bio.BufWriter(os.Stdout) + Bso = bufio.NewWriter(os.Stdout) Ctxt = linknew(SysArch) Ctxt.Diag = Diag -- cgit v1.3 From 93368be61ebaf8069d0d70034097de580441c412 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Fri, 8 Apr 2016 20:37:54 +1000 Subject: cmd/internal/bio: embed bufio.{Reader,Writer} in bio.{Reader,Writer} Change-Id: Ie95b0b0d4f724f4769cf2d4f8063cb5019fa9bc9 Reviewed-on: https://go-review.googlesource.com/21781 Reviewed-by: Brad Fitzpatrick --- src/cmd/compile/internal/gc/export.go | 2 +- src/cmd/internal/bio/buf.go | 56 ++++++++--------------------------- src/cmd/internal/obj/objfile.go | 2 +- src/cmd/link/internal/ld/objfile.go | 2 +- 4 files changed, 16 insertions(+), 46 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go index dc7c0869bf..ae36657a65 100644 --- a/src/cmd/compile/internal/gc/export.go +++ b/src/cmd/compile/internal/gc/export.go @@ -407,7 +407,7 @@ func dumpexport() { pkgs = savedPkgs pkgMap = savedPkgMap } else { - size = export(bout.Writer(), Debug_export != 0) + size = export(bout.Writer, Debug_export != 0) } exportf("\n$$\n") } else { diff --git a/src/cmd/internal/bio/buf.go b/src/cmd/internal/bio/buf.go index 983ce46627..564ac77cbf 100644 --- a/src/cmd/internal/bio/buf.go +++ b/src/cmd/internal/bio/buf.go @@ -17,21 +17,15 @@ const EOF = -1 // Reader implements a seekable buffered io.Reader. type Reader struct { f *os.File - r *bufio.Reader + *bufio.Reader } // Writer implements a seekable buffered io.Writer. type Writer struct { f *os.File - w *bufio.Writer + *bufio.Writer } -// Reader returns this Reader's underlying bufio.Reader. -func (r *Reader) Reader() *bufio.Reader { return r.r } - -// Writer returns this Writer's underlying bufio.Writer. -func (w *Writer) Writer() *bufio.Writer { return w.w } - // Create creates the file named name and returns a Writer // for that file. func Create(name string) (*Writer, error) { @@ -39,7 +33,7 @@ func Create(name string) (*Writer, error) { if err != nil { return nil, err } - return &Writer{f: f, w: bufio.NewWriter(f)}, nil + return &Writer{f: f, Writer: bufio.NewWriter(f)}, nil } // Open returns a Reader for the file named name. @@ -48,31 +42,23 @@ func Open(name string) (*Reader, error) { if err != nil { return nil, err } - return &Reader{f: f, r: bufio.NewReader(f)}, nil -} - -func (w *Writer) Write(p []byte) (int, error) { - return w.w.Write(p) -} - -func (w *Writer) WriteString(p string) (int, error) { - return w.w.WriteString(p) + return &Reader{f: f, Reader: bufio.NewReader(f)}, nil } func (r *Reader) Seek(offset int64, whence int) int64 { if whence == 1 { - offset -= int64(r.r.Buffered()) + offset -= int64(r.Buffered()) } off, err := r.f.Seek(offset, whence) if err != nil { log.Fatalf("seeking in output: %v", err) } - r.r.Reset(r.f) + r.Reset(r.f) return off } func (w *Writer) Seek(offset int64, whence int) int64 { - if err := w.w.Flush(); err != nil { + if err := w.Flush(); err != nil { log.Fatalf("writing output: %v", err) } off, err := w.f.Seek(offset, whence) @@ -87,12 +73,12 @@ func (r *Reader) Offset() int64 { if err != nil { log.Fatalf("seeking in output [0, 1]: %v", err) } - off -= int64(r.r.Buffered()) + off -= int64(r.Buffered()) return off } func (w *Writer) Offset() int64 { - if err := w.w.Flush(); err != nil { + if err := w.Flush(); err != nil { log.Fatalf("writing output: %v", err) } off, err := w.f.Seek(0, 1) @@ -102,16 +88,8 @@ func (w *Writer) Offset() int64 { return off } -func (w *Writer) Flush() error { - return w.w.Flush() -} - -func (w *Writer) WriteByte(c byte) error { - return w.w.WriteByte(c) -} - func Bread(r *Reader, p []byte) int { - n, err := io.ReadFull(r.r, p) + n, err := io.ReadFull(r, p) if n == 0 { if err != nil && err != io.EOF { n = -1 @@ -121,7 +99,7 @@ func Bread(r *Reader, p []byte) int { } func Bgetc(r *Reader) int { - c, err := r.r.ReadByte() + c, err := r.ReadByte() if err != nil { if err != io.EOF { log.Fatalf("reading input: %v", err) @@ -131,16 +109,8 @@ func Bgetc(r *Reader) int { return int(c) } -func (r *Reader) Read(p []byte) (int, error) { - return r.r.Read(p) -} - -func (r *Reader) Peek(n int) ([]byte, error) { - return r.r.Peek(n) -} - func Brdline(r *Reader, delim int) string { - s, err := r.r.ReadBytes(byte(delim)) + s, err := r.ReadBytes(byte(delim)) if err != nil { log.Fatalf("reading input: %v", err) } @@ -152,7 +122,7 @@ func (r *Reader) Close() error { } func (w *Writer) Close() error { - err := w.w.Flush() + err := w.Flush() err1 := w.f.Close() if err == nil { err = err1 diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index ed6d75eba3..ee21f39d10 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -377,7 +377,7 @@ func (w *objWriter) writeLengths() { func newObjWriter(ctxt *Link, b *bio.Writer) *objWriter { return &objWriter{ ctxt: ctxt, - wr: b.Writer(), + wr: b.Writer, vrefIdx: make(map[string]int), refIdx: make(map[string]int), } diff --git a/src/cmd/link/internal/ld/objfile.go b/src/cmd/link/internal/ld/objfile.go index 61a67cf94c..578afd4c74 100644 --- a/src/cmd/link/internal/ld/objfile.go +++ b/src/cmd/link/internal/ld/objfile.go @@ -150,7 +150,7 @@ type objReader struct { func LoadObjFile(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) { start := f.Offset() r := &objReader{ - rd: f.Reader(), + rd: f.Reader, pkg: pkg, ctxt: ctxt, pn: pn, -- cgit v1.3 From bce9747ed00c53e7ddeea102e87aede1b3ec9bd3 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Sat, 9 Apr 2016 15:04:45 +1000 Subject: cmd: remove unused code Generated with honnef.co/go/unused There is a large amount of unused code in cmd/internal/obj/s390x but that can wait til the s390x port is merged. There is some unused code in cmd/internal/unvendor/golang.org/x/arch/arm/armasm but that should be addressed upstream and a new revision imported. Change-Id: I252c0f9ea8c5bb1a0b530a374ef13a0a20ea56aa Reviewed-on: https://go-review.googlesource.com/21782 Reviewed-by: Brad Fitzpatrick Run-TryBot: Dave Cheney --- src/cmd/internal/goobj/read.go | 7 ++---- src/cmd/internal/obj/mips/asm0.go | 4 ---- src/cmd/internal/obj/x86/asm6.go | 5 ----- src/cmd/internal/obj/x86/obj6_test.go | 1 - src/cmd/internal/objfile/pe.go | 2 -- src/cmd/link/internal/amd64/asm.go | 6 ----- src/cmd/link/internal/arm/asm.go | 5 ----- src/cmd/link/internal/arm64/asm.go | 4 ---- src/cmd/link/internal/ld/data.go | 4 ---- src/cmd/link/internal/ld/deadcode.go | 4 +--- src/cmd/link/internal/ld/decodesym.go | 18 --------------- src/cmd/link/internal/ld/go.go | 30 +------------------------ src/cmd/link/internal/ld/macho.go | 7 ++---- src/cmd/link/internal/ld/macho_combine_dwarf.go | 4 +--- src/cmd/link/internal/mips64/asm.go | 4 ---- src/cmd/link/internal/ppc64/asm.go | 4 ---- src/cmd/link/internal/x86/asm.go | 4 ---- 17 files changed, 7 insertions(+), 106 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/internal/goobj/read.go b/src/cmd/internal/goobj/read.go index 5434661384..698d58efe0 100644 --- a/src/cmd/internal/goobj/read.go +++ b/src/cmd/internal/goobj/read.go @@ -229,11 +229,8 @@ var ( errCorruptArchive = errors.New("corrupt archive") errTruncatedArchive = errors.New("truncated archive") - errNotArchive = errors.New("unrecognized archive format") - - errCorruptObject = errors.New("corrupt object file") - errTruncatedObject = errors.New("truncated object file") - errNotObject = errors.New("unrecognized object file format") + errCorruptObject = errors.New("corrupt object file") + errNotObject = errors.New("unrecognized object file format") ) // An objReader is an object file reader. diff --git a/src/cmd/internal/obj/mips/asm0.go b/src/cmd/internal/obj/mips/asm0.go index 521cb66dec..5cb5d1cfd9 100644 --- a/src/cmd/internal/obj/mips/asm0.go +++ b/src/cmd/internal/obj/mips/asm0.go @@ -974,10 +974,6 @@ func OP_JMP(op uint32, i uint32) uint32 { return op | i&0x3FFFFFF } -func oclass(a *obj.Addr) int { - return int(a.Class) - 1 -} - func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 := uint32(0) o2 := uint32(0) diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index b940094b8b..c15b59b5e8 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -884,11 +884,6 @@ var yvex_vpbroadcast = []ytab{ {Yxm, Ynone, Yyr, Zvex_rm_v_r, 2}, } -var yvex_xxmyxm = []ytab{ - {Yxr, Ynone, Yxm, Zvex_r_v_rm, 2}, - {Yyr, Ynone, Yxm, Zvex_r_v_rm, 2}, -} - var ymmxmm0f38 = []ytab{ {Ymm, Ynone, Ymr, Zlitm_r, 3}, {Yxm, Ynone, Yxr, Zlitm_r, 5}, diff --git a/src/cmd/internal/obj/x86/obj6_test.go b/src/cmd/internal/obj/x86/obj6_test.go index a5c80cea3b..fe1f95cc0d 100644 --- a/src/cmd/internal/obj/x86/obj6_test.go +++ b/src/cmd/internal/obj/x86/obj6_test.go @@ -76,7 +76,6 @@ func parseTestData(t *testing.T) *ParsedTestData { } var spaces_re *regexp.Regexp = regexp.MustCompile("\\s+") -var marker_re *regexp.Regexp = regexp.MustCompile("MOVQ \\$([0-9]+), AX") func normalize(s string) string { return spaces_re.ReplaceAllLiteralString(strings.TrimSpace(s), " ") diff --git a/src/cmd/internal/objfile/pe.go b/src/cmd/internal/objfile/pe.go index 1b319941ac..c024762371 100644 --- a/src/cmd/internal/objfile/pe.go +++ b/src/cmd/internal/objfile/pe.go @@ -69,8 +69,6 @@ func (f *peFile) symbols() ([]Sym, error) { text = 0x20 data = 0x40 bss = 0x80 - permX = 0x20000000 - permR = 0x40000000 permW = 0x80000000 ) ch := sect.Characteristics diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go index 8cecd422e1..a6dce6c2c9 100644 --- a/src/cmd/link/internal/amd64/asm.go +++ b/src/cmd/link/internal/amd64/asm.go @@ -99,12 +99,6 @@ func gentext() { ld.Addaddr(ld.Ctxt, initarray_entry, initfunc) } -func adddynrela(rela *ld.LSym, s *ld.LSym, r *ld.Reloc) { - ld.Addaddrplus(ld.Ctxt, rela, s, int64(r.Off)) - ld.Adduint64(ld.Ctxt, rela, ld.R_X86_64_RELATIVE) - ld.Addaddrplus(ld.Ctxt, rela, r.Sym, r.Add) // Addend -} - func adddynrel(s *ld.LSym, r *ld.Reloc) { targ := r.Sym ld.Ctxt.Cursym = s diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go index b89cb20bdf..1188615716 100644 --- a/src/cmd/link/internal/arm/asm.go +++ b/src/cmd/link/internal/arm/asm.go @@ -114,11 +114,6 @@ func braddoff(a int32, b int32) int32 { return int32((uint32(a))&0xff000000 | 0x00ffffff&uint32(a+b)) } -func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) { - ld.Addaddrplus(ld.Ctxt, rel, s, int64(r.Off)) - ld.Adduint32(ld.Ctxt, rel, ld.R_ARM_RELATIVE) -} - func adddynrel(s *ld.LSym, r *ld.Reloc) { targ := r.Sym ld.Ctxt.Cursym = s diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go index fd8929dd99..d3ba5ff3f3 100644 --- a/src/cmd/link/internal/arm64/asm.go +++ b/src/cmd/link/internal/arm64/asm.go @@ -91,10 +91,6 @@ func gentext() { ld.Addaddr(ld.Ctxt, initarray_entry, initfunc) } -func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) { - log.Fatalf("adddynrela not implemented") -} - func adddynrel(s *ld.LSym, r *ld.Reloc) { log.Fatalf("adddynrel not implemented") } diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index cd910b54c0..2c8cc9ca4f 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -236,10 +236,6 @@ func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 { * Used for the data block. */ -func listnextp(s *LSym) **LSym { - return &s.Next -} - func listsubp(s *LSym) **LSym { return &s.Sub } diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index b17b96001e..8b2d0d447e 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -170,9 +170,7 @@ type methodref struct { r [3]*Reloc // R_METHOD relocations to fields of runtime.method } -func (m methodref) mtyp() *LSym { return m.r[0].Sym } -func (m methodref) ifn() *LSym { return m.r[1].Sym } -func (m methodref) tfn() *LSym { return m.r[2].Sym } +func (m methodref) ifn() *LSym { return m.r[1].Sym } func (m methodref) isExported() bool { for _, r := range m.m { diff --git a/src/cmd/link/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go index bc29938590..1066d220f7 100644 --- a/src/cmd/link/internal/ld/decodesym.go +++ b/src/cmd/link/internal/ld/decodesym.go @@ -56,11 +56,6 @@ func decodetype_kind(s *LSym) uint8 { return uint8(s.P[2*SysArch.PtrSize+7] & obj.KindMask) // 0x13 / 0x1f } -// Type.commonType.kind -func decodetype_noptr(s *LSym) uint8 { - return uint8(s.P[2*SysArch.PtrSize+7] & obj.KindNoPointers) // 0x13 / 0x1f -} - // Type.commonType.kind func decodetype_usegcprog(s *LSym) uint8 { return uint8(s.P[2*SysArch.PtrSize+7] & obj.KindGCProg) // 0x13 / 0x1f @@ -216,19 +211,6 @@ func decodetype_structfieldarrayoff(s *LSym, i int) int { return off } -func decodetype_stringptr(s *LSym, off int) string { - s = decode_reloc_sym(s, int32(off)) - if s == nil { - return "" - } - r := decode_reloc(s, 0) // s has a pointer to the string data at offset 0 - if r == nil { // shouldn't happen. - return "" - } - strlen := int64(decode_inuxi(s.P[SysArch.PtrSize:], SysArch.IntSize)) - return string(r.Sym.P[r.Add : r.Add+strlen]) -} - // decodetype_name decodes the name from a reflect.name. func decodetype_name(s *LSym, off int) string { r := decode_reloc(s, int32(off)) diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go index 5dad90dae6..3af5f7a046 100644 --- a/src/cmd/link/internal/ld/go.go +++ b/src/cmd/link/internal/ld/go.go @@ -419,35 +419,7 @@ type Pkg struct { impby []*Pkg } -var ( - // pkgmap records the imported-by relationship between packages. - // Entries are keyed by package path (e.g., "runtime" or "net/url"). - pkgmap = map[string]*Pkg{} - - pkgall []*Pkg -) - -func lookupPkg(path string) *Pkg { - if p, ok := pkgmap[path]; ok { - return p - } - p := &Pkg{path: path} - pkgmap[path] = p - pkgall = append(pkgall, p) - return p -} - -// imported records that package pkg imports package imp. -func imported(pkg, imp string) { - // everyone imports runtime, even runtime. - if imp == "runtime" { - return - } - - p := lookupPkg(pkg) - i := lookupPkg(imp) - i.impby = append(i.impby, p) -} +var pkgall []*Pkg func (p *Pkg) cycle() *Pkg { if p.checked { diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index 25d48fbf22..1d9a1a9324 100644 --- a/src/cmd/link/internal/ld/macho.go +++ b/src/cmd/link/internal/ld/macho.go @@ -586,11 +586,8 @@ func Asmbmacho() { // and we can assume OS X. // // See golang.org/issues/12941. - const ( - LC_VERSION_MIN_MACOSX = 0x24 - LC_VERSION_MIN_IPHONEOS = 0x25 - LC_VERSION_MIN_WATCHOS = 0x30 - ) + const LC_VERSION_MIN_MACOSX = 0x24 + ml := newMachoLoad(LC_VERSION_MIN_MACOSX, 2) ml.data[0] = 10<<16 | 7<<8 | 0<<0 // OS X version 10.7.0 ml.data[1] = 10<<16 | 7<<8 | 0<<0 // SDK 10.7.0 diff --git a/src/cmd/link/internal/ld/macho_combine_dwarf.go b/src/cmd/link/internal/ld/macho_combine_dwarf.go index b5a5a8d429..dcc371ec05 100644 --- a/src/cmd/link/internal/ld/macho_combine_dwarf.go +++ b/src/cmd/link/internal/ld/macho_combine_dwarf.go @@ -15,11 +15,9 @@ import ( "unsafe" ) -var fakedwarf, realdwarf, linkseg *macho.Segment +var realdwarf, linkseg *macho.Segment var dwarfstart, linkstart int64 var linkoffset uint32 -var machHeader *macho.FileHeader -var mappedHeader []byte const ( LC_ID_DYLIB = 0xd diff --git a/src/cmd/link/internal/mips64/asm.go b/src/cmd/link/internal/mips64/asm.go index 027736cc11..ad6a1f7524 100644 --- a/src/cmd/link/internal/mips64/asm.go +++ b/src/cmd/link/internal/mips64/asm.go @@ -41,10 +41,6 @@ import ( func gentext() {} -func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) { - log.Fatalf("adddynrela not implemented") -} - func adddynrel(s *ld.LSym, r *ld.Reloc) { log.Fatalf("adddynrel not implemented") } diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index 13d80545c7..3970f3c5f9 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -265,10 +265,6 @@ func gencallstub(abicase int, stub *ld.LSym, targ *ld.LSym) { ld.Adduint32(ld.Ctxt, stub, 0x4e800420) // bctr } -func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) { - log.Fatalf("adddynrela not implemented") -} - func adddynrel(s *ld.LSym, r *ld.Reloc) { targ := r.Sym ld.Ctxt.Cursym = s diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go index a786ba5a48..19a8917ec8 100644 --- a/src/cmd/link/internal/x86/asm.go +++ b/src/cmd/link/internal/x86/asm.go @@ -139,10 +139,6 @@ func gentext() { ld.Addaddr(ld.Ctxt, initarray_entry, initfunc) } -func adddynrela(rela *ld.LSym, s *ld.LSym, r *ld.Reloc) { - log.Fatalf("adddynrela not implemented") -} - func adddynrel(s *ld.LSym, r *ld.Reloc) { targ := r.Sym ld.Ctxt.Cursym = s -- cgit v1.3 From cd6b2b7451c6feb277d38820f41f81ce4a036af2 Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Sun, 10 Apr 2016 20:01:49 -0400 Subject: cmd/internal/obj/s390x: add MULHD instruction Emulate 64-bit signed high multiplication ((a*b)>>64). To do this we use the 64-bit unsigned high multiplication method and then fix the result as shown in Hacker's Delight 2nd ed., chapter 8-3. Required to enable some division optimizations. Change-Id: I9194f428e09d3d029cb1afb4715cd5424b5d922e Reviewed-on: https://go-review.googlesource.com/21774 Reviewed-by: Bill O'Farrell Run-TryBot: Brad Fitzpatrick Reviewed-by: Brad Fitzpatrick --- src/cmd/asm/internal/asm/testdata/s390x.s | 4 ++++ src/cmd/internal/obj/s390x/a.out.go | 1 + src/cmd/internal/obj/s390x/anames.go | 1 + src/cmd/internal/obj/s390x/asmz.go | 34 +++++++++++++++++++++++-------- 4 files changed, 32 insertions(+), 8 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/asm/internal/asm/testdata/s390x.s b/src/cmd/asm/internal/asm/testdata/s390x.s index 148cd2eaae..f1dc9aff2d 100644 --- a/src/cmd/asm/internal/asm/testdata/s390x.s +++ b/src/cmd/asm/internal/asm/testdata/s390x.s @@ -61,6 +61,10 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0 MULLW R6, R7, R8 // b9040087b91c0086 MULLW $8192, R6 // c26000002000 MULLW $8192, R6, R7 // b9040076c27000002000 + MULHD R9, R8 // b90400b8b98600a9ebb9003f000ab98000b8b90900abebb8003f000ab98000b9b9e9b08a + MULHD R7, R2, R1 // b90400b2b98600a7ebb7003f000ab98000b2b90900abebb2003f000ab98000b7b9e9b01a + MULHDU R3, R4 // b90400b4b98600a3b904004a + MULHDU R5, R6, R7 // b90400b6b98600a5b904007a DIVD R1, R2 // b90400b2b90d00a1b904002b DIVD R1, R2, R3 // b90400b2b90d00a1b904003b DIVW R4, R5 // b90400b5b91d00a4b904005b diff --git a/src/cmd/internal/obj/s390x/a.out.go b/src/cmd/internal/obj/s390x/a.out.go index 2cb03ae603..e7256d1d41 100644 --- a/src/cmd/internal/obj/s390x/a.out.go +++ b/src/cmd/internal/obj/s390x/a.out.go @@ -218,6 +218,7 @@ const ( ADIVDU AMULLW AMULLD + AMULHD AMULHDU ASUB ASUBC diff --git a/src/cmd/internal/obj/s390x/anames.go b/src/cmd/internal/obj/s390x/anames.go index e79a147a90..62dd181eda 100644 --- a/src/cmd/internal/obj/s390x/anames.go +++ b/src/cmd/internal/obj/s390x/anames.go @@ -17,6 +17,7 @@ var Anames = []string{ "DIVDU", "MULLW", "MULLD", + "MULHD", "MULHDU", "SUB", "SUBC", diff --git a/src/cmd/internal/obj/s390x/asmz.go b/src/cmd/internal/obj/s390x/asmz.go index bccd7c3bd8..cf3b11424b 100644 --- a/src/cmd/internal/obj/s390x/asmz.go +++ b/src/cmd/internal/obj/s390x/asmz.go @@ -150,6 +150,8 @@ var optab = []Optab{ Optab{AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 0}, Optab{AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 0}, Optab{AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 0}, + Optab{AMULHD, C_REG, C_NONE, C_NONE, C_REG, 4, 0}, + Optab{AMULHD, C_REG, C_REG, C_NONE, C_REG, 4, 0}, Optab{ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 0}, Optab{ASUBC, C_REG, C_NONE, C_NONE, C_REG, 10, 0}, Optab{ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 0}, @@ -793,10 +795,11 @@ func buildop(ctxt *obj.Link) { case ADIVW: opset(AADDE, r) opset(AMULLD, r) - opset(AMULHDU, r) opset(ADIVD, r) opset(ADIVDU, r) opset(ADIVWU, r) + case AMULHD: + opset(AMULHDU, r) case AMOVBZ: opset(AMOVH, r) opset(AMOVHZ, r) @@ -2580,8 +2583,6 @@ func asmout(ctxt *obj.Link, asm *[]byte) { opcode = op_MSGFR case AMULLD: opcode = op_MSGR - case AMULHDU: - opcode = op_MLGR case ADIVW: opcode = op_DSGFR case ADIVWU: @@ -2628,11 +2629,6 @@ func asmout(ctxt *obj.Link, asm *[]byte) { zRRE(opcode, REGTMP, uint32(p.From.Reg), asm) zRRE(op_LGR, uint32(p.To.Reg), REGTMP2, asm) - case AMULHDU: - zRRE(op_LGR, REGTMP2, uint32(r), asm) - zRRE(opcode, REGTMP, uint32(p.From.Reg), asm) - zRRE(op_LGR, uint32(p.To.Reg), REGTMP, asm) - case AFADD, AFADDS: if r == int(p.To.Reg) { zRRE(opcode, uint32(p.To.Reg), uint32(p.From.Reg), asm) @@ -2695,6 +2691,28 @@ func asmout(ctxt *obj.Link, asm *[]byte) { zRIL(_a, op_IIHF, uint32(p.To.Reg), uint32(v>>32), asm) } + case 4: // multiply high (a*b)>>64 + r := p.Reg + if r == 0 { + r = p.To.Reg + } + zRRE(op_LGR, REGTMP2, uint32(r), asm) + zRRE(op_MLGR, REGTMP, uint32(p.From.Reg), asm) + switch p.As { + case AMULHDU: + // Unsigned: move result into correct register. + zRRE(op_LGR, uint32(p.To.Reg), REGTMP, asm) + case AMULHD: + // Signed: need to convert result. + // See Hacker's Delight 8-3. + zRSY(op_SRAG, REGTMP2, uint32(p.From.Reg), 0, 63, asm) + zRRE(op_NGR, REGTMP2, uint32(r), asm) + zRRE(op_SGR, REGTMP, REGTMP2, asm) + zRSY(op_SRAG, REGTMP2, uint32(r), 0, 63, asm) + zRRE(op_NGR, REGTMP2, uint32(p.From.Reg), asm) + zRRF(op_SGRK, REGTMP2, 0, uint32(p.To.Reg), REGTMP, asm) + } + case 5: // syscall zI(op_SVC, 0, asm) -- cgit v1.3 From e07a4459a155789fb57bbf4e2c8eaca5b369fd17 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 12 Apr 2016 12:16:20 -0700 Subject: cmd: replace x[i:][0] expressions with x[i] Passes toolstash -cmp. Change-Id: Id504e71ed1f23900e24a9aed25143c94f4d7d50c Reviewed-on: https://go-review.googlesource.com/21899 Run-TryBot: Matthew Dempsky Reviewed-by: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/cmd/internal/obj/arm64/asm7.go | 2 +- src/cmd/internal/obj/mips/asm0.go | 2 +- src/cmd/internal/obj/s390x/asmz.go | 2 +- src/cmd/internal/obj/x86/asm6.go | 3 +-- src/cmd/link/internal/ld/decodesym.go | 4 ++-- src/cmd/link/internal/ld/ldelf.go | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index ff8d4fdf60..d0ae6115cb 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -1087,7 +1087,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { a1 := int(p.Optab) if a1 != 0 { - return &optab[a1-1:][0] + return &optab[a1-1] } a1 = int(p.From.Class) if a1 == 0 { diff --git a/src/cmd/internal/obj/mips/asm0.go b/src/cmd/internal/obj/mips/asm0.go index 5cb5d1cfd9..13e7600c21 100644 --- a/src/cmd/internal/obj/mips/asm0.go +++ b/src/cmd/internal/obj/mips/asm0.go @@ -611,7 +611,7 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { a1 := int(p.Optab) if a1 != 0 { - return &optab[a1-1:][0] + return &optab[a1-1] } a1 = int(p.From.Class) if a1 == 0 { diff --git a/src/cmd/internal/obj/s390x/asmz.go b/src/cmd/internal/obj/s390x/asmz.go index cf3b11424b..bae4dc3ce7 100644 --- a/src/cmd/internal/obj/s390x/asmz.go +++ b/src/cmd/internal/obj/s390x/asmz.go @@ -606,7 +606,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { a1 := int(p.Optab) if a1 != 0 { - return &optab[a1-1:][0] + return &optab[a1-1] } a1 = int(p.From.Class) if a1 == 0 { diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index c15b59b5e8..c563a7a48d 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -4452,9 +4452,8 @@ func asmins(ctxt *obj.Link, p *obj.Prog) { } n := ctxt.AsmBuf.Len() - var r *obj.Reloc for i := len(ctxt.Cursym.R) - 1; i >= 0; i-- { - r = &ctxt.Cursym.R[i:][0] + r := &ctxt.Cursym.R[i] if int64(r.Off) < p.Pc { break } diff --git a/src/cmd/link/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go index 1066d220f7..7daa8bc812 100644 --- a/src/cmd/link/internal/ld/decodesym.go +++ b/src/cmd/link/internal/ld/decodesym.go @@ -17,9 +17,9 @@ import ( // ../gc/reflect.c stuffs in these. func decode_reloc(s *LSym, off int32) *Reloc { - for i := 0; i < len(s.R); i++ { + for i := range s.R { if s.R[i].Off == off { - return &s.R[i:][0] + return &s.R[i] } } return nil diff --git a/src/cmd/link/internal/ld/ldelf.go b/src/cmd/link/internal/ld/ldelf.go index d9581a5189..d07a2a2c34 100644 --- a/src/cmd/link/internal/ld/ldelf.go +++ b/src/cmd/link/internal/ld/ldelf.go @@ -774,7 +774,7 @@ func ldelf(f *bio.Reader, pkg string, length int64, pn string) { if sym.sym == nil { continue } - sect = &elfobj.sect[sym.shndx:][0] + sect = &elfobj.sect[sym.shndx] if sect.sym == nil { if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this continue -- cgit v1.3 From f028b9f9e2433662502283850d06e9e07e72a6bb Mon Sep 17 00:00:00 2001 From: David Crawshaw Date: Sun, 27 Mar 2016 10:21:48 -0400 Subject: cmd/link, etc: store typelinks as offsets This is the first in a series of CLs to replace the use of pointers in binary read-only data with offsets. In standard Go binaries these CLs have a small effect, shrinking 8-byte pointers to 4-bytes. In position-independent code, it also saves the dynamic relocation for the pointer. This has a significant effect on the binary size when building as PIE, c-archive, or c-shared. darwin/amd64: cmd/go: -12KB (0.1%) jujud: -82KB (0.1%) linux/amd64 PIE: cmd/go: -86KB (0.7%) jujud: -569KB (0.7%) For #6853. Change-Id: Iad5625bbeba58dabfd4d334dbee3fcbfe04b2dcf Reviewed-on: https://go-review.googlesource.com/21284 Reviewed-by: Ian Lance Taylor Run-TryBot: David Crawshaw TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/go.go | 2 -- src/cmd/compile/internal/gc/main.go | 4 --- src/cmd/compile/internal/gc/obj.go | 6 +++++ src/cmd/compile/internal/gc/reflect.go | 17 +++++------- src/cmd/internal/obj/data.go | 21 ++++++++++++++- src/cmd/internal/obj/link.go | 3 +++ src/cmd/link/internal/ld/data.go | 18 +++++++++++++ src/cmd/link/internal/ld/symtab.go | 4 +++ src/reflect/export_test.go | 8 +++--- src/reflect/type.go | 47 ++++++++++++++++++++++------------ src/runtime/runtime1.go | 8 +++--- src/runtime/symtab.go | 3 ++- 12 files changed, 99 insertions(+), 42 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index d9b28ff8e6..5df49b56d6 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -171,8 +171,6 @@ var msanpkg *Pkg // package runtime/msan var typepkg *Pkg // fake package for runtime type info (headers) -var typelinkpkg *Pkg // fake package for runtime type info (data) - var unsafepkg *Pkg // package unsafe var trackpkg *Pkg // fake package for field tracking diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 26acf8861f..45a510d577 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -126,10 +126,6 @@ func Main() { itabpkg.Name = "go.itab" itabpkg.Prefix = "go.itab" // not go%2eitab - typelinkpkg = mkpkg("go.typelink") - typelinkpkg.Name = "go.typelink" - typelinkpkg.Prefix = "go.typelink" // not go%2etypelink - itablinkpkg = mkpkg("go.itablink") itablinkpkg.Name = "go.itablink" itablinkpkg.Prefix = "go.itablink" // not go%2eitablink diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 23c8be645c..eed0ed6e24 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -321,6 +321,12 @@ func dsymptrLSym(s *obj.LSym, off int, x *obj.LSym, xoff int) int { return off } +func dsymptrOffLSym(s *obj.LSym, off int, x *obj.LSym, xoff int) int { + s.WriteOff(Ctxt, int64(off), x, int64(xoff)) + off += 4 + return off +} + func gdata(nam *Node, nr *Node, wid int) { if nam.Op != ONAME { Fatalf("gdata nam op %v", opnames[nam.Op]) diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index df9ef27b7a..ea67634260 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -879,7 +879,7 @@ func tracksym(t *Type, f *Field) *Sym { return Pkglookup(Tconv(t, FmtLeft)+"."+f.Sym.Name, trackpkg) } -func typelinksym(t *Type) *Sym { +func typelinkLSym(t *Type) *obj.LSym { // %-uT is what the generated Type's string field says. // It uses (ambiguous) package names instead of import paths. // %-T is the complete, unambiguous type name. @@ -889,13 +889,8 @@ func typelinksym(t *Type) *Sym { // ensure the types appear sorted by their string field. The // names are a little long but they are discarded by the linker // and do not end up in the symbol table of the final binary. - p := Tconv(t, FmtLeft|FmtUnsigned) + "\t" + Tconv(t, FmtLeft) - - s := Pkglookup(p, typelinkpkg) - - //print("typelinksym: %s -> %+S\n", p, s); - - return s + name := "go.typelink." + Tconv(t, FmtLeft|FmtUnsigned) + "\t" + Tconv(t, FmtLeft) + return obj.Linklookup(Ctxt, name, 0) } func typesymprefix(prefix string, t *Type) *Sym { @@ -1298,9 +1293,9 @@ ok: if t.Sym == nil { switch t.Etype { case TPTR32, TPTR64, TARRAY, TCHAN, TFUNC, TMAP, TSTRUCT: - slink := typelinksym(t) - dsymptr(slink, 0, s, 0) - ggloblsym(slink, int32(Widthptr), int16(dupok|obj.RODATA)) + slink := typelinkLSym(t) + dsymptrOffLSym(slink, 0, Linksym(s), 0) + ggloblLSym(slink, 4, int16(dupok|obj.RODATA)) } } diff --git a/src/cmd/internal/obj/data.go b/src/cmd/internal/obj/data.go index 37ab70bb0e..546ff37269 100644 --- a/src/cmd/internal/obj/data.go +++ b/src/cmd/internal/obj/data.go @@ -111,17 +111,36 @@ func (s *LSym) WriteInt(ctxt *Link, off int64, siz int, i int64) { // rsym and roff specify the relocation for the address. func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) { if siz != ctxt.Arch.PtrSize { - ctxt.Diag("WriteAddr: bad address size: %d", siz) + ctxt.Diag("WriteAddr: bad address size %d in %s", siz, s.Name) } s.prepwrite(ctxt, off, siz) r := Addrel(s) r.Off = int32(off) + if int64(r.Off) != off { + ctxt.Diag("WriteAddr: off overflow %d in %s", off, s.Name) + } r.Siz = uint8(siz) r.Sym = rsym r.Type = R_ADDR r.Add = roff } +// WriteOff writes a 4 byte offset to rsym+roff into s at offset off. +// After linking the 4 bytes stored at s+off will be +// rsym+roff-(start of section that s is in). +func (s *LSym) WriteOff(ctxt *Link, off int64, rsym *LSym, roff int64) { + s.prepwrite(ctxt, off, 4) + r := Addrel(s) + r.Off = int32(off) + if int64(r.Off) != off { + ctxt.Diag("WriteOff: off overflow %d in %s", off, s.Name) + } + r.Siz = 4 + r.Sym = rsym + r.Type = R_ADDROFF + r.Add = roff +} + // WriteString writes a string of size siz into s at offset off. func (s *LSym) WriteString(ctxt *Link, off int64, siz int, str string) { if siz < len(str) { diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 62175f9ed8..d44d4398b1 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -457,6 +457,9 @@ const ( // R_ADDRMIPS (only used on mips64) resolves to a 32-bit external address, // by loading the address into a register with two instructions (lui, ori). R_ADDRMIPS + // R_ADDROFF resolves to an offset from the beginning of the section holding + // the data being relocated to the referenced symbol. + R_ADDROFF R_SIZE R_CALL R_CALLARM diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index ae7c287f59..cf51b0a908 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -525,6 +525,9 @@ func relocsym(s *LSym) { } o = Symaddr(r.Sym) + r.Add - int64(r.Sym.Sect.Vaddr) + case obj.R_ADDROFF: + o = Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr) + r.Add + // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call. case obj.R_CALL, obj.R_GOTPCREL, obj.R_PCREL: if Linkmode == LinkExternal && r.Sym != nil && r.Sym.Type != obj.SCONST && (r.Sym.Sect != Ctxt.Cursym.Sect || r.Type == obj.R_GOTPCREL) { @@ -1599,6 +1602,10 @@ func dodata() { sect.Vaddr = 0 Linklookup(Ctxt, "runtime.rodata", 0).Sect = sect Linklookup(Ctxt, "runtime.erodata", 0).Sect = sect + if !UseRelro() { + Linklookup(Ctxt, "runtime.types", 0).Sect = sect + Linklookup(Ctxt, "runtime.etypes", 0).Sect = sect + } for ; s != nil && s.Type < obj.STYPERELRO; s = s.Next { datsize = aligndatsize(datsize, s) s.Sect = sect @@ -1631,6 +1638,8 @@ func dodata() { sect.Align = maxalign(s, obj.STYPELINK-1) datsize = Rnd(datsize, int64(sect.Align)) sect.Vaddr = 0 + Linklookup(Ctxt, "runtime.types", 0).Sect = sect + Linklookup(Ctxt, "runtime.etypes", 0).Sect = sect for ; s != nil && s.Type < obj.STYPELINK; s = s.Next { datsize = aligndatsize(datsize, s) if s.Outer != nil && s.Outer.Sect != nil && s.Outer.Sect != sect { @@ -1970,10 +1979,12 @@ func address() { } else { rodata = text.Next } + var relrodata *Section typelink := rodata.Next if UseRelro() { // There is another section (.data.rel.ro) when building a shared // object on elf systems. + relrodata = typelink typelink = typelink.Next } itablink := typelink.Next @@ -2007,6 +2018,11 @@ func address() { s.Value = int64(sectSym.Sect.Vaddr + 16) } + types := relrodata + if types == nil { + types = rodata + } + xdefine("runtime.text", obj.STEXT, int64(text.Vaddr)) xdefine("runtime.etext", obj.STEXT, int64(text.Vaddr+text.Length)) if HEADTYPE == obj.Hwindows { @@ -2014,6 +2030,8 @@ func address() { } xdefine("runtime.rodata", obj.SRODATA, int64(rodata.Vaddr)) xdefine("runtime.erodata", obj.SRODATA, int64(rodata.Vaddr+rodata.Length)) + xdefine("runtime.types", obj.SRODATA, int64(types.Vaddr)) + xdefine("runtime.etypes", obj.SRODATA, int64(types.Vaddr+types.Length)) xdefine("runtime.typelink", obj.SRODATA, int64(typelink.Vaddr)) xdefine("runtime.etypelink", obj.SRODATA, int64(typelink.Vaddr+typelink.Length)) xdefine("runtime.itablink", obj.SRODATA, int64(itablink.Vaddr)) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index ae0b17c259..678ed38730 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -329,6 +329,8 @@ func symtab() { xdefine("runtime.eitablink", obj.SRODATA, 0) xdefine("runtime.rodata", obj.SRODATA, 0) xdefine("runtime.erodata", obj.SRODATA, 0) + xdefine("runtime.types", obj.SRODATA, 0) + xdefine("runtime.etypes", obj.SRODATA, 0) xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0) xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0) xdefine("runtime.data", obj.SDATA, 0) @@ -537,6 +539,8 @@ func symtab() { Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.end", 0)) Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcdata", 0)) Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0)) + Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.types", 0)) + Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etypes", 0)) // The typelinks slice Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0)) adduint(Ctxt, moduledata, uint64(ntypelinks)) diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go index ddc64b46be..037c953718 100644 --- a/src/reflect/export_test.go +++ b/src/reflect/export_test.go @@ -46,9 +46,11 @@ func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr, func TypeLinks() []string { var r []string - for _, m := range typelinks() { - for _, t := range m { - r = append(r, t.string) + sections, offset := typelinks() + for i, offs := range offset { + rodata := sections[i] + for _, off := range offs { + r = append(r, rtypeOff(rodata, off).string) } } return r diff --git a/src/reflect/type.go b/src/reflect/type.go index 8f13acf26e..7104fde60a 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -1558,30 +1558,48 @@ func haveIdenticalUnderlyingType(T, V *rtype) bool { } // typelinks is implemented in package runtime. -// It returns a slice of all the 'typelink' information in the binary, -// which is to say a slice of known types, sorted by string. +// It returns a slice of the sections in each module, +// and a slice of *rtype offsets in each module. +// +// The types in each module are sorted by string. That is, the first +// two linked types of the first module are: +// +// d0 := sections[0] +// t1 := (*rtype)(add(d0, offset[0][0])) +// t2 := (*rtype)(add(d0, offset[0][1])) +// +// and +// +// t1.string < t2.string +// // Note that strings are not unique identifiers for types: // there can be more than one with a given string. // Only types we might want to look up are included: // pointers, channels, maps, slices, and arrays. -func typelinks() [][]*rtype +func typelinks() (sections []unsafe.Pointer, offset [][]int32) + +func rtypeOff(section unsafe.Pointer, off int32) *rtype { + return (*rtype)(add(section, uintptr(off))) +} // typesByString returns the subslice of typelinks() whose elements have // the given string representation. // It may be empty (no known types with that string) or may have // multiple elements (multiple types with that string). func typesByString(s string) []*rtype { - typs := typelinks() + sections, offset := typelinks() var ret []*rtype - for _, typ := range typs { + for offsI, offs := range offset { + section := sections[offsI] + // We are looking for the first index i where the string becomes >= s. // This is a copy of sort.Search, with f(h) replaced by (*typ[h].string >= s). - i, j := 0, len(typ) + i, j := 0, len(offs) for i < j { h := i + (j-i)/2 // avoid overflow when computing h // i ≤ h < j - if !(typ[h].string >= s) { + if !(rtypeOff(section, offs[h]).string >= s) { i = h + 1 // preserves f(i-1) == false } else { j = h // preserves f(j) == true @@ -1592,17 +1610,12 @@ func typesByString(s string) []*rtype { // Having found the first, linear scan forward to find the last. // We could do a second binary search, but the caller is going // to do a linear scan anyway. - j = i - for j < len(typ) && typ[j].string == s { - j++ - } - - if j > i { - if ret == nil { - ret = typ[i:j:j] - } else { - ret = append(ret, typ[i:j]...) + for j := i; j < len(offs); j++ { + typ := rtypeOff(section, offs[j]) + if typ.string != s { + break } + ret = append(ret, typ) } } return ret diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index 95bebac593..e1956569fd 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -477,10 +477,12 @@ func gomcache() *mcache { } //go:linkname reflect_typelinks reflect.typelinks -func reflect_typelinks() [][]*_type { - ret := [][]*_type{firstmoduledata.typelinks} +func reflect_typelinks() ([]unsafe.Pointer, [][]int32) { + sections := []unsafe.Pointer{unsafe.Pointer(firstmoduledata.types)} + ret := [][]int32{firstmoduledata.typelinks} for datap := firstmoduledata.next; datap != nil; datap = datap.next { + sections = append(sections, unsafe.Pointer(datap.types)) ret = append(ret, datap.typelinks) } - return ret + return sections, ret } diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 158bdcea0d..8c70f22c1f 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -127,8 +127,9 @@ type moduledata struct { bss, ebss uintptr noptrbss, enoptrbss uintptr end, gcdata, gcbss uintptr + types, etypes uintptr - typelinks []*_type + typelinks []int32 // offsets from types itablinks []*itab modulename string -- cgit v1.3 From 24fc3234428e138e693584185fab4146de6088db Mon Sep 17 00:00:00 2001 From: Shahar Kohanim Date: Mon, 11 Apr 2016 17:35:55 +0300 Subject: cmd/internal/obj: split plist flushing from object writing Only splits into separate files, no other changes. Change-Id: Icc0da2c5f18e03e9ed7c0043bd7c790f741900f2 Reviewed-on: https://go-review.googlesource.com/21804 Reviewed-by: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot --- src/cmd/internal/obj/link.go | 21 ---- src/cmd/internal/obj/objfile.go | 187 ---------------------------------- src/cmd/internal/obj/plist.go | 218 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+), 208 deletions(-) create mode 100644 src/cmd/internal/obj/plist.go (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index d44d4398b1..146be6f98f 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -730,27 +730,6 @@ const ( Hwindows ) -type Plist struct { - Name *LSym - Firstpc *Prog - Recur int - Link *Plist -} - -/* - * start a new Prog list. - */ -func Linknewplist(ctxt *Link) *Plist { - pl := new(Plist) - if ctxt.Plist == nil { - ctxt.Plist = pl - } else { - ctxt.Plast.Link = pl - } - ctxt.Plast = pl - return pl -} - // AsmBuf is a simple buffer to assemble variable-length x86 instructions into. type AsmBuf struct { buf [100]byte diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index ee21f39d10..7d88db2bcc 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -115,7 +115,6 @@ import ( "log" "path/filepath" "sort" - "strings" ) // The Go and C compilers, and the assembler, call writeobj to write @@ -126,192 +125,6 @@ func Writeobjdirect(ctxt *Link, b *bio.Writer) { WriteObjFile(ctxt, b) } -func Flushplist(ctxt *Link) { - flushplist(ctxt, ctxt.Debugasm == 0) -} -func FlushplistNoFree(ctxt *Link) { - flushplist(ctxt, false) -} -func flushplist(ctxt *Link, freeProgs bool) { - // Build list of symbols, and assign instructions to lists. - // Ignore ctxt->plist boundaries. There are no guarantees there, - // and the assemblers just use one big list. - var curtext *LSym - var etext *Prog - var text []*LSym - - for pl := ctxt.Plist; pl != nil; pl = pl.Link { - var plink *Prog - for p := pl.Firstpc; p != nil; p = plink { - if ctxt.Debugasm != 0 && ctxt.Debugvlog != 0 { - fmt.Printf("obj: %v\n", p) - } - plink = p.Link - p.Link = nil - - switch p.As { - case AEND: - continue - - case ATYPE: - // Assume each TYPE instruction describes - // a different local variable or parameter, - // so no dedup. - // Using only the TYPE instructions means - // that we discard location information about local variables - // in C and assembly functions; that information is inferred - // from ordinary references, because there are no TYPE - // instructions there. Without the type information, gdb can't - // use the locations, so we don't bother to save them. - // If something else could use them, we could arrange to - // preserve them. - if curtext == nil { - continue - } - a := new(Auto) - a.Asym = p.From.Sym - a.Aoffset = int32(p.From.Offset) - a.Name = int16(p.From.Name) - a.Gotype = p.From.Gotype - a.Link = curtext.Autom - curtext.Autom = a - continue - - case AGLOBL: - s := p.From.Sym - if s.Seenglobl { - fmt.Printf("duplicate %v\n", p) - } - s.Seenglobl = true - if s.Onlist { - log.Fatalf("symbol %s listed multiple times", s.Name) - } - s.Onlist = true - ctxt.Data = append(ctxt.Data, s) - s.Size = p.To.Offset - if s.Type == 0 || s.Type == SXREF { - s.Type = SBSS - } - flag := int(p.From3.Offset) - if flag&DUPOK != 0 { - s.Dupok = true - } - if flag&RODATA != 0 { - s.Type = SRODATA - } else if flag&NOPTR != 0 { - s.Type = SNOPTRBSS - } else if flag&TLSBSS != 0 { - s.Type = STLSBSS - } - continue - - case ATEXT: - s := p.From.Sym - if s == nil { - // func _() { } - curtext = nil - - continue - } - - if s.Text != nil { - log.Fatalf("duplicate TEXT for %s", s.Name) - } - if s.Onlist { - log.Fatalf("symbol %s listed multiple times", s.Name) - } - s.Onlist = true - text = append(text, s) - flag := int(p.From3Offset()) - if flag&DUPOK != 0 { - s.Dupok = true - } - if flag&NOSPLIT != 0 { - s.Nosplit = true - } - if flag&REFLECTMETHOD != 0 { - s.ReflectMethod = true - } - s.Type = STEXT - s.Text = p - etext = p - curtext = s - continue - - case AFUNCDATA: - // Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information. - if curtext == nil { // func _() {} - continue - } - if p.To.Sym.Name == "go_args_stackmap" { - if p.From.Type != TYPE_CONST || p.From.Offset != FUNCDATA_ArgsPointerMaps { - ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps") - } - p.To.Sym = Linklookup(ctxt, fmt.Sprintf("%s.args_stackmap", curtext.Name), int(curtext.Version)) - } - - } - - if curtext == nil { - etext = nil - continue - } - etext.Link = p - etext = p - } - } - - // Add reference to Go arguments for C or assembly functions without them. - for _, s := range text { - if !strings.HasPrefix(s.Name, "\"\".") { - continue - } - found := false - var p *Prog - for p = s.Text; p != nil; p = p.Link { - if p.As == AFUNCDATA && p.From.Type == TYPE_CONST && p.From.Offset == FUNCDATA_ArgsPointerMaps { - found = true - break - } - } - - if !found { - p = Appendp(ctxt, s.Text) - p.As = AFUNCDATA - p.From.Type = TYPE_CONST - p.From.Offset = FUNCDATA_ArgsPointerMaps - p.To.Type = TYPE_MEM - p.To.Name = NAME_EXTERN - p.To.Sym = Linklookup(ctxt, fmt.Sprintf("%s.args_stackmap", s.Name), int(s.Version)) - } - } - - // Turn functions into machine code images. - for _, s := range text { - mkfwd(s) - linkpatch(ctxt, s) - if ctxt.Flag_optimize { - ctxt.Arch.Follow(ctxt, s) - } - ctxt.Arch.Preprocess(ctxt, s) - ctxt.Arch.Assemble(ctxt, s) - fieldtrack(ctxt, s) - linkpcln(ctxt, s) - if freeProgs { - s.Text = nil - } - } - - // Add to running list in ctxt. - ctxt.Text = append(ctxt.Text, text...) - ctxt.Plist = nil - ctxt.Plast = nil - ctxt.Curp = nil - if freeProgs { - ctxt.freeProgs() - } -} - // objWriter writes Go object files. type objWriter struct { wr *bufio.Writer diff --git a/src/cmd/internal/obj/plist.go b/src/cmd/internal/obj/plist.go new file mode 100644 index 0000000000..e55dbeca1e --- /dev/null +++ b/src/cmd/internal/obj/plist.go @@ -0,0 +1,218 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package obj + +import ( + "fmt" + "log" + "strings" +) + +type Plist struct { + Name *LSym + Firstpc *Prog + Recur int + Link *Plist +} + +/* + * start a new Prog list. + */ +func Linknewplist(ctxt *Link) *Plist { + pl := new(Plist) + if ctxt.Plist == nil { + ctxt.Plist = pl + } else { + ctxt.Plast.Link = pl + } + ctxt.Plast = pl + return pl +} + +func Flushplist(ctxt *Link) { + flushplist(ctxt, ctxt.Debugasm == 0) +} +func FlushplistNoFree(ctxt *Link) { + flushplist(ctxt, false) +} +func flushplist(ctxt *Link, freeProgs bool) { + // Build list of symbols, and assign instructions to lists. + // Ignore ctxt->plist boundaries. There are no guarantees there, + // and the assemblers just use one big list. + var curtext *LSym + var etext *Prog + var text []*LSym + + for pl := ctxt.Plist; pl != nil; pl = pl.Link { + var plink *Prog + for p := pl.Firstpc; p != nil; p = plink { + if ctxt.Debugasm != 0 && ctxt.Debugvlog != 0 { + fmt.Printf("obj: %v\n", p) + } + plink = p.Link + p.Link = nil + + switch p.As { + case AEND: + continue + + case ATYPE: + // Assume each TYPE instruction describes + // a different local variable or parameter, + // so no dedup. + // Using only the TYPE instructions means + // that we discard location information about local variables + // in C and assembly functions; that information is inferred + // from ordinary references, because there are no TYPE + // instructions there. Without the type information, gdb can't + // use the locations, so we don't bother to save them. + // If something else could use them, we could arrange to + // preserve them. + if curtext == nil { + continue + } + a := new(Auto) + a.Asym = p.From.Sym + a.Aoffset = int32(p.From.Offset) + a.Name = int16(p.From.Name) + a.Gotype = p.From.Gotype + a.Link = curtext.Autom + curtext.Autom = a + continue + + case AGLOBL: + s := p.From.Sym + if s.Seenglobl { + fmt.Printf("duplicate %v\n", p) + } + s.Seenglobl = true + if s.Onlist { + log.Fatalf("symbol %s listed multiple times", s.Name) + } + s.Onlist = true + ctxt.Data = append(ctxt.Data, s) + s.Size = p.To.Offset + if s.Type == 0 || s.Type == SXREF { + s.Type = SBSS + } + flag := int(p.From3.Offset) + if flag&DUPOK != 0 { + s.Dupok = true + } + if flag&RODATA != 0 { + s.Type = SRODATA + } else if flag&NOPTR != 0 { + s.Type = SNOPTRBSS + } else if flag&TLSBSS != 0 { + s.Type = STLSBSS + } + continue + + case ATEXT: + s := p.From.Sym + if s == nil { + // func _() { } + curtext = nil + + continue + } + + if s.Text != nil { + log.Fatalf("duplicate TEXT for %s", s.Name) + } + if s.Onlist { + log.Fatalf("symbol %s listed multiple times", s.Name) + } + s.Onlist = true + text = append(text, s) + flag := int(p.From3Offset()) + if flag&DUPOK != 0 { + s.Dupok = true + } + if flag&NOSPLIT != 0 { + s.Nosplit = true + } + if flag&REFLECTMETHOD != 0 { + s.ReflectMethod = true + } + s.Type = STEXT + s.Text = p + etext = p + curtext = s + continue + + case AFUNCDATA: + // Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information. + if curtext == nil { // func _() {} + continue + } + if p.To.Sym.Name == "go_args_stackmap" { + if p.From.Type != TYPE_CONST || p.From.Offset != FUNCDATA_ArgsPointerMaps { + ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps") + } + p.To.Sym = Linklookup(ctxt, fmt.Sprintf("%s.args_stackmap", curtext.Name), int(curtext.Version)) + } + + } + + if curtext == nil { + etext = nil + continue + } + etext.Link = p + etext = p + } + } + + // Add reference to Go arguments for C or assembly functions without them. + for _, s := range text { + if !strings.HasPrefix(s.Name, "\"\".") { + continue + } + found := false + var p *Prog + for p = s.Text; p != nil; p = p.Link { + if p.As == AFUNCDATA && p.From.Type == TYPE_CONST && p.From.Offset == FUNCDATA_ArgsPointerMaps { + found = true + break + } + } + + if !found { + p = Appendp(ctxt, s.Text) + p.As = AFUNCDATA + p.From.Type = TYPE_CONST + p.From.Offset = FUNCDATA_ArgsPointerMaps + p.To.Type = TYPE_MEM + p.To.Name = NAME_EXTERN + p.To.Sym = Linklookup(ctxt, fmt.Sprintf("%s.args_stackmap", s.Name), int(s.Version)) + } + } + + // Turn functions into machine code images. + for _, s := range text { + mkfwd(s) + linkpatch(ctxt, s) + if ctxt.Flag_optimize { + ctxt.Arch.Follow(ctxt, s) + } + ctxt.Arch.Preprocess(ctxt, s) + ctxt.Arch.Assemble(ctxt, s) + fieldtrack(ctxt, s) + linkpcln(ctxt, s) + if freeProgs { + s.Text = nil + } + } + + // Add to running list in ctxt. + ctxt.Text = append(ctxt.Text, text...) + ctxt.Plist = nil + ctxt.Plast = nil + ctxt.Curp = nil + if freeProgs { + ctxt.freeProgs() + } +} -- cgit v1.3 From e46b00a43b62bd67ec13ca75c51037db3b312043 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 12 Apr 2016 14:44:49 -0700 Subject: cmd/internal/obj: remove unused Pciter type Change-Id: Ie8323cfcd1193f390729d0d3dd67863aedf47d13 Reviewed-on: https://go-review.googlesource.com/21906 Run-TryBot: Matthew Dempsky Reviewed-by: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/cmd/internal/obj/link.go | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 146be6f98f..42aaa5f4f0 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -600,19 +600,6 @@ type Pcdata struct { P []byte } -// Pcdata iterator. -// for(pciterinit(ctxt, &it, &pcd); !it.done; pciternext(&it)) { it.value holds in [it.pc, it.nextpc) } -type Pciter struct { - d Pcdata - p []byte - pc uint32 - nextpc uint32 - pcscale uint32 - value int32 - start int - done int -} - // symbol version, incremented each time a file is loaded. // version==1 is reserved for savehist. const ( -- cgit v1.3 From 7d469179e6e3dafe16700b7fc1cf8683ad9453fa Mon Sep 17 00:00:00 2001 From: David Crawshaw Date: Mon, 28 Mar 2016 10:32:27 -0400 Subject: cmd/compile, etc: store method tables as offsets This CL introduces the typeOff type and a lookup method of the same name that can turn a typeOff offset into an *rtype. In a typical Go binary (built with buildmode=exe, pie, c-archive, or c-shared), there is one moduledata and all typeOff values are offsets relative to firstmoduledata.types. This makes computing the pointer cheap in typical programs. With buildmode=shared (and one day, buildmode=plugin) there are multiple modules whose relative offset is determined at runtime. We identify a type in the general case by the pair of the original *rtype that references it and its typeOff value. We determine the module from the original pointer, and then use the typeOff from there to compute the final *rtype. To ensure there is only one *rtype representing each type, the runtime initializes a typemap for each module, using any identical type from an earlier module when resolving that offset. This means that types computed from an offset match the type mapped by the pointer dynamic relocations. A series of followup CLs will replace other *rtype values with typeOff (and name/*string with nameOff). For types created at runtime by reflect, type offsets are treated as global IDs and reference into a reflect offset map kept by the runtime. darwin/amd64: cmd/go: -57KB (0.6%) jujud: -557KB (0.8%) linux/amd64 PIE: cmd/go: -361KB (3.0%) jujud: -3.5MB (4.2%) For #6853. Change-Id: Icf096fd884a0a0cb9f280f46f7a26c70a9006c96 Reviewed-on: https://go-review.googlesource.com/21285 Reviewed-by: Ian Lance Taylor Run-TryBot: David Crawshaw TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/reflect.go | 75 +++++--- src/cmd/internal/obj/link.go | 15 +- src/cmd/link/internal/ld/deadcode.go | 14 +- src/cmd/link/internal/ld/decodesym.go | 22 +-- src/reflect/export_test.go | 2 +- src/reflect/type.go | 267 +++++++++++++++++++++------- src/reflect/value.go | 15 +- src/runtime/iface.go | 10 +- src/runtime/proc.go | 3 +- src/runtime/runtime1.go | 33 ++++ src/runtime/symtab.go | 2 + src/runtime/type.go | 307 ++++++++++++++++++++++++++++++++- 12 files changed, 637 insertions(+), 128 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index ea67634260..2bd50b4665 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -75,7 +75,7 @@ func uncommonSize(t *Type) int { // Sizeof(runtime.uncommontype{}) if t.Sym == nil && len(methods(t)) == 0 { return 0 } - return 2*Widthptr + 2*Widthint + return 2 * Widthptr } func makefield(name string, t *Type) *Field { @@ -580,13 +580,23 @@ func dextratype(s *Sym, ot int, t *Type, dataAdd int) int { ot = dgopkgpath(s, ot, typePkg(t)) - // slice header - ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint+dataAdd) - - n := len(m) - ot = duintxx(s, ot, uint64(n), Widthint) - ot = duintxx(s, ot, uint64(n), Widthint) + dataAdd += Widthptr + 2 + 2 + if Widthptr == 8 { + dataAdd += 4 + } + mcount := len(m) + if mcount != int(uint16(mcount)) { + Fatalf("too many methods on %s: %d", t, mcount) + } + if dataAdd != int(uint16(dataAdd)) { + Fatalf("methods are too far away on %s: %d", t, dataAdd) + } + ot = duint16(s, ot, uint16(mcount)) + ot = duint16(s, ot, uint16(dataAdd)) + if Widthptr == 8 { + ot = duint32(s, ot, 0) // align for following pointers + } return ot } @@ -609,6 +619,7 @@ func typePkg(t *Type) *Pkg { // dextratypeData dumps the backing array for the []method field of // runtime.uncommontype. func dextratypeData(s *Sym, ot int, t *Type) int { + lsym := Linksym(s) for _, a := range methods(t) { // ../../../../runtime/type.go:/method exported := exportname(a.name) @@ -617,21 +628,24 @@ func dextratypeData(s *Sym, ot int, t *Type) int { pkg = a.pkg } ot = dname(s, ot, a.name, "", pkg, exported) - ot = dmethodptr(s, ot, dtypesym(a.mtype)) - ot = dmethodptr(s, ot, a.isym) - ot = dmethodptr(s, ot, a.tsym) + ot = dmethodptrOffLSym(lsym, ot, Linksym(dtypesym(a.mtype))) + ot = dmethodptrOffLSym(lsym, ot, Linksym(a.isym)) + ot = dmethodptrOffLSym(lsym, ot, Linksym(a.tsym)) + if Widthptr == 8 { + ot = duintxxLSym(lsym, ot, 0, 4) // pad to reflect.method size + } } return ot } -func dmethodptr(s *Sym, off int, x *Sym) int { - duintptr(s, off, 0) - r := obj.Addrel(Linksym(s)) - r.Off = int32(off) - r.Siz = uint8(Widthptr) - r.Sym = Linksym(x) - r.Type = obj.R_METHOD - return off + Widthptr +func dmethodptrOffLSym(s *obj.LSym, ot int, x *obj.LSym) int { + duintxxLSym(s, ot, 0, 4) + r := obj.Addrel(s) + r.Off = int32(ot) + r.Siz = 4 + r.Sym = x + r.Type = obj.R_METHODOFF + return ot + 4 } var kinds = []int{ @@ -1286,18 +1300,29 @@ ok: ggloblsym(s, int32(ot), int16(dupok|obj.RODATA)) // generate typelink.foo pointing at s = type.foo. + // // The linker will leave a table of all the typelinks for - // types in the binary, so reflect can find them. - // We only need the link for unnamed composites that - // we want be able to find. - if t.Sym == nil { + // types in the binary, so the runtime can find them. + // + // When buildmode=shared, all types are in typelinks so the + // runtime can deduplicate type pointers. + keep := Ctxt.Flag_dynlink + if !keep && t.Sym == nil { + // For an unnamed type, we only need the link if the type can + // be created at run time by reflect.PtrTo and similar + // functions. If the type exists in the program, those + // functions must return the existing type structure rather + // than creating a new one. switch t.Etype { case TPTR32, TPTR64, TARRAY, TCHAN, TFUNC, TMAP, TSTRUCT: - slink := typelinkLSym(t) - dsymptrOffLSym(slink, 0, Linksym(s), 0) - ggloblLSym(slink, 4, int16(dupok|obj.RODATA)) + keep = true } } + if keep { + slink := typelinkLSym(t) + dsymptrOffLSym(slink, 0, Linksym(s), 0) + ggloblLSym(slink, 4, int16(dupok|obj.RODATA)) + } return s } diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 42aaa5f4f0..55c9f4f9e2 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -457,8 +457,8 @@ const ( // R_ADDRMIPS (only used on mips64) resolves to a 32-bit external address, // by loading the address into a register with two instructions (lui, ori). R_ADDRMIPS - // R_ADDROFF resolves to an offset from the beginning of the section holding - // the data being relocated to the referenced symbol. + // R_ADDROFF resolves to a 32-bit offset from the beginning of the section + // holding the data being relocated to the referenced symbol. R_ADDROFF R_SIZE R_CALL @@ -492,11 +492,12 @@ const ( // should be linked into the final binary, even if there are no other // direct references. (This is used for types reachable by reflection.) R_USETYPE - // R_METHOD resolves to an *rtype for a method. - // It is used when linking from the uncommonType of another *rtype, and - // may be set to zero by the linker if it determines the method text is - // unreachable by the linked program. - R_METHOD + // R_METHODOFF resolves to a 32-bit offset from the beginning of the section + // holding the data being relocated to the referenced symbol. + // It is a variant of R_ADDROFF used when linking from the uncommonType of a + // *rtype, and may be set to zero by the linker if it determines the method + // text is unreachable by the linked program. + R_METHODOFF R_POWER_TOC R_GOTPCREL // R_JMPMIPS (only used on mips64) resolves to non-PC-relative target address diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go index 51fae02ef0..c83a104a54 100644 --- a/src/cmd/link/internal/ld/deadcode.go +++ b/src/cmd/link/internal/ld/deadcode.go @@ -19,7 +19,7 @@ import ( // // This flood fill is wrapped in logic for pruning unused methods. // All methods are mentioned by relocations on their receiver's *rtype. -// These relocations are specially defined as R_METHOD by the compiler +// These relocations are specially defined as R_METHODOFF by the compiler // so we can detect and manipulated them here. // // There are three ways a method of a reachable type can be invoked: @@ -100,7 +100,7 @@ func deadcode(ctxt *Link) { d.flood() } - // Remove all remaining unreached R_METHOD relocations. + // Remove all remaining unreached R_METHODOFF relocations. for _, m := range d.markableMethods { for _, r := range m.r { d.cleanupReloc(r) @@ -167,7 +167,7 @@ var markextra = []string{ type methodref struct { m methodsig src *LSym // receiver type symbol - r [3]*Reloc // R_METHOD relocations to fields of runtime.method + r [3]*Reloc // R_METHODOFF relocations to fields of runtime.method } func (m methodref) ifn() *LSym { return m.r[1].Sym } @@ -190,7 +190,7 @@ type deadcodepass struct { func (d *deadcodepass) cleanupReloc(r *Reloc) { if r.Sym.Attr.Reachable() { - r.Type = obj.R_ADDR + r.Type = obj.R_ADDROFF } else { if Debug['v'] > 1 { fmt.Fprintf(d.ctxt.Bso, "removing method %s\n", r.Sym.Name) @@ -217,7 +217,7 @@ func (d *deadcodepass) mark(s, parent *LSym) { func (d *deadcodepass) markMethod(m methodref) { for _, r := range m.r { d.mark(r.Sym, m.src) - r.Type = obj.R_ADDR + r.Type = obj.R_ADDROFF } } @@ -291,14 +291,14 @@ func (d *deadcodepass) flood() { } } - mpos := 0 // 0-3, the R_METHOD relocs of runtime.uncommontype + mpos := 0 // 0-3, the R_METHODOFF relocs of runtime.uncommontype var methods []methodref for i := 0; i < len(s.R); i++ { r := &s.R[i] if r.Sym == nil { continue } - if r.Type != obj.R_METHOD { + if r.Type != obj.R_METHODOFF { d.mark(r.Sym, s) continue } diff --git a/src/cmd/link/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go index 7daa8bc812..5fa8b4c81f 100644 --- a/src/cmd/link/internal/ld/decodesym.go +++ b/src/cmd/link/internal/ld/decodesym.go @@ -47,9 +47,9 @@ func decode_inuxi(p []byte, sz int) uint64 { } } -func commonsize() int { return 6*SysArch.PtrSize + 8 } // runtime._type -func structfieldSize() int { return 3 * SysArch.PtrSize } // runtime.structfield -func uncommonSize() int { return 2*SysArch.PtrSize + 2*SysArch.IntSize } // runtime.uncommontype +func commonsize() int { return 6*SysArch.PtrSize + 8 } // runtime._type +func structfieldSize() int { return 3 * SysArch.PtrSize } // runtime.structfield +func uncommonSize() int { return 2 * SysArch.PtrSize } // runtime.uncommontype // Type.commonType.kind func decodetype_kind(s *LSym) uint8 { @@ -341,12 +341,14 @@ func decodetype_methods(s *LSym) []methodsig { // just Sizeof(rtype) } - numMethods := int(decode_inuxi(s.P[off+2*SysArch.PtrSize:], SysArch.IntSize)) - r := decode_reloc(s, int32(off+SysArch.PtrSize)) - if r.Sym != s { - panic(fmt.Sprintf("method slice pointer in %s leads to a different symbol %s", s, r.Sym)) + mcount := int(decode_inuxi(s.P[off+SysArch.PtrSize:], 2)) + moff := int(decode_inuxi(s.P[off+SysArch.PtrSize+2:], 2)) + off += moff // offset to array of reflect.method values + var sizeofMethod int // sizeof reflect.method in program + if SysArch.PtrSize == 4 { + sizeofMethod = 4 * SysArch.PtrSize + } else { + sizeofMethod = 3 * SysArch.PtrSize } - off = int(r.Add) // array of reflect.method values - sizeofMethod := 4 * SysArch.PtrSize // sizeof reflect.method in program - return decode_methodsig(s, off, sizeofMethod, numMethods) + return decode_methodsig(s, off, sizeofMethod, mcount) } diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go index 037c953718..2769e0db40 100644 --- a/src/reflect/export_test.go +++ b/src/reflect/export_test.go @@ -90,7 +90,7 @@ func FirstMethodNameBytes(t Type) *byte { if ut == nil { panic("type has no methods") } - m := ut.methods[0] + m := ut.methods()[0] if *m.name.data(0)&(1<<2) == 0 { panic("method name does not have pkgPath *string") } diff --git a/src/reflect/type.go b/src/reflect/type.go index 7104fde60a..c7ed402be2 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -288,10 +288,10 @@ type typeAlg struct { // Method on non-interface type type method struct { - name name // name of method - mtyp *rtype // method type (without receiver) - ifn unsafe.Pointer // fn used in interface call (one-word receiver) - tfn unsafe.Pointer // fn used for normal method call + name name // name of method + mtyp typeOff // method type (without receiver) + ifn textOff // fn used in interface call (one-word receiver) + tfn textOff // fn used for normal method call } // uncommonType is present only for types with names or methods @@ -299,8 +299,9 @@ type method struct { // Using a pointer to this struct reduces the overall size required // to describe an unnamed type with no methods. type uncommonType struct { - pkgPath *string // import path; nil for built-in types like int, string - methods []method // methods associated with type + pkgPath *string // import path; nil for built-in types like int, string + mcount uint16 // number of methods + moff uint16 // offset from this uncommontype to [mcount]method } // ChanDir represents a channel type's direction. @@ -589,6 +590,10 @@ var kindNames = []string{ UnsafePointer: "unsafe.Pointer", } +func (t *uncommonType) methods() []method { + return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff)))[:t.mcount:t.mcount] +} + func (t *uncommonType) PkgPath() string { if t == nil || t.pkgPath == nil { return "" @@ -596,13 +601,55 @@ func (t *uncommonType) PkgPath() string { return *t.pkgPath } +// resolveTypeOff resolves an *rtype offset from a base type. +// The (*rtype).typeOff method is a convenience wrapper for this function. +// Implemented in the runtime package. +func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer + +// resolveTextOff resolves an function pointer offset from a base type. +// The (*rtype).textOff method is a convenience wrapper for this function. +// Implemented in the runtime package. +func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer + +// addReflectOff adds a pointer to the reflection lookup map in the runtime. +// It returns a new ID that can be used as a typeOff or textOff, and will +// be resolved correctly. Implemented in the runtime package. +func addReflectOff(ptr unsafe.Pointer) int32 + +// resolveReflectType adds a *rtype to the reflection lookup map in the runtime. +// It returns a new typeOff that can be used to refer to the pointer. +func resolveReflectType(t *rtype) typeOff { + return typeOff(addReflectOff(unsafe.Pointer(t))) +} + +// resolveReflectText adds a function pointer to the reflection lookup map in +// the runtime. It returns a new textOff that can be used to refer to the +// pointer. +func resolveReflectText(ptr unsafe.Pointer) textOff { + return textOff(addReflectOff(ptr)) +} + +type typeOff int32 // offset to an *rtype +type textOff int32 // offset from top of text section + +func (t *rtype) typeOff(off typeOff) *rtype { + if off == 0 { + return nil + } + return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off))) +} + +func (t *rtype) textOff(off textOff) unsafe.Pointer { + return resolveTextOff(unsafe.Pointer(t), int32(off)) +} + func (t *rtype) uncommon() *uncommonType { if t.tflag&tflagUncommon == 0 { return nil } switch t.Kind() { case Struct: - return &(*structTypeWithMethods)(unsafe.Pointer(t)).u + return &(*structTypeUncommon)(unsafe.Pointer(t)).u case Ptr: type u struct { ptrType @@ -688,7 +735,7 @@ func (t *rtype) NumMethod() int { if ut == nil { return 0 } - return len(ut.methods) + return int(ut.mcount) } func (t *rtype) Method(i int) (m Method) { @@ -698,10 +745,10 @@ func (t *rtype) Method(i int) (m Method) { } ut := t.uncommon() - if ut == nil || i < 0 || i >= len(ut.methods) { + if ut == nil || i < 0 || i >= int(ut.mcount) { panic("reflect: Method index out of range") } - p := &ut.methods[i] + p := ut.methods()[i] m.Name = p.name.name() fl := flag(Func) if !p.name.isExported() { @@ -712,8 +759,9 @@ func (t *rtype) Method(i int) (m Method) { m.PkgPath = *pkgPath fl |= flagStickyRO } - if p.mtyp != nil { - ft := (*funcType)(unsafe.Pointer(p.mtyp)) + if p.mtyp != 0 { + mtyp := t.typeOff(p.mtyp) + ft := (*funcType)(unsafe.Pointer(mtyp)) in := make([]Type, 0, 1+len(ft.in())) in = append(in, t) for _, arg := range ft.in() { @@ -723,9 +771,10 @@ func (t *rtype) Method(i int) (m Method) { for _, ret := range ft.out() { out = append(out, ret) } - mt := FuncOf(in, out, p.mtyp.IsVariadic()) + mt := FuncOf(in, out, ft.IsVariadic()) m.Type = mt - fn := unsafe.Pointer(&p.tfn) + tfn := t.textOff(p.tfn) + fn := unsafe.Pointer(&tfn) m.Func = Value{mt.(*rtype), fn, fl} } m.Index = i @@ -741,8 +790,9 @@ func (t *rtype) MethodByName(name string) (m Method, ok bool) { if ut == nil { return Method{}, false } - for i := range ut.methods { - p := &ut.methods[i] + utmethods := ut.methods() + for i := 0; i < int(ut.mcount); i++ { + p := utmethods[i] if p.name.name() == name { return t.Method(i), true } @@ -1430,10 +1480,11 @@ func implements(T, V *rtype) bool { return false } i := 0 - for j := 0; j < len(v.methods); j++ { + vmethods := v.methods() + for j := 0; j < int(v.mcount); j++ { tm := &t.methods[i] - vm := &v.methods[j] - if vm.name.name() == tm.name.name() && vm.mtyp == tm.typ { + vm := vmethods[j] + if vm.name.name() == tm.name.name() && V.typeOff(vm.mtyp) == tm.typ { if i++; i >= len(t.methods) { return true } @@ -2161,21 +2212,55 @@ func SliceOf(t Type) Type { return cachePut(ckey, &slice.rtype) } -// structTypeWithMethods is a structType created at runtime with StructOf. -// It is needed to pin the []method slice from its associated uncommonType struct. -// Keep in sync with the memory layout of structType. -type structTypeWithMethods struct { - structType - u uncommonType -} - // The structLookupCache caches StructOf lookups. // StructOf does not share the common lookupCache since we need to pin -// the *structType and its associated *uncommonType (especially the -// []method slice field of that uncommonType.) +// the memory associated with *structTypeFixedN. var structLookupCache struct { sync.RWMutex - m map[uint32][]*structTypeWithMethods // keyed by hash calculated in StructOf + m map[uint32][]interface { + common() *rtype + } // keyed by hash calculated in StructOf +} + +type structTypeUncommon struct { + structType + u uncommonType +} + +// A *rtype representing a struct is followed directly in memory by an +// array of method objects representing the methods attached to the +// struct. To get the same layout for a run time generated type, we +// need an array directly following the uncommonType memory. The types +// structTypeFixed4, ...structTypeFixedN are used to do this. +// +// A similar strategy is used for funcTypeFixed4, ...funcTypeFixedN. + +// TODO(crawshaw): as these structTypeFixedN and funcTypeFixedN structs +// have no methods, they could be defined at runtime using the StructOf +// function. + +type structTypeFixed4 struct { + structType + u uncommonType + m [4]method +} + +type structTypeFixed8 struct { + structType + u uncommonType + m [8]method +} + +type structTypeFixed16 struct { + structType + u uncommonType + m [16]method +} + +type structTypeFixed32 struct { + structType + u uncommonType + m [32]method } // StructOf returns the struct type containing fields. @@ -2192,7 +2277,7 @@ func StructOf(fields []StructField) Type { typalign uint8 comparable = true hashable = true - typ = new(structTypeWithMethods) + methods []method fs = make([]structField, len(fields)) repr = make([]byte, 0, 64) @@ -2269,7 +2354,6 @@ func StructOf(fields []StructField) Type { } return recv.Field(ifield).Method(imethod).Call(args) }) - } else { tfn = MakeFunc(m.typ, func(in []Value) []Value { var args []Value @@ -2287,47 +2371,59 @@ func StructOf(fields []StructField) Type { } return recv.Field(ifield).Method(imethod).Call(args) }) - } - typ.u.methods = append( - typ.u.methods, - method{ - name: m.name, - mtyp: m.typ, - ifn: unsafe.Pointer(&ifn), - tfn: unsafe.Pointer(&tfn), - }, - ) + methods = append(methods, method{ + name: m.name, + mtyp: resolveReflectType(m.typ), + ifn: resolveReflectText(unsafe.Pointer(&ifn)), + tfn: resolveReflectText(unsafe.Pointer(&tfn)), + }) } case Ptr: ptr := (*ptrType)(unsafe.Pointer(ft)) if unt := ptr.uncommon(); unt != nil { - for _, m := range unt.methods { + for _, m := range unt.methods() { if m.name.pkgPath() != nil { // TODO(sbinet) panic("reflect: embedded interface with unexported method(s) not implemented") } - typ.u.methods = append(typ.u.methods, m) + methods = append(methods, method{ + name: m.name, + mtyp: resolveReflectType(ptr.typeOff(m.mtyp)), + ifn: resolveReflectText(ptr.textOff(m.ifn)), + tfn: resolveReflectText(ptr.textOff(m.tfn)), + }) } } if unt := ptr.elem.uncommon(); unt != nil { - for _, m := range unt.methods { + for _, m := range unt.methods() { if m.name.pkgPath() != nil { // TODO(sbinet) panic("reflect: embedded interface with unexported method(s) not implemented") } - typ.u.methods = append(typ.u.methods, m) + methods = append(methods, method{ + name: m.name, + mtyp: resolveReflectType(ptr.elem.typeOff(m.mtyp)), + ifn: resolveReflectText(ptr.elem.textOff(m.ifn)), + tfn: resolveReflectText(ptr.elem.textOff(m.tfn)), + }) } } default: if unt := ft.uncommon(); unt != nil { - for _, m := range unt.methods { + for _, m := range unt.methods() { if m.name.pkgPath() != nil { // TODO(sbinet) panic("reflect: embedded interface with unexported method(s) not implemented") } - typ.u.methods = append(typ.u.methods, m) + methods = append(methods, method{ + name: m.name, + mtyp: resolveReflectType(ft.typeOff(m.mtyp)), + ifn: resolveReflectText(ft.textOff(m.ifn)), + tfn: resolveReflectText(ft.textOff(m.tfn)), + }) + } } } @@ -2359,6 +2455,49 @@ func StructOf(fields []StructField) Type { fs[i] = f } + + var typ *structType + var ut *uncommonType + var typPin interface { + common() *rtype + } // structTypeFixedN + + switch { + case len(methods) == 0: + t := new(structTypeUncommon) + typ = &t.structType + ut = &t.u + typPin = t + case len(methods) <= 4: + t := new(structTypeFixed4) + typ = &t.structType + ut = &t.u + copy(t.m[:], methods) + typPin = t + case len(methods) <= 8: + t := new(structTypeFixed8) + typ = &t.structType + ut = &t.u + copy(t.m[:], methods) + typPin = t + case len(methods) <= 16: + t := new(structTypeFixed16) + typ = &t.structType + ut = &t.u + copy(t.m[:], methods) + typPin = t + case len(methods) <= 32: + t := new(structTypeFixed32) + typ = &t.structType + ut = &t.u + copy(t.m[:], methods) + typPin = t + default: + panic("reflect.StructOf: too many methods") + } + ut.mcount = uint16(len(methods)) + ut.moff = uint16(unsafe.Sizeof(uncommonType{})) + if len(fs) > 0 { repr = append(repr, ' ') } @@ -2372,15 +2511,16 @@ func StructOf(fields []StructField) Type { // Make the struct type. var istruct interface{} = struct{}{} prototype := *(**structType)(unsafe.Pointer(&istruct)) - typ.structType = *prototype - typ.structType.fields = fs + *typ = *prototype + typ.fields = fs // Look in cache structLookupCache.RLock() - for _, t := range structLookupCache.m[hash] { - if haveIdenticalUnderlyingType(&typ.rtype, &t.rtype) { + for _, st := range structLookupCache.m[hash] { + t := st.common() + if haveIdenticalUnderlyingType(&typ.rtype, t) { structLookupCache.RUnlock() - return &t.rtype + return t } } structLookupCache.RUnlock() @@ -2389,11 +2529,14 @@ func StructOf(fields []StructField) Type { structLookupCache.Lock() defer structLookupCache.Unlock() if structLookupCache.m == nil { - structLookupCache.m = make(map[uint32][]*structTypeWithMethods) + structLookupCache.m = make(map[uint32][]interface { + common() *rtype + }) } - for _, t := range structLookupCache.m[hash] { - if haveIdenticalUnderlyingType(&typ.rtype, &t.rtype) { - return &t.rtype + for _, st := range structLookupCache.m[hash] { + t := st.common() + if haveIdenticalUnderlyingType(&typ.rtype, t) { + return t } } @@ -2403,9 +2546,8 @@ func StructOf(fields []StructField) Type { // even if 't' wasn't a structType with methods, we should be ok // as the 'u uncommonType' field won't be accessed except when // tflag&tflagUncommon is set. - tt := (*structTypeWithMethods)(unsafe.Pointer(t)) - structLookupCache.m[hash] = append(structLookupCache.m[hash], tt) - return &tt.rtype + structLookupCache.m[hash] = append(structLookupCache.m[hash], t) + return t } } @@ -2414,7 +2556,7 @@ func StructOf(fields []StructField) Type { typ.size = size typ.align = typalign typ.fieldAlign = typalign - if len(typ.u.methods) > 0 { + if len(methods) > 0 { typ.tflag |= tflagUncommon } if !hasPtr { @@ -2514,7 +2656,7 @@ func StructOf(fields []StructField) Type { typ.kind &^= kindDirectIface } - structLookupCache.m[hash] = append(structLookupCache.m[hash], typ) + structLookupCache.m[hash] = append(structLookupCache.m[hash], typPin) return &typ.rtype } @@ -2533,6 +2675,7 @@ func runtimeStructField(field StructField) structField { } } + _ = resolveReflectType(field.Type.common()) return structField{ name: newName(field.Name, string(field.Tag), field.PkgPath, exported), typ: field.Type.common(), diff --git a/src/reflect/value.go b/src/reflect/value.go index 262545d973..d72c14e9e1 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -566,15 +566,16 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn } else { rcvrtype = v.typ ut := v.typ.uncommon() - if ut == nil || uint(i) >= uint(len(ut.methods)) { + if ut == nil || uint(i) >= uint(ut.mcount) { panic("reflect: internal error: invalid method index") } - m := &ut.methods[i] + m := ut.methods()[i] if !m.name.isExported() { panic("reflect: " + op + " of unexported method") } - fn = unsafe.Pointer(&m.ifn) - t = m.mtyp + ifn := v.typ.textOff(m.ifn) + fn = unsafe.Pointer(&ifn) + t = v.typ.typeOff(m.mtyp) } return } @@ -1687,11 +1688,11 @@ func (v Value) Type() Type { } // Method on concrete type. ut := v.typ.uncommon() - if ut == nil || uint(i) >= uint(len(ut.methods)) { + if ut == nil || uint(i) >= uint(ut.mcount) { panic("reflect: internal error: invalid method index") } - m := &ut.methods[i] - return m.mtyp + m := ut.methods()[i] + return v.typ.typeOff(m.mtyp) } // Uint returns v's underlying value, as a uint64. diff --git a/src/runtime/iface.go b/src/runtime/iface.go index a4c962fb7a..700bdc2f48 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -93,7 +93,8 @@ func additab(m *itab, locked, canfail bool) { // so can iterate over both in lock step; // the loop is O(ni+nt) not O(ni*nt). ni := len(inter.mhdr) - nt := len(x.mhdr) + nt := int(x.mcount) + xmhdr := (*[1 << 16]method)(add(unsafe.Pointer(x), uintptr(x.moff)))[:nt:nt] j := 0 for k := 0; k < ni; k++ { i := &inter.mhdr[k] @@ -104,15 +105,16 @@ func additab(m *itab, locked, canfail bool) { ipkg = inter.pkgpath } for ; j < nt; j++ { - t := &x.mhdr[j] - if t.mtyp == itype && t.name.name() == iname { + t := &xmhdr[j] + if typ.typeOff(t.mtyp) == itype && t.name.name() == iname { pkgPath := t.name.pkgPath() if pkgPath == nil { pkgPath = x.pkgpath } if t.name.isExported() || pkgPath == ipkg { if m != nil { - *(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*sys.PtrSize)) = t.ifn + ifn := typ.textOff(t.ifn) + *(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*sys.PtrSize)) = ifn } goto nextimethod } diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 1a9dbd6c53..98a986cd63 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -435,9 +435,10 @@ func schedinit() { tracebackinit() moduledataverify() stackinit() - itabsinit() mallocinit() mcommoninit(_g_.m) + typelinksinit() + itabsinit() msigsave(_g_.m) initSigmask = _g_.m.sigmask diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index e1956569fd..02aeedaf75 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -486,3 +486,36 @@ func reflect_typelinks() ([]unsafe.Pointer, [][]int32) { } return sections, ret } + +// reflect_resolveTypeOff resolves an *rtype offset from a base type. +//go:linkname reflect_resolveTypeOff reflect.resolveTypeOff +func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer { + return unsafe.Pointer((*_type)(rtype).typeOff(typeOff(off))) +} + +// reflect_resolveTextOff resolves an function pointer offset from a base type. +//go:linkname reflect_resolveTextOff reflect.resolveTextOff +func reflect_resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer { + return (*_type)(rtype).textOff(textOff(off)) + +} + +// reflect_addReflectOff adds a pointer to the reflection offset lookup map. +//go:linkname reflect_addReflectOff reflect.addReflectOff +func reflect_addReflectOff(ptr unsafe.Pointer) int32 { + lock(&reflectOffs.lock) + if reflectOffs.m == nil { + reflectOffs.m = make(map[int32]unsafe.Pointer) + reflectOffs.minv = make(map[unsafe.Pointer]int32) + reflectOffs.next = -1 + } + id, found := reflectOffs.minv[ptr] + if !found { + id = reflectOffs.next + reflectOffs.next-- // use negative offsets as IDs to aid debugging + reflectOffs.m[id] = ptr + reflectOffs.minv[ptr] = id + } + unlock(&reflectOffs.lock) + return id +} diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 8c70f22c1f..2df390253a 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -137,6 +137,8 @@ type moduledata struct { gcdatamask, gcbssmask bitvector + typemap map[typeOff]*_type // offset to *_rtype in previous module + next *moduledata } diff --git a/src/runtime/type.go b/src/runtime/type.go index fbf6f9973c..86131d3ff3 100644 --- a/src/runtime/type.go +++ b/src/runtime/type.go @@ -131,6 +131,92 @@ func (t *_type) name() string { return t._string[i+1:] } +// reflectOffs holds type offsets defined at run time by the reflect package. +// +// When a type is defined at run time, its *rtype data lives on the heap. +// There are a wide range of possible addresses the heap may use, that +// may not be representable as a 32-bit offset. Moreover the GC may +// one day start moving heap memory, in which case there is no stable +// offset that can be defined. +// +// To provide stable offsets, we add pin *rtype objects in a global map +// and treat the offset as an identifier. We use negative offsets that +// do not overlap with any compile-time module offsets. +// +// Entries are created by reflect.addReflectOff. +var reflectOffs struct { + lock mutex + next int32 + m map[int32]unsafe.Pointer + minv map[unsafe.Pointer]int32 +} + +func (t *_type) typeOff(off typeOff) *_type { + if off == 0 { + return nil + } + base := uintptr(unsafe.Pointer(t)) + var md *moduledata + for next := &firstmoduledata; next != nil; next = next.next { + if base >= next.types && base < next.etypes { + md = next + break + } + } + if md == nil { + lock(&reflectOffs.lock) + res := reflectOffs.m[int32(off)] + unlock(&reflectOffs.lock) + if res == nil { + println("runtime: typeOff", hex(off), "base", hex(base), "not in ranges:") + for next := &firstmoduledata; next != nil; next = next.next { + println("\ttypes", hex(next.types), "etypes", hex(next.etypes)) + } + throw("runtime: type offset base pointer out of range") + } + return (*_type)(res) + } + if t := md.typemap[off]; t != nil { + return t + } + res := md.types + uintptr(off) + if res > md.etypes { + println("runtime: typeOff", hex(off), "out of range", hex(md.types), "-", hex(md.etypes)) + throw("runtime: type offset out of range") + } + return (*_type)(unsafe.Pointer(res)) +} + +func (t *_type) textOff(off textOff) unsafe.Pointer { + base := uintptr(unsafe.Pointer(t)) + var md *moduledata + for next := &firstmoduledata; next != nil; next = next.next { + if base >= next.types && base < next.etypes { + md = next + break + } + } + if md == nil { + lock(&reflectOffs.lock) + res := reflectOffs.m[int32(off)] + unlock(&reflectOffs.lock) + if res == nil { + println("runtime: textOff", hex(off), "base", hex(base), "not in ranges:") + for next := &firstmoduledata; next != nil; next = next.next { + println("\ttypes", hex(next.types), "etypes", hex(next.etypes)) + } + throw("runtime: text offset base pointer out of range") + } + return res + } + res := md.text + uintptr(off) + if res > md.etext { + println("runtime: textOff", hex(off), "out of range", hex(md.text), "-", hex(md.etext)) + throw("runtime: text offset out of range") + } + return unsafe.Pointer(res) +} + func (t *functype) in() []*_type { // See funcType in reflect/type.go for details on data layout. uadd := uintptr(unsafe.Sizeof(functype{})) @@ -154,16 +240,20 @@ func (t *functype) dotdotdot() bool { return t.outCount&(1<<15) != 0 } +type typeOff int32 +type textOff int32 + type method struct { name name - mtyp *_type - ifn unsafe.Pointer - tfn unsafe.Pointer + mtyp typeOff + ifn textOff + tfn textOff } type uncommontype struct { pkgpath *string - mhdr []method + mcount uint16 // number of methods + moff uint16 // offset from this uncommontype to [mcount]method } type imethod struct { @@ -270,6 +360,18 @@ func (n *name) name() (s string) { return s } +func (n *name) tag() (s string) { + tl := n.tagLen() + if tl == 0 { + return "" + } + nl := n.nameLen() + hdr := (*stringStruct)(unsafe.Pointer(&s)) + hdr.str = unsafe.Pointer(n.data(3 + nl + 2)) + hdr.len = tl + return s +} + func (n *name) pkgPath() *string { if *n.data(0)&(1<<2) == 0 { return nil @@ -281,3 +383,200 @@ func (n *name) pkgPath() *string { off = int(round(uintptr(off), sys.PtrSize)) return *(**string)(unsafe.Pointer(n.data(off))) } + +// typelinksinit scans the types from extra modules and builds the +// moduledata typemap used to de-duplicate type pointers. +func typelinksinit() { + if firstmoduledata.next == nil { + return + } + typehash := make(map[uint32][]*_type) + + modules := []*moduledata{} + for md := &firstmoduledata; md != nil; md = md.next { + modules = append(modules, md) + } + prev, modules := modules[len(modules)-1], modules[:len(modules)-1] + for len(modules) > 0 { + // Collect types from the previous module into typehash. + collect: + for _, tl := range prev.typelinks { + var t *_type + if prev.typemap == nil { + t = (*_type)(unsafe.Pointer(prev.types + uintptr(tl))) + } else { + t = prev.typemap[typeOff(tl)] + } + // Add to typehash if not seen before. + tlist := typehash[t.hash] + for _, tcur := range tlist { + if tcur == t { + continue collect + } + } + typehash[t.hash] = append(tlist, t) + } + + // If any of this module's typelinks match a type from a + // prior module, prefer that prior type by adding the offset + // to this module's typemap. + md := modules[len(modules)-1] + md.typemap = make(map[typeOff]*_type, len(md.typelinks)) + for _, tl := range md.typelinks { + t := (*_type)(unsafe.Pointer(md.types + uintptr(tl))) + for _, candidate := range typehash[t.hash] { + if typesEqual(t, candidate) { + t = candidate + break + } + } + md.typemap[typeOff(tl)] = t + } + + prev, modules = md, modules[:len(modules)-1] + } +} + +// typesEqual reports whether two types are equal. +// +// Everywhere in the runtime and reflect packages, it is assumed that +// there is exactly one *_type per Go type, so that pointer equality +// can be used to test if types are equal. There is one place that +// breaks this assumption: buildmode=shared. In this case a type can +// appear as two different pieces of memory. This is hidden from the +// runtime and reflect package by the per-module typemap built in +// typelinksinit. It uses typesEqual to map types from later modules +// back into earlier ones. +// +// Only typelinksinit needs this function. +func typesEqual(t, v *_type) bool { + if t == v { + return true + } + kind := t.kind & kindMask + if kind != v.kind&kindMask { + return false + } + if t._string != v._string { + return false + } + ut := t.uncommon() + uv := v.uncommon() + if ut != nil || uv != nil { + if ut == nil || uv == nil { + return false + } + if !pkgPathEqual(ut.pkgpath, uv.pkgpath) { + return false + } + } + if kindBool <= kind && kind <= kindComplex128 { + return true + } + switch kind { + case kindString, kindUnsafePointer: + return true + case kindArray: + at := (*arraytype)(unsafe.Pointer(t)) + av := (*arraytype)(unsafe.Pointer(v)) + return typesEqual(at.elem, av.elem) && at.len == av.len + case kindChan: + ct := (*chantype)(unsafe.Pointer(t)) + cv := (*chantype)(unsafe.Pointer(v)) + return ct.dir == cv.dir && typesEqual(ct.elem, cv.elem) + case kindFunc: + ft := (*functype)(unsafe.Pointer(t)) + fv := (*functype)(unsafe.Pointer(v)) + if ft.outCount != fv.outCount || ft.inCount != fv.inCount { + return false + } + tin, vin := ft.in(), fv.in() + for i := 0; i < len(tin); i++ { + if !typesEqual(tin[i], vin[i]) { + return false + } + } + tout, vout := ft.out(), fv.out() + for i := 0; i < len(tout); i++ { + if !typesEqual(tout[i], vout[i]) { + return false + } + } + return true + case kindInterface: + it := (*interfacetype)(unsafe.Pointer(t)) + iv := (*interfacetype)(unsafe.Pointer(v)) + if !pkgPathEqual(it.pkgpath, iv.pkgpath) { + return false + } + if len(it.mhdr) != len(iv.mhdr) { + return false + } + for i := range it.mhdr { + tm := &it.mhdr[i] + vm := &iv.mhdr[i] + if tm.name.name() != vm.name.name() { + return false + } + if !pkgPathEqual(tm.name.pkgPath(), vm.name.pkgPath()) { + return false + } + if !typesEqual(tm._type, vm._type) { + return false + } + } + return true + case kindMap: + mt := (*maptype)(unsafe.Pointer(t)) + mv := (*maptype)(unsafe.Pointer(v)) + return typesEqual(mt.key, mv.key) && typesEqual(mt.elem, mv.elem) + case kindPtr: + pt := (*ptrtype)(unsafe.Pointer(t)) + pv := (*ptrtype)(unsafe.Pointer(v)) + return typesEqual(pt.elem, pv.elem) + case kindSlice: + st := (*slicetype)(unsafe.Pointer(t)) + sv := (*slicetype)(unsafe.Pointer(v)) + return typesEqual(st.elem, sv.elem) + case kindStruct: + st := (*structtype)(unsafe.Pointer(t)) + sv := (*structtype)(unsafe.Pointer(v)) + if len(st.fields) != len(sv.fields) { + return false + } + for i := range st.fields { + tf := &st.fields[i] + vf := &sv.fields[i] + if tf.name.name() != vf.name.name() { + return false + } + if !pkgPathEqual(tf.name.pkgPath(), vf.name.pkgPath()) { + return false + } + if !typesEqual(tf.typ, vf.typ) { + return false + } + if tf.name.tag() != vf.name.tag() { + return false + } + if tf.offset != vf.offset { + return false + } + } + return true + default: + println("runtime: impossible type kind", kind) + throw("runtime: impossible type kind") + return false + } +} + +func pkgPathEqual(p, q *string) bool { + if p == q { + return true + } + if p == nil || q == nil { + return false + } + return *p == *q +} -- cgit v1.3 From f120936dfffa3ac935730699587e6957f2d5ea61 Mon Sep 17 00:00:00 2001 From: David Crawshaw Date: Thu, 31 Mar 2016 10:02:10 -0400 Subject: cmd/compile, etc: use name for type pkgPath By replacing the *string used to represent pkgPath with a reflect.name everywhere, the embedded *string for package paths inside the reflect.name can be replaced by an offset, nameOff. This reduces the number of pointers in the type information. This also moves all reflect.name types into the same section, making it possible to use nameOff more widely in later CLs. No significant binary size change for normal binaries, but: linux/amd64 PIE: cmd/go: -440KB (3.7%) jujud: -2.6MB (3.2%) For #6853. Change-Id: I3890b132a784a1090b1b72b32febfe0bea77eaee Reviewed-on: https://go-review.googlesource.com/21395 Run-TryBot: David Crawshaw TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/cmd/compile/internal/gc/go.go | 2 +- src/cmd/compile/internal/gc/reflect.go | 117 +++++++++++++++++++-------------- src/cmd/internal/obj/data.go | 13 +++- src/reflect/type.go | 64 +++++++++--------- src/runtime/heapdump.go | 5 +- src/runtime/iface.go | 8 +-- src/runtime/type.go | 72 ++++++++++++-------- 7 files changed, 168 insertions(+), 113 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index 5df49b56d6..8411d2d0ac 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -20,7 +20,7 @@ const ( type Pkg struct { Name string // package name, e.g. "sys" Path string // string literal used in import statement, e.g. "runtime/internal/sys" - Pathsym *Sym + Pathsym *obj.LSym Prefix string // escaped path for use in symbol table Imported bool // export data of this package was parsed Exported bool // import line written in export data diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 2bd50b4665..70a75f9324 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -412,8 +412,6 @@ func imethods(t *Type) []*Sig { return methods } -var dimportpath_gopkg *Pkg - func dimportpath(p *Pkg) { if p.Pathsym != nil { return @@ -426,27 +424,18 @@ func dimportpath(p *Pkg) { return } - if dimportpath_gopkg == nil { - dimportpath_gopkg = mkpkg("go") - dimportpath_gopkg.Name = "go" - } - - nam := "importpath." + p.Prefix + "." - - n := Nod(ONAME, nil, nil) - n.Sym = Pkglookup(nam, dimportpath_gopkg) - - n.Class = PEXTERN - n.Xoffset = 0 - p.Pathsym = n.Sym - + var str string if p == localpkg { // Note: myimportpath != "", or else dgopkgpath won't call dimportpath. - gdatastring(n, myimportpath) + str = myimportpath } else { - gdatastring(n, p.Path) + str = p.Path } - ggloblsym(n.Sym, int32(Types[TSTRING].Width), obj.DUPOK|obj.RODATA) + + s := obj.Linklookup(Ctxt, "go.importpath."+p.Prefix+".", 0) + ot := dnameData(s, 0, str, "", nil, false) + ggloblLSym(s, int32(ot), obj.DUPOK|obj.RODATA) + p.Pathsym = s } func dgopkgpath(s *Sym, ot int, pkg *Pkg) int { @@ -469,7 +458,23 @@ func dgopkgpathLSym(s *obj.LSym, ot int, pkg *Pkg) int { } dimportpath(pkg) - return dsymptrLSym(s, ot, Linksym(pkg.Pathsym), 0) + return dsymptrLSym(s, ot, pkg.Pathsym, 0) +} + +// dgopkgpathOffLSym writes an offset relocation in s at offset ot to the pkg path symbol. +func dgopkgpathOffLSym(s *obj.LSym, ot int, pkg *Pkg) int { + if pkg == localpkg && myimportpath == "" { + // If we don't know the full import path of the package being compiled + // (i.e. -p was not passed on the compiler command line), emit a reference to + // go.importpath.""., which the linker will rewrite using the correct import path. + // Every package that imports this one directly defines the symbol. + // See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ. + ns := obj.Linklookup(Ctxt, `go.importpath."".`, 0) + return dsymptrOffLSym(s, ot, ns, 0) + } + + dimportpath(pkg) + return dsymptrOffLSym(s, ot, pkg.Pathsym, 0) } // isExportedField reports whether a struct field is exported. @@ -495,13 +500,12 @@ func dnameField(s *Sym, ot int, ft *Field) int { if ft.Note != nil { tag = *ft.Note } - return dname(s, ot, name, tag, nil, isExportedField(ft)) + nsym := dname(name, tag, nil, isExportedField(ft)) + return dsymptrLSym(Linksym(s), ot, nsym, 0) } -var dnameCount int - -// dname dumps a reflect.name for a struct field or method. -func dname(s *Sym, ot int, name, tag string, pkg *Pkg, exported bool) int { +// dnameData writes the contents of a reflect.name into s at offset ot. +func dnameData(s *obj.LSym, ot int, name, tag string, pkg *Pkg, exported bool) int { if len(name) > 1<<16-1 { Fatalf("name too long: %s", name) } @@ -534,31 +538,46 @@ func dname(s *Sym, ot int, name, tag string, pkg *Pkg, exported bool) int { copy(tb[2:], tag) } - // Very few names require a pkgPath *string (only those - // defined in a different package than their type). So if - // there is no pkgPath, we treat the name contents as string - // data that duplicates across packages. - var bsym *obj.LSym + ot = int(s.WriteBytes(Ctxt, int64(ot), b)) + + if pkg != nil { + ot = dgopkgpathOffLSym(s, ot, pkg) + } + + return ot +} + +var dnameCount int + +// dname creates a reflect.name for a struct field or method. +func dname(name, tag string, pkg *Pkg, exported bool) *obj.LSym { + // Write out data as "type.." to signal two things to the + // linker, first that when dynamically linking, the symbol + // should be moved to a relro section, and second that the + // contents should not be decoded as a type. + sname := "type..namedata." if pkg == nil { - _, bsym = stringsym(string(b)) + // In the common case, share data with other packages. + if name == "" { + if exported { + sname += "-noname-exported." + tag + } else { + sname += "-noname-unexported." + tag + } + } else { + sname += name + "." + tag + } } else { - // Write out data as "type.." to signal two things to the - // linker, first that when dynamically linking, the symbol - // should be moved to a relro section, and second that the - // contents should not be decoded as a type. - bsymname := fmt.Sprintf(`type..methodname."".%d`, dnameCount) + sname = fmt.Sprintf(`%s"".%d`, sname, dnameCount) dnameCount++ - bsym = obj.Linklookup(Ctxt, bsymname, 0) - bsym.P = b - boff := len(b) - boff = int(Rnd(int64(boff), int64(Widthptr))) - boff = dgopkgpathLSym(bsym, boff, pkg) - ggloblLSym(bsym, int32(boff), obj.RODATA|obj.LOCAL) } - - ot = dsymptrLSym(Linksym(s), ot, bsym, 0) - - return ot + s := obj.Linklookup(Ctxt, sname, 0) + if len(s.P) > 0 { + return s + } + ot := dnameData(s, 0, name, tag, pkg, exported) + ggloblLSym(s, int32(ot), obj.DUPOK|obj.RODATA) + return s } // dextratype dumps the fields of a runtime.uncommontype. @@ -627,7 +646,8 @@ func dextratypeData(s *Sym, ot int, t *Type) int { if !exported && a.pkg != typePkg(t) { pkg = a.pkg } - ot = dname(s, ot, a.name, "", pkg, exported) + nsym := dname(a.name, "", pkg, exported) + ot = dsymptrLSym(lsym, ot, nsym, 0) ot = dmethodptrOffLSym(lsym, ot, Linksym(dtypesym(a.mtype))) ot = dmethodptrOffLSym(lsym, ot, Linksym(a.isym)) ot = dmethodptrOffLSym(lsym, ot, Linksym(a.tsym)) @@ -1213,7 +1233,8 @@ ok: if !exported && a.pkg != tpkg { pkg = a.pkg } - ot = dname(s, ot, a.name, "", pkg, exported) + nsym := dname(a.name, "", pkg, exported) + ot = dsymptrLSym(Linksym(s), ot, nsym, 0) ot = dsymptr(s, ot, dtypesym(a.type_), 0) } diff --git a/src/cmd/internal/obj/data.go b/src/cmd/internal/obj/data.go index 546ff37269..d7f0840bc1 100644 --- a/src/cmd/internal/obj/data.go +++ b/src/cmd/internal/obj/data.go @@ -75,7 +75,11 @@ func (s *LSym) prepwrite(ctxt *Link, off int64, siz int) { if s.Type == SBSS || s.Type == STLSBSS { ctxt.Diag("cannot supply data for BSS var") } - s.Grow(off + int64(siz)) + l := off + int64(siz) + s.Grow(l) + if l > s.Size { + s.Size = l + } } // WriteFloat32 writes f into s at offset off. @@ -150,6 +154,13 @@ func (s *LSym) WriteString(ctxt *Link, off int64, siz int, str string) { copy(s.P[off:off+int64(siz)], str) } +// WriteBytes writes a slice of bytes into s at offset off. +func (s *LSym) WriteBytes(ctxt *Link, off int64, b []byte) int64 { + s.prepwrite(ctxt, off, len(b)) + copy(s.P[off:], b) + return off + int64(len(b)) +} + func Addrel(s *LSym) *Reloc { s.R = append(s.R, Reloc{}) return &s.R[len(s.R)-1] diff --git a/src/reflect/type.go b/src/reflect/type.go index c7ed402be2..3c7affcd7f 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -299,9 +299,9 @@ type method struct { // Using a pointer to this struct reduces the overall size required // to describe an unnamed type with no methods. type uncommonType struct { - pkgPath *string // import path; nil for built-in types like int, string - mcount uint16 // number of methods - moff uint16 // offset from this uncommontype to [mcount]method + pkgPath name // import path; empty for built-in types like int, string + mcount uint16 // number of methods + moff uint16 // offset from this uncommontype to [mcount]method } // ChanDir represents a channel type's direction. @@ -354,7 +354,7 @@ type imethod struct { // interfaceType represents an interface type. type interfaceType struct { rtype `reflect:"interface"` - pkgPath *string // import path + pkgPath name // import path methods []imethod // sorted by hash } @@ -396,7 +396,7 @@ type structField struct { // structType represents a struct type. type structType struct { rtype `reflect:"struct"` - pkgPath *string + pkgPath name fields []structField // sorted by offset } @@ -406,7 +406,7 @@ type structType struct { // // 1<<0 the name is exported // 1<<1 tag data follows the name -// 1<<2 pkgPath *string follow the name and tag +// 1<<2 pkgPath nameOff follows the name and tag // // The next two bytes are the data length: // @@ -417,10 +417,9 @@ type structType struct { // If tag data follows then bytes 3+l and 3+l+1 are the tag length, // with the data following. // -// If the import path follows, then ptrSize bytes at the end of -// the data form a *string. The pointer is aligned to its width. -// The import path is only set for concrete methods that are defined -// in a different package than their type. +// If the import path follows, then 4 bytes at the end of +// the data form a nameOff. The import path is only set for concrete +// methods that are defined in a different package than their type. type name struct { bytes *byte } @@ -446,6 +445,9 @@ func (n *name) tagLen() int { } func (n *name) name() (s string) { + if n.bytes == nil { + return "" + } nl := n.nameLen() if nl == 0 { return "" @@ -468,16 +470,18 @@ func (n *name) tag() (s string) { return s } -func (n *name) pkgPath() *string { - if *n.data(0)&(1<<2) == 0 { - return nil +func (n *name) pkgPath() string { + if n.bytes == nil || *n.data(0)&(1<<2) == 0 { + return "" } off := 3 + n.nameLen() if tl := n.tagLen(); tl > 0 { off += 2 + tl } - off = int(round(uintptr(off), ptrSize)) - return *(**string)(unsafe.Pointer(n.data(off))) + var nameOff int32 + copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off)))[:]) + pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n), nameOff))} + return pkgPathName.name() } // round n up to a multiple of a. a must be a power of 2. @@ -595,10 +599,10 @@ func (t *uncommonType) methods() []method { } func (t *uncommonType) PkgPath() string { - if t == nil || t.pkgPath == nil { + if t == nil { return "" } - return *t.pkgPath + return t.pkgPath.name() } // resolveTypeOff resolves an *rtype offset from a base type. @@ -752,11 +756,10 @@ func (t *rtype) Method(i int) (m Method) { m.Name = p.name.name() fl := flag(Func) if !p.name.isExported() { - pkgPath := p.name.pkgPath() - if pkgPath == nil { - pkgPath = ut.pkgPath + m.PkgPath = p.name.pkgPath() + if m.PkgPath == "" { + m.PkgPath = ut.pkgPath.name() } - m.PkgPath = *pkgPath fl |= flagStickyRO } if p.mtyp != 0 { @@ -1004,11 +1007,10 @@ func (t *interfaceType) Method(i int) (m Method) { p := &t.methods[i] m.Name = p.name.name() if !p.name.isExported() { - pkgPath := p.name.pkgPath() - if pkgPath == nil { - pkgPath = t.pkgPath + m.PkgPath = p.name.pkgPath() + if m.PkgPath == "" { + m.PkgPath = t.pkgPath.name() } - m.PkgPath = *pkgPath } m.Type = toType(p.typ) m.Index = i @@ -1146,9 +1148,9 @@ func (t *structType) Field(i int) (f StructField) { f.Name = t.Name() f.Anonymous = true } - if t.pkgPath != nil && !p.name.isExported() { + if !p.name.isExported() { // Fields never have an import path in their name. - f.PkgPath = *t.pkgPath + f.PkgPath = t.pkgPath.name() } if tag := p.name.tag(); tag != "" { f.Tag = StructTag(tag) @@ -2325,7 +2327,7 @@ func StructOf(fields []StructField) Type { case Interface: ift := (*interfaceType)(unsafe.Pointer(ft)) for im, m := range ift.methods { - if m.name.pkgPath() != nil { + if m.name.pkgPath() != "" { // TODO(sbinet) panic("reflect: embedded interface with unexported method(s) not implemented") } @@ -2384,7 +2386,7 @@ func StructOf(fields []StructField) Type { ptr := (*ptrType)(unsafe.Pointer(ft)) if unt := ptr.uncommon(); unt != nil { for _, m := range unt.methods() { - if m.name.pkgPath() != nil { + if m.name.pkgPath() != "" { // TODO(sbinet) panic("reflect: embedded interface with unexported method(s) not implemented") } @@ -2398,7 +2400,7 @@ func StructOf(fields []StructField) Type { } if unt := ptr.elem.uncommon(); unt != nil { for _, m := range unt.methods() { - if m.name.pkgPath() != nil { + if m.name.pkgPath() != "" { // TODO(sbinet) panic("reflect: embedded interface with unexported method(s) not implemented") } @@ -2413,7 +2415,7 @@ func StructOf(fields []StructField) Type { default: if unt := ft.uncommon(); unt != nil { for _, m := range unt.methods() { - if m.name.pkgPath() != nil { + if m.name.pkgPath() != "" { // TODO(sbinet) panic("reflect: embedded interface with unexported method(s) not implemented") } diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go index 2410b1954a..adfd660847 100644 --- a/src/runtime/heapdump.go +++ b/src/runtime/heapdump.go @@ -183,10 +183,11 @@ func dumptype(t *_type) { dumpint(tagType) dumpint(uint64(uintptr(unsafe.Pointer(t)))) dumpint(uint64(t.size)) - if x := t.uncommon(); x == nil || x.pkgpath == nil { + if x := t.uncommon(); x == nil || x.pkgpath.name() == "" { dumpstr(t._string) } else { - pkgpath := stringStructOf(x.pkgpath) + pkgpathstr := x.pkgpath.name() + pkgpath := stringStructOf(&pkgpathstr) namestr := t.name() name := stringStructOf(&namestr) dumpint(uint64(uintptr(pkgpath.len) + 1 + uintptr(name.len))) diff --git a/src/runtime/iface.go b/src/runtime/iface.go index 700bdc2f48..84f0ee8f0c 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -101,15 +101,15 @@ func additab(m *itab, locked, canfail bool) { iname := i.name.name() itype := i._type ipkg := i.name.pkgPath() - if ipkg == nil { - ipkg = inter.pkgpath + if ipkg == "" { + ipkg = inter.pkgpath.name() } for ; j < nt; j++ { t := &xmhdr[j] if typ.typeOff(t.mtyp) == itype && t.name.name() == iname { pkgPath := t.name.pkgPath() - if pkgPath == nil { - pkgPath = x.pkgpath + if pkgPath == "" { + pkgPath = x.pkgpath.name() } if t.name.isExported() || pkgPath == ipkg { if m != nil { diff --git a/src/runtime/type.go b/src/runtime/type.go index 86131d3ff3..711753bab5 100644 --- a/src/runtime/type.go +++ b/src/runtime/type.go @@ -6,10 +6,7 @@ package runtime -import ( - "runtime/internal/sys" - "unsafe" -) +import "unsafe" // tflag is documented in ../reflect/type.go. type tflag uint8 @@ -151,6 +148,33 @@ var reflectOffs struct { minv map[unsafe.Pointer]int32 } +func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name { + if off == 0 { + return name{} + } + base := uintptr(ptrInModule) + var md *moduledata + for next := &firstmoduledata; next != nil; next = next.next { + if base >= next.types && base < next.etypes { + md = next + break + } + } + if md == nil { + println("runtime: nameOff", hex(off), "base", hex(base), "not in ranges:") + for next := &firstmoduledata; next != nil; next = next.next { + println("\ttypes", hex(next.types), "etypes", hex(next.etypes)) + } + throw("runtime: name offset base pointer out of range") + } + res := md.types + uintptr(off) + if res > md.etypes { + println("runtime: nameOff", hex(off), "out of range", hex(md.types), "-", hex(md.etypes)) + throw("runtime: name offset out of range") + } + return name{(*byte)(unsafe.Pointer(res))} +} + func (t *_type) typeOff(off typeOff) *_type { if off == 0 { return nil @@ -240,6 +264,7 @@ func (t *functype) dotdotdot() bool { return t.outCount&(1<<15) != 0 } +type nameOff int32 type typeOff int32 type textOff int32 @@ -251,7 +276,7 @@ type method struct { } type uncommontype struct { - pkgpath *string + pkgpath name mcount uint16 // number of methods moff uint16 // offset from this uncommontype to [mcount]method } @@ -263,7 +288,7 @@ type imethod struct { type interfacetype struct { typ _type - pkgpath *string + pkgpath name mhdr []imethod } @@ -319,7 +344,7 @@ type structfield struct { type structtype struct { typ _type - pkgPath *string + pkgPath name fields []structfield } @@ -350,6 +375,9 @@ func (n *name) tagLen() int { } func (n *name) name() (s string) { + if n.bytes == nil { + return "" + } nl := n.nameLen() if nl == 0 { return "" @@ -372,16 +400,18 @@ func (n *name) tag() (s string) { return s } -func (n *name) pkgPath() *string { - if *n.data(0)&(1<<2) == 0 { - return nil +func (n *name) pkgPath() string { + if n.bytes == nil || *n.data(0)&(1<<2) == 0 { + return "" } off := 3 + n.nameLen() if tl := n.tagLen(); tl > 0 { off += 2 + tl } - off = int(round(uintptr(off), sys.PtrSize)) - return *(**string)(unsafe.Pointer(n.data(off))) + var nameOff nameOff + copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off)))[:]) + pkgPathName := resolveNameOff(unsafe.Pointer(n.bytes), nameOff) + return pkgPathName.name() } // typelinksinit scans the types from extra modules and builds the @@ -466,7 +496,7 @@ func typesEqual(t, v *_type) bool { if ut == nil || uv == nil { return false } - if !pkgPathEqual(ut.pkgpath, uv.pkgpath) { + if ut.pkgpath.name() != uv.pkgpath.name() { return false } } @@ -506,7 +536,7 @@ func typesEqual(t, v *_type) bool { case kindInterface: it := (*interfacetype)(unsafe.Pointer(t)) iv := (*interfacetype)(unsafe.Pointer(v)) - if !pkgPathEqual(it.pkgpath, iv.pkgpath) { + if it.pkgpath.name() != iv.pkgpath.name() { return false } if len(it.mhdr) != len(iv.mhdr) { @@ -518,7 +548,7 @@ func typesEqual(t, v *_type) bool { if tm.name.name() != vm.name.name() { return false } - if !pkgPathEqual(tm.name.pkgPath(), vm.name.pkgPath()) { + if tm.name.pkgPath() != vm.name.pkgPath() { return false } if !typesEqual(tm._type, vm._type) { @@ -550,7 +580,7 @@ func typesEqual(t, v *_type) bool { if tf.name.name() != vf.name.name() { return false } - if !pkgPathEqual(tf.name.pkgPath(), vf.name.pkgPath()) { + if tf.name.pkgPath() != vf.name.pkgPath() { return false } if !typesEqual(tf.typ, vf.typ) { @@ -570,13 +600,3 @@ func typesEqual(t, v *_type) bool { return false } } - -func pkgPathEqual(p, q *string) bool { - if p == q { - return true - } - if p == nil || q == nil { - return false - } - return *p == *q -} -- cgit v1.3 From babfb4ec3ba3e4e36b1003d6efbaeddf2e975240 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 13 Apr 2016 18:41:59 -0700 Subject: cmd/internal/obj: change Link.Flag_shared to bool Change-Id: I9bda2ce6f45fb8292503f86d8f9f161601f222b7 Reviewed-on: https://go-review.googlesource.com/22053 Reviewed-by: Michael Hudson-Doyle --- src/cmd/asm/main.go | 4 +--- src/cmd/compile/internal/gc/cgen.go | 2 +- src/cmd/compile/internal/gc/main.go | 8 +------- src/cmd/compile/internal/ppc64/galign.go | 2 +- src/cmd/compile/internal/ppc64/gsubr.go | 4 ++-- src/cmd/compile/internal/ppc64/reg.go | 2 +- src/cmd/compile/internal/x86/reg.go | 2 +- src/cmd/internal/obj/arm/asm5.go | 8 ++++---- src/cmd/internal/obj/arm64/asm7.go | 2 +- src/cmd/internal/obj/link.go | 2 +- src/cmd/internal/obj/ppc64/asm9.go | 10 +++++----- src/cmd/internal/obj/ppc64/obj9.go | 4 ++-- src/cmd/internal/obj/s390x/asmz.go | 2 +- src/cmd/internal/obj/x86/asm6.go | 22 +++++++++++----------- src/cmd/internal/obj/x86/obj6.go | 4 ++-- 15 files changed, 35 insertions(+), 43 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go index f010ca93f1..40e1d9c4a9 100644 --- a/src/cmd/asm/main.go +++ b/src/cmd/asm/main.go @@ -39,9 +39,7 @@ func main() { } ctxt.LineHist.TrimPathPrefix = *flags.TrimPath ctxt.Flag_dynlink = *flags.Dynlink - if *flags.Shared || *flags.Dynlink { - ctxt.Flag_shared = 1 - } + ctxt.Flag_shared = *flags.Shared || *flags.Dynlink ctxt.Bso = bufio.NewWriter(os.Stdout) defer ctxt.Bso.Flush() diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go index 9de2a19f68..32ca1ae940 100644 --- a/src/cmd/compile/internal/gc/cgen.go +++ b/src/cmd/compile/internal/gc/cgen.go @@ -2363,7 +2363,7 @@ func Ginscall(f *Node, proc int) { // If the MOVD is not needed, insert a hardware NOP // so that the same number of instructions are used // on ppc64 in both shared and non-shared modes. - if Ctxt.Flag_shared != 0 { + if Ctxt.Flag_shared { p := Thearch.Gins(ppc64.AMOVD, nil, nil) p.From.Type = obj.TYPE_MEM p.From.Offset = 24 diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index f41097b83b..2baf9f6585 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -207,13 +207,7 @@ func Main() { flag.BoolVar(&ssaEnabled, "ssa", true, "use SSA backend to generate code") obj.Flagparse(usage) - if flag_dynlink { - flag_shared = true - } - if flag_shared { - // TODO(mdempsky): Change Flag_shared to bool. - Ctxt.Flag_shared = 1 - } + Ctxt.Flag_shared = flag_dynlink || flag_shared Ctxt.Flag_dynlink = flag_dynlink Ctxt.Flag_optimize = Debug['N'] == 0 diff --git a/src/cmd/compile/internal/ppc64/galign.go b/src/cmd/compile/internal/ppc64/galign.go index 04fa4cfc78..a83dff9a8b 100644 --- a/src/cmd/compile/internal/ppc64/galign.go +++ b/src/cmd/compile/internal/ppc64/galign.go @@ -11,7 +11,7 @@ import ( ) func betypeinit() { - if gc.Ctxt.Flag_shared != 0 { + if gc.Ctxt.Flag_shared { gc.Thearch.ReservedRegs = append(gc.Thearch.ReservedRegs, ppc64.REG_R2) gc.Thearch.ReservedRegs = append(gc.Thearch.ReservedRegs, ppc64.REG_R12) } diff --git a/src/cmd/compile/internal/ppc64/gsubr.go b/src/cmd/compile/internal/ppc64/gsubr.go index de6e2fbe05..eb6cd2c5e9 100644 --- a/src/cmd/compile/internal/ppc64/gsubr.go +++ b/src/cmd/compile/internal/ppc64/gsubr.go @@ -580,7 +580,7 @@ func rawgins(as obj.As, f *gc.Node, t *gc.Node) *obj.Prog { case obj.ACALL: if p.To.Type == obj.TYPE_REG && p.To.Reg != ppc64.REG_CTR { // Allow front end to emit CALL REG, and rewrite into MOV REG, CTR; CALL CTR. - if gc.Ctxt.Flag_shared != 0 { + if gc.Ctxt.Flag_shared { // Make sure function pointer is in R12 as well when // compiling Go into PIC. // TODO(mwhudson): it would obviously be better to @@ -602,7 +602,7 @@ func rawgins(as obj.As, f *gc.Node, t *gc.Node) *obj.Prog { p.To.Type = obj.TYPE_REG p.To.Reg = ppc64.REG_CTR - if gc.Ctxt.Flag_shared != 0 { + if gc.Ctxt.Flag_shared { // When compiling Go into PIC, the function we just // called via pointer might have been implemented in // a separate module and so overwritten the TOC diff --git a/src/cmd/compile/internal/ppc64/reg.go b/src/cmd/compile/internal/ppc64/reg.go index 447679e207..558ba4a4f4 100644 --- a/src/cmd/compile/internal/ppc64/reg.go +++ b/src/cmd/compile/internal/ppc64/reg.go @@ -113,7 +113,7 @@ func excludedregs() uint64 { // Exclude registers with fixed functions regbits := 1<<0 | RtoB(ppc64.REGSP) | RtoB(ppc64.REGG) | RtoB(ppc64.REGTLS) | RtoB(ppc64.REGTMP) - if gc.Ctxt.Flag_shared != 0 { + if gc.Ctxt.Flag_shared { // When compiling Go into PIC, R2 is reserved to be the TOC pointer // and R12 so that calls via function pointer can stomp on it. regbits |= RtoB(ppc64.REG_R2) diff --git a/src/cmd/compile/internal/x86/reg.go b/src/cmd/compile/internal/x86/reg.go index 76d90b8e89..d49a1aed9d 100644 --- a/src/cmd/compile/internal/x86/reg.go +++ b/src/cmd/compile/internal/x86/reg.go @@ -62,7 +62,7 @@ func regnames(n *int) []string { } func excludedregs() uint64 { - if gc.Ctxt.Flag_shared != 0 { + if gc.Ctxt.Flag_shared { return RtoB(x86.REG_SP) | RtoB(x86.REG_CX) } else { return RtoB(x86.REG_SP) diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go index f49ee65a04..564f96a94e 100644 --- a/src/cmd/internal/obj/arm/asm5.go +++ b/src/cmd/internal/obj/arm/asm5.go @@ -870,7 +870,7 @@ func addpool(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) { t.To.Type = a.Type t.To.Name = a.Name - if ctxt.Flag_shared != 0 && t.To.Sym != nil { + if ctxt.Flag_shared && t.To.Sym != nil { t.Rel = p } @@ -1015,7 +1015,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { ctxt.Instoffset = 0 // s.b. unused but just in case if a.Sym.Type == obj.STLSBSS { - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { return C_TLS_IE } else { return C_TLS_LE @@ -1322,7 +1322,7 @@ func buildop(ctxt *obj.Link) { } for n = 0; optab[n].as != obj.AXXX; n++ { if optab[n].flag&LPCREL != 0 { - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { optab[n].size += int8(optab[n].pcrelsiz) } else { optab[n].flag &^= LPCREL @@ -1633,7 +1633,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { rel.Sym = p.To.Sym rel.Add = p.To.Offset - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { if p.To.Name == obj.NAME_GOTREF { rel.Type = obj.R_GOTPCREL } else { diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index d0ae6115cb..55397132e0 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -972,7 +972,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { ctxt.Instoffset = a.Offset if a.Sym != nil { // use relocation if a.Sym.Type == obj.STLSBSS { - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { return C_TLS_IE } else { return C_TLS_LE diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 55c9f4f9e2..5f257f60ab 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -617,7 +617,7 @@ type Link struct { Debugvlog int32 Debugdivmod int32 Debugpcln int32 - Flag_shared int32 + Flag_shared bool Flag_dynlink bool Flag_optimize bool Bso *bufio.Writer diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 0497d3b678..e793f26803 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -585,7 +585,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { ctxt.Instoffset = a.Offset if a.Sym != nil { // use relocation if a.Sym.Type == obj.STLSBSS { - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { return C_TLS_IE } else { return C_TLS_LE @@ -1413,7 +1413,7 @@ func opform(ctxt *obj.Link, insn uint32) int { func symbolAccess(ctxt *obj.Link, s *obj.LSym, d int64, reg int16, op uint32) (o1, o2 uint32) { var base uint32 form := opform(ctxt, op) - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { base = REG_R2 } else { base = REG_R0 @@ -1425,7 +1425,7 @@ func symbolAccess(ctxt *obj.Link, s *obj.LSym, d int64, reg int16, op uint32) (o rel.Siz = 8 rel.Sym = s rel.Add = d - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { switch form { case D_FORM: rel.Type = obj.R_ADDRPOWER_TOCREL @@ -1646,7 +1646,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { if v != 0 { ctxt.Diag("illegal indexed instruction\n%v", p) } - if ctxt.Flag_shared != 0 && r == REG_R13 { + if ctxt.Flag_shared && r == REG_R13 { rel := obj.Addrel(ctxt.Cursym) rel.Off = int32(ctxt.Pc) rel.Siz = 4 @@ -1677,7 +1677,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { if v != 0 { ctxt.Diag("illegal indexed instruction\n%v", p) } - if ctxt.Flag_shared != 0 && r == REG_R13 { + if ctxt.Flag_shared && r == REG_R13 { rel := obj.Addrel(ctxt.Cursym) rel.Off = int32(ctxt.Pc) rel.Siz = 4 diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go index 7a24d1d1bf..4f9b3943cf 100644 --- a/src/cmd/internal/obj/ppc64/obj9.go +++ b/src/cmd/internal/obj/ppc64/obj9.go @@ -470,7 +470,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { q = p - if ctxt.Flag_shared != 0 && cursym.Name != "runtime.duffzero" && cursym.Name != "runtime.duffcopy" && cursym.Name != "runtime.stackBarrier" { + if ctxt.Flag_shared && cursym.Name != "runtime.duffzero" && cursym.Name != "runtime.duffcopy" && cursym.Name != "runtime.stackBarrier" { // When compiling Go into PIC, all functions must start // with instructions to load the TOC pointer into r2: // @@ -558,7 +558,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { q.Spadj = int32(-aoffset) } - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { q = obj.Appendp(ctxt, q) q.As = AMOVD q.Lineno = p.Lineno diff --git a/src/cmd/internal/obj/s390x/asmz.go b/src/cmd/internal/obj/s390x/asmz.go index bae4dc3ce7..9b26580d11 100644 --- a/src/cmd/internal/obj/s390x/asmz.go +++ b/src/cmd/internal/obj/s390x/asmz.go @@ -473,7 +473,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { } ctxt.Instoffset = a.Offset if a.Sym.Type == obj.STLSBSS { - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { return C_TLS_IE // initial exec model } return C_TLS_LE // local exec model diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index c563a7a48d..e806a834fd 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -2165,7 +2165,7 @@ func prefixof(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int { return 0x64 // FS } - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { log.Fatalf("unknown TLS base register for linux with -shared") } else { return 0x64 // FS @@ -2185,7 +2185,7 @@ func prefixof(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int { } if p.Mode == 32 { - if a.Index == REG_TLS && ctxt.Flag_shared != 0 { + if a.Index == REG_TLS && ctxt.Flag_shared { // When building for inclusion into a shared library, an instruction of the form // MOVL 0(CX)(TLS*1), AX // becomes @@ -2214,7 +2214,7 @@ func prefixof(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int { return 0x26 case REG_TLS: - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { // When building for inclusion into a shared library, an instruction of the form // MOV 0(CX)(TLS*1), AX // becomes @@ -2288,7 +2288,7 @@ func oclass(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int { case obj.NAME_EXTERN, obj.NAME_STATIC: - if a.Sym != nil && isextern(a.Sym) || (p.Mode == 32 && ctxt.Flag_shared == 0) { + if a.Sym != nil && isextern(a.Sym) || (p.Mode == 32 && !ctxt.Flag_shared) { return Yi32 } return Yiauto // use pc-relative addressing @@ -2707,7 +2707,7 @@ func vaddr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r *obj.Reloc) int64 { if a.Name == obj.NAME_GOTREF { r.Siz = 4 r.Type = obj.R_GOTPCREL - } else if isextern(s) || (p.Mode != 64 && ctxt.Flag_shared == 0) { + } else if isextern(s) || (p.Mode != 64 && !ctxt.Flag_shared) { r.Siz = 4 r.Type = obj.R_ADDR } else { @@ -2728,7 +2728,7 @@ func vaddr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r *obj.Reloc) int64 { log.Fatalf("reloc") } - if ctxt.Flag_shared == 0 || isAndroid { + if !ctxt.Flag_shared || isAndroid { r.Type = obj.R_TLS_LE r.Siz = 4 r.Off = -1 // caller must fill in @@ -2793,7 +2793,7 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) if !isextern(a.Sym) && p.Mode == 64 { goto bad } - if p.Mode == 32 && ctxt.Flag_shared != 0 { + if p.Mode == 32 && ctxt.Flag_shared { base = REG_CX } else { base = REG_NONE @@ -2838,7 +2838,7 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) if a.Sym == nil { ctxt.Diag("bad addr: %v", p) } - if p.Mode == 32 && ctxt.Flag_shared != 0 { + if p.Mode == 32 && ctxt.Flag_shared { base = REG_CX } else { base = REG_NONE @@ -2892,7 +2892,7 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) } if REG_AX <= base && base <= REG_R15 { - if a.Index == REG_TLS && ctxt.Flag_shared == 0 { + if a.Index == REG_TLS && !ctxt.Flag_shared { rel = obj.Reloc{} rel.Type = obj.R_TLS_LE rel.Siz = 4 @@ -3945,7 +3945,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { case obj.Hlinux, obj.Hnacl: - if ctxt.Flag_shared != 0 { + if ctxt.Flag_shared { // Note that this is not generating the same insns as the other cases. // MOV TLS, R_to // becomes @@ -4019,7 +4019,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { log.Fatalf("unknown TLS base location for %s", obj.Headstr(ctxt.Headtype)) case obj.Hlinux: - if ctxt.Flag_shared == 0 { + if !ctxt.Flag_shared { log.Fatalf("unknown TLS base location for linux without -shared") } // Note that this is not generating the same insn as the other cases. diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index 302a597f4c..b638c048e8 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -66,7 +66,7 @@ func CanUse1InsnTLS(ctxt *obj.Link) bool { obj.Hwindows: return false case obj.Hlinux: - return ctxt.Flag_shared == 0 + return !ctxt.Flag_shared } return true @@ -314,7 +314,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { rewriteToUseGot(ctxt, p) } - if ctxt.Flag_shared != 0 && p.Mode == 32 { + if ctxt.Flag_shared && p.Mode == 32 { rewriteToPcrel(ctxt, p) } } -- cgit v1.3 From 045411e6f28c64e6448a2432fa652cc80ca18f31 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 12 Apr 2016 17:58:46 -0700 Subject: cmd/internal/obj: remove use of package bio Also add MustClose and MustWriter to cmd/internal/bio, and use them in cmd/asm. Change-Id: I07f5df3b66c17bc5b2e6ec9c4357d9b653e354e0 Reviewed-on: https://go-review.googlesource.com/21938 Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- src/cmd/asm/main.go | 13 +++++++----- src/cmd/compile/internal/gc/obj.go | 2 +- src/cmd/internal/bio/buf.go | 2 +- src/cmd/internal/bio/must.go | 43 ++++++++++++++++++++++++++++++++++++++ src/cmd/internal/obj/objfile.go | 9 ++++---- 5 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 src/cmd/internal/bio/must.go (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go index 40e1d9c4a9..c612583e6b 100644 --- a/src/cmd/asm/main.go +++ b/src/cmd/asm/main.go @@ -44,12 +44,15 @@ func main() { defer ctxt.Bso.Flush() // Create object file, write header. - output, err := bio.Create(*flags.OutputFile) + out, err := os.Create(*flags.OutputFile) if err != nil { log.Fatal(err) } - fmt.Fprintf(output, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion()) - fmt.Fprintf(output, "!\n") + defer bio.MustClose(out) + buf := bufio.NewWriter(bio.MustWriter(out)) + + fmt.Fprintf(buf, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion()) + fmt.Fprintf(buf, "!\n") lexer := lex.NewLexer(flag.Arg(0), ctxt) parser := asm.NewParser(ctxt, architecture, lexer) @@ -63,12 +66,12 @@ func main() { pList.Firstpc, ok = parser.Parse() if ok { // reports errors to parser.Errorf - obj.Writeobjdirect(ctxt, output) + obj.Writeobjdirect(ctxt, buf) } if !ok || diag { log.Printf("assembly of %s failed", flag.Arg(0)) os.Remove(*flags.OutputFile) os.Exit(1) } - output.Flush() + buf.Flush() } diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 59ce0547c8..b60f78f638 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -88,7 +88,7 @@ func dumpobj() { externdcl = tmp dumpdata() - obj.Writeobjdirect(Ctxt, bout) + obj.Writeobjdirect(Ctxt, bout.Writer) if writearchive { bout.Flush() diff --git a/src/cmd/internal/bio/buf.go b/src/cmd/internal/bio/buf.go index 7a077041c2..54ce3c7681 100644 --- a/src/cmd/internal/bio/buf.go +++ b/src/cmd/internal/bio/buf.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package bio implements seekable buffered I/O. +// Package bio implements common I/O abstractions used within the Go toolchain. package bio import ( diff --git a/src/cmd/internal/bio/must.go b/src/cmd/internal/bio/must.go new file mode 100644 index 0000000000..3604b29175 --- /dev/null +++ b/src/cmd/internal/bio/must.go @@ -0,0 +1,43 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bio + +import ( + "io" + "log" +) + +// MustClose closes Closer c and calls log.Fatal if it returns a non-nil error. +func MustClose(c io.Closer) { + if err := c.Close(); err != nil { + log.Fatal(err) + } +} + +// MustWriter returns a Writer that wraps the provided Writer, +// except that it calls log.Fatal instead of returning a non-nil error. +func MustWriter(w io.Writer) io.Writer { + return mustWriter{w} +} + +type mustWriter struct { + w io.Writer +} + +func (w mustWriter) Write(b []byte) (int, error) { + n, err := w.w.Write(b) + if err != nil { + log.Fatal(err) + } + return n, nil +} + +func (w mustWriter) WriteString(s string) (int, error) { + n, err := io.WriteString(w.w, s) + if err != nil { + log.Fatal(err) + } + return n, nil +} diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 7d88db2bcc..60505dfbb5 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -109,7 +109,6 @@ package obj import ( "bufio" - "cmd/internal/bio" "cmd/internal/sys" "fmt" "log" @@ -120,7 +119,7 @@ import ( // The Go and C compilers, and the assembler, call writeobj to write // out a Go object file. The linker does not call this; the linker // does not write out object files. -func Writeobjdirect(ctxt *Link, b *bio.Writer) { +func Writeobjdirect(ctxt *Link, b *bufio.Writer) { Flushplist(ctxt) WriteObjFile(ctxt, b) } @@ -187,16 +186,16 @@ func (w *objWriter) writeLengths() { w.writeInt(int64(w.nFile)) } -func newObjWriter(ctxt *Link, b *bio.Writer) *objWriter { +func newObjWriter(ctxt *Link, b *bufio.Writer) *objWriter { return &objWriter{ ctxt: ctxt, - wr: b.Writer, + wr: b, vrefIdx: make(map[string]int), refIdx: make(map[string]int), } } -func WriteObjFile(ctxt *Link, b *bio.Writer) { +func WriteObjFile(ctxt *Link, b *bufio.Writer) { w := newObjWriter(ctxt, b) // Magic header -- cgit v1.3 From 1441f76938bf61a2c8c2ed1a65082ddde0319633 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 14 Apr 2016 19:04:45 -0700 Subject: cmd: remove unnecessary type conversions CL generated mechanically with github.com/mdempsky/unconvert. Change-Id: Ic590315cbc7026163a1b3f8ea306ba35f1a53256 Reviewed-on: https://go-review.googlesource.com/22103 Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot Reviewed-by: Michael Hudson-Doyle --- src/cmd/asm/internal/asm/asm.go | 4 ++-- src/cmd/cgo/ast.go | 10 +++++----- src/cmd/compile/internal/s390x/peep.go | 4 ++-- src/cmd/go/http.go | 2 +- src/cmd/go/vcs.go | 4 ++-- src/cmd/internal/obj/arm64/obj7.go | 4 ++-- src/cmd/internal/obj/data.go | 2 +- src/cmd/internal/obj/mips/asm0.go | 2 +- src/cmd/internal/obj/objfile.go | 6 +++--- src/cmd/internal/obj/pcln.go | 10 +++++----- src/cmd/internal/obj/ppc64/asm9.go | 14 +++++++------- src/cmd/internal/obj/util.go | 2 +- src/cmd/internal/obj/x86/asm6.go | 16 ++++++++-------- src/cmd/internal/objfile/plan9obj.go | 2 +- src/cmd/internal/pprof/profile/legacy_profile.go | 10 +++++----- .../unvendor/golang.org/x/arch/arm/armasm/decode.go | 8 ++++---- .../unvendor/golang.org/x/arch/x86/x86asm/decode.go | 2 +- src/cmd/link/internal/amd64/asm.go | 2 +- src/cmd/link/internal/arm/asm.go | 2 +- src/cmd/link/internal/arm64/asm.go | 2 +- src/cmd/link/internal/ld/data.go | 18 +++++++++--------- src/cmd/link/internal/ld/decodesym.go | 4 ++-- src/cmd/link/internal/ld/dwarf.go | 18 +++++++++--------- src/cmd/link/internal/ld/elf.go | 2 +- src/cmd/link/internal/ld/ldelf.go | 6 +++--- src/cmd/link/internal/ld/ldmacho.go | 16 ++++++++-------- src/cmd/link/internal/ld/ldpe.go | 8 ++++---- src/cmd/link/internal/ld/lib.go | 4 ++-- src/cmd/link/internal/ld/macho.go | 4 ++-- src/cmd/link/internal/ld/objfile.go | 2 +- src/cmd/link/internal/ld/pcln.go | 4 ++-- src/cmd/link/internal/ld/pe.go | 4 ++-- src/cmd/link/internal/ld/symtab.go | 8 ++++---- src/cmd/link/internal/mips64/asm.go | 4 ++-- src/cmd/link/internal/ppc64/asm.go | 2 +- src/cmd/link/internal/x86/asm.go | 2 +- src/cmd/vet/structtag.go | 2 +- 37 files changed, 108 insertions(+), 108 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go index d674914c67..24906e2cce 100644 --- a/src/cmd/asm/internal/asm/asm.go +++ b/src/cmd/asm/internal/asm/asm.go @@ -59,7 +59,7 @@ func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) { } p.pendingLabels = p.pendingLabels[0:0] } - prog.Pc = int64(p.pc) + prog.Pc = p.pc if *flags.Debug { fmt.Println(p.histLineNum, prog) } @@ -371,7 +371,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) { Offset: p.getConstant(prog, op, &a[0]), } reg := int16(p.getConstant(prog, op, &a[1])) - reg, ok := p.arch.RegisterNumber("R", int16(reg)) + reg, ok := p.arch.RegisterNumber("R", reg) if !ok { p.errorf("bad register number %d", reg) return diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go index 2859d59750..823da43c1d 100644 --- a/src/cmd/cgo/ast.go +++ b/src/cmd/cgo/ast.go @@ -73,7 +73,7 @@ func (f *File) ReadGo(name string) { } for _, spec := range d.Specs { s, ok := spec.(*ast.ImportSpec) - if !ok || string(s.Path.Value) != `"C"` { + if !ok || s.Path.Value != `"C"` { continue } sawC = true @@ -106,7 +106,7 @@ func (f *File) ReadGo(name string) { ws := 0 for _, spec := range d.Specs { s, ok := spec.(*ast.ImportSpec) - if !ok || string(s.Path.Value) != `"C"` { + if !ok || s.Path.Value != `"C"` { d.Specs[ws] = spec ws++ } @@ -147,7 +147,7 @@ func commentText(g *ast.CommentGroup) string { } var pieces []string for _, com := range g.List { - c := string(com.Text) + c := com.Text // Remove comment markers. // The parser has given us exactly the comment text. switch c[1] { @@ -242,11 +242,11 @@ func (f *File) saveExport(x interface{}, context string) { return } for _, c := range n.Doc.List { - if !strings.HasPrefix(string(c.Text), "//export ") { + if !strings.HasPrefix(c.Text, "//export ") { continue } - name := strings.TrimSpace(string(c.Text[9:])) + name := strings.TrimSpace(c.Text[9:]) if name == "" { error_(c.Pos(), "export missing name") } diff --git a/src/cmd/compile/internal/s390x/peep.go b/src/cmd/compile/internal/s390x/peep.go index 86258d67da..cd6a8c5d8c 100644 --- a/src/cmd/compile/internal/s390x/peep.go +++ b/src/cmd/compile/internal/s390x/peep.go @@ -135,7 +135,7 @@ func pushback(r0 *gc.Flow) { } } - t := obj.Prog(*r0.Prog) + t := *r0.Prog for r = gc.Uniqp(r0); ; r = gc.Uniqp(r) { p0 = r.Link.Prog p := r.Prog @@ -162,7 +162,7 @@ func pushback(r0 *gc.Flow) { if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 { fmt.Printf("\tafter\n") - for r := (*gc.Flow)(b); ; r = r.Link { + for r := b; ; r = r.Link { fmt.Printf("\t%v\n", r.Prog) if r == r0 { break diff --git a/src/cmd/go/http.go b/src/cmd/go/http.go index 19e1fe4f77..05ea503049 100644 --- a/src/cmd/go/http.go +++ b/src/cmd/go/http.go @@ -30,7 +30,7 @@ var httpClient = http.DefaultClient // when we're connecting to https servers that might not be there // or might be using self-signed certificates. var impatientInsecureHTTPClient = &http.Client{ - Timeout: time.Duration(5 * time.Second), + Timeout: 5 * time.Second, Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go index e3342999fa..4ff71f2168 100644 --- a/src/cmd/go/vcs.go +++ b/src/cmd/go/vcs.go @@ -253,7 +253,7 @@ func bzrResolveRepo(vcsBzr *vcsCmd, rootDir, remoteRepo string) (realRepo string return "", fmt.Errorf("unable to parse output of bzr info") } out = out[:i] - return strings.TrimSpace(string(out)), nil + return strings.TrimSpace(out), nil } // vcsSvn describes how to use Subversion. @@ -294,7 +294,7 @@ func svnRemoteRepo(vcsSvn *vcsCmd, rootDir string) (remoteRepo string, err error return "", fmt.Errorf("unable to parse output of svn info") } out = out[:i] - return strings.TrimSpace(string(out)), nil + return strings.TrimSpace(out), nil } func (v *vcsCmd) String() string { diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index d833beeb2d..ffa1b416d6 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -250,7 +250,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { if p.From.Type == obj.TYPE_FCONST { f32 := float32(p.From.Val.(float64)) i32 := math.Float32bits(f32) - literal := fmt.Sprintf("$f32.%08x", uint32(i32)) + literal := fmt.Sprintf("$f32.%08x", i32) s := obj.Linklookup(ctxt, literal, 0) s.Size = 4 p.From.Type = obj.TYPE_MEM @@ -263,7 +263,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { case AFMOVD: if p.From.Type == obj.TYPE_FCONST { i64 := math.Float64bits(p.From.Val.(float64)) - literal := fmt.Sprintf("$f64.%016x", uint64(i64)) + literal := fmt.Sprintf("$f64.%016x", i64) s := obj.Linklookup(ctxt, literal, 0) s.Size = 8 p.From.Type = obj.TYPE_MEM diff --git a/src/cmd/internal/obj/data.go b/src/cmd/internal/obj/data.go index d7f0840bc1..5fe4cb10a5 100644 --- a/src/cmd/internal/obj/data.go +++ b/src/cmd/internal/obj/data.go @@ -183,7 +183,7 @@ func Setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 { case 4: ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(v)) case 8: - ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(v)) + ctxt.Arch.ByteOrder.PutUint64(s.P[off:], v) } return off + wid diff --git a/src/cmd/internal/obj/mips/asm0.go b/src/cmd/internal/obj/mips/asm0.go index 13e7600c21..73d6cabbcb 100644 --- a/src/cmd/internal/obj/mips/asm0.go +++ b/src/cmd/internal/obj/mips/asm0.go @@ -1024,7 +1024,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 = OP_IRR(opirr(ctxt, p.As), uint32(v), uint32(r), uint32(p.To.Reg)) case 5: /* syscall */ - o1 = uint32(oprrr(ctxt, p.As)) + o1 = oprrr(ctxt, p.As) case 6: /* beq r1,[r2],sbra */ v := int32(0) diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 60505dfbb5..17175ebf06 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -371,9 +371,9 @@ func (w *objWriter) writeSymDebug(s *LSym) { name = "TLS" } if ctxt.Arch.InFamily(sys.ARM, sys.PPC64) { - fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%x\n", int(r.Off), r.Siz, r.Type, name, uint64(int64(r.Add))) + fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%x\n", int(r.Off), r.Siz, r.Type, name, uint64(r.Add)) } else { - fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%d\n", int(r.Off), r.Siz, r.Type, name, int64(r.Add)) + fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%d\n", int(r.Off), r.Siz, r.Type, name, r.Add) } } } @@ -473,7 +473,7 @@ func (w *objWriter) writeSym(s *LSym) { func (w *objWriter) writeInt(sval int64) { var v uint64 - uv := (uint64(sval) << 1) ^ uint64(int64(sval>>63)) + uv := (uint64(sval) << 1) ^ uint64(sval>>63) p := w.varintbuf[:] for v = uv; v >= 0x80; v >>= 7 { p[0] = uint8(v | 0x80) diff --git a/src/cmd/internal/obj/pcln.go b/src/cmd/internal/obj/pcln.go index eca7531f3c..a086be9f66 100644 --- a/src/cmd/internal/obj/pcln.go +++ b/src/cmd/internal/obj/pcln.go @@ -64,7 +64,7 @@ func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(* if val == oldval && started != 0 { val = valfunc(ctxt, func_, val, p, 1, arg) if ctxt.Debugpcln != 0 { - fmt.Fprintf(ctxt.Bso, "%6x %6s %v\n", uint64(int64(p.Pc)), "", p) + fmt.Fprintf(ctxt.Bso, "%6x %6s %v\n", uint64(p.Pc), "", p) } continue } @@ -76,7 +76,7 @@ func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(* if p.Link != nil && p.Link.Pc == p.Pc { val = valfunc(ctxt, func_, val, p, 1, arg) if ctxt.Debugpcln != 0 { - fmt.Fprintf(ctxt.Bso, "%6x %6s %v\n", uint64(int64(p.Pc)), "", p) + fmt.Fprintf(ctxt.Bso, "%6x %6s %v\n", uint64(p.Pc), "", p) } continue } @@ -96,7 +96,7 @@ func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(* // where the 0x80 bit indicates that the integer continues. if ctxt.Debugpcln != 0 { - fmt.Fprintf(ctxt.Bso, "%6x %6d %v\n", uint64(int64(p.Pc)), val, p) + fmt.Fprintf(ctxt.Bso, "%6x %6d %v\n", uint64(p.Pc), val, p) } if started != 0 { @@ -118,7 +118,7 @@ func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(* if started != 0 { if ctxt.Debugpcln != 0 { - fmt.Fprintf(ctxt.Bso, "%6x done\n", uint64(int64(func_.Text.Pc)+func_.Size)) + fmt.Fprintf(ctxt.Bso, "%6x done\n", uint64(func_.Text.Pc+func_.Size)) } addvarint(ctxt, dst, uint32((func_.Size-pc)/int64(ctxt.Arch.MinLC))) addvarint(ctxt, dst, 0) // terminator @@ -164,7 +164,7 @@ func pctofileline(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg if file == f { pcln.Lastfile = f pcln.Lastindex = int(i) - return int32(i) + return i } } pcln.File = append(pcln.File, f) diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index e793f26803..f786f3c443 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -1384,7 +1384,7 @@ const ( // which relocation to use with a load or store and only supports the needed // instructions. func opform(ctxt *obj.Link, insn uint32) int { - switch uint32(insn) { + switch insn { default: ctxt.Diag("bad insn in loadform: %x", insn) case OPVCC(58, 0, 0, 0), // ld @@ -2198,9 +2198,9 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { } v := oprrr(ctxt, p.As) t := v & (1<<10 | 1) /* OE|Rc */ - o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg)) + o1 = AOP_RRR(v&^t, REGTMP, uint32(r), uint32(p.From.Reg)) o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, uint32(p.From.Reg)) - o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r)) + o3 = AOP_RRR(OP_SUBF|t, uint32(p.To.Reg), REGTMP, uint32(r)) if p.As == AREMU { o4 = o3 @@ -2216,9 +2216,9 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { } v := oprrr(ctxt, p.As) t := v & (1<<10 | 1) /* OE|Rc */ - o1 = AOP_RRR(uint32(v)&^uint32(t), REGTMP, uint32(r), uint32(p.From.Reg)) + o1 = AOP_RRR(v&^t, REGTMP, uint32(r), uint32(p.From.Reg)) o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, uint32(p.From.Reg)) - o3 = AOP_RRR(OP_SUBF|uint32(t), uint32(p.To.Reg), REGTMP, uint32(r)) + o3 = AOP_RRR(OP_SUBF|t, uint32(p.To.Reg), REGTMP, uint32(r)) case 52: /* mtfsbNx cr(n) */ v := regoff(ctxt, &p.From) & 31 @@ -2485,7 +2485,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ctxt.Diag("invalid offset against tls var %v", p) } o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), REG_R2, 0) - o2 = AOP_IRR(uint32(opload(ctxt, AMOVD)), uint32(p.To.Reg), uint32(p.To.Reg), 0) + o2 = AOP_IRR(opload(ctxt, AMOVD), uint32(p.To.Reg), uint32(p.To.Reg), 0) rel := obj.Addrel(ctxt.Cursym) rel.Off = int32(ctxt.Pc) rel.Siz = 8 @@ -2499,7 +2499,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { } o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), REG_R2, 0) - o2 = AOP_IRR(uint32(opload(ctxt, AMOVD)), uint32(p.To.Reg), uint32(p.To.Reg), 0) + o2 = AOP_IRR(opload(ctxt, AMOVD), uint32(p.To.Reg), uint32(p.To.Reg), 0) rel := obj.Addrel(ctxt.Cursym) rel.Off = int32(ctxt.Pc) rel.Siz = 8 diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go index 04e6a76e1a..294cedcb0a 100644 --- a/src/cmd/internal/obj/util.go +++ b/src/cmd/internal/obj/util.go @@ -279,7 +279,7 @@ func Dconv(p *Prog, a *Addr) string { case TYPE_SHIFT: v := int(a.Offset) - op := string("<<>>->@>"[((v>>5)&3)<<1:]) + op := "<<>>->@>"[((v>>5)&3)<<1:] if v&(1<<4) != 0 { str = fmt.Sprintf("R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15) } else { diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index e806a834fd..57ef045b98 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -3308,7 +3308,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { case Pf2, /* xmm opcode escape */ Pf3: - ctxt.AsmBuf.Put2(byte(o.prefix), Pm) + ctxt.AsmBuf.Put2(o.prefix, Pm) case Pef3: ctxt.AsmBuf.Put3(Pe, Pf3, Pm) @@ -3421,7 +3421,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { asmand(ctxt, p, &p.From, &p.To) case Zm2_r: - ctxt.AsmBuf.Put2(byte(op), byte(o.op[z+1])) + ctxt.AsmBuf.Put2(byte(op), o.op[z+1]) asmand(ctxt, p, &p.From, &p.To) case Zm_r_xm: @@ -3531,7 +3531,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { } ctxt.AsmBuf.Put1(byte(op)) if p.As == AXABORT { - ctxt.AsmBuf.Put1(byte(o.op[z+1])) + ctxt.AsmBuf.Put1(o.op[z+1]) } ctxt.AsmBuf.Put1(byte(vaddr(ctxt, p, a, nil))) @@ -3657,7 +3657,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { if yt.zcase == Zcallcon { ctxt.AsmBuf.Put1(byte(op)) } else { - ctxt.AsmBuf.Put1(byte(o.op[z+1])) + ctxt.AsmBuf.Put1(o.op[z+1]) } r = obj.Addrel(ctxt.Cursym) r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) @@ -3667,7 +3667,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ctxt.AsmBuf.PutInt32(0) case Zcallind: - ctxt.AsmBuf.Put2(byte(op), byte(o.op[z+1])) + ctxt.AsmBuf.Put2(byte(op), o.op[z+1]) r = obj.Addrel(ctxt.Cursym) r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Type = obj.R_ADDR @@ -3722,7 +3722,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { log.Fatalf("bad code") } - ctxt.AsmBuf.Put1(byte(o.op[z+1])) + ctxt.AsmBuf.Put1(o.op[z+1]) r = obj.Addrel(ctxt.Cursym) r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Sym = p.To.Sym @@ -3762,7 +3762,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { v-- } - ctxt.AsmBuf.Put1(byte(o.op[z+1])) + ctxt.AsmBuf.Put1(o.op[z+1]) ctxt.AsmBuf.PutInt32(int32(v)) } @@ -3784,7 +3784,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { if yt.zcase == Zbr { ctxt.AsmBuf.Put1(0x0f) } - ctxt.AsmBuf.Put1(byte(o.op[z+1])) + ctxt.AsmBuf.Put1(o.op[z+1]) ctxt.AsmBuf.PutInt32(0) } diff --git a/src/cmd/internal/objfile/plan9obj.go b/src/cmd/internal/objfile/plan9obj.go index 1d808f77eb..6ee389dc2e 100644 --- a/src/cmd/internal/objfile/plan9obj.go +++ b/src/cmd/internal/objfile/plan9obj.go @@ -59,7 +59,7 @@ func (f *plan9File) symbols() ([]Sym, error) { if !validSymType[s.Type] { continue } - sym := Sym{Addr: s.Value, Name: s.Name, Code: rune(s.Type)} + sym := Sym{Addr: s.Value, Name: s.Name, Code: s.Type} i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value }) if i < len(addrs) { sym.Size = int64(addrs[i] - s.Value) diff --git a/src/cmd/internal/pprof/profile/legacy_profile.go b/src/cmd/internal/pprof/profile/legacy_profile.go index 3d4da6b4d7..8ccfe45176 100644 --- a/src/cmd/internal/pprof/profile/legacy_profile.go +++ b/src/cmd/internal/pprof/profile/legacy_profile.go @@ -74,7 +74,7 @@ func parseGoCount(b []byte) (*Profile, error) { if m == nil { return nil, errUnrecognized } - profileType := string(m[1]) + profileType := m[1] p := &Profile{ PeriodType: &ValueType{Type: profileType, Unit: "count"}, Period: 1, @@ -99,11 +99,11 @@ func parseGoCount(b []byte) (*Profile, error) { if m == nil { return nil, errMalformed } - n, err := strconv.ParseInt(string(m[1]), 0, 64) + n, err := strconv.ParseInt(m[1], 0, 64) if err != nil { return nil, errMalformed } - fields := strings.Fields(string(m[2])) + fields := strings.Fields(m[2]) locs := make([]*Location, 0, len(fields)) for _, stk := range fields { addr, err := strconv.ParseUint(stk, 0, 64) @@ -458,7 +458,7 @@ func parseCPUSamples(b []byte, parse func(b []byte) (uint64, []byte), adjust boo } p.Sample = append(p.Sample, &Sample{ - Value: []int64{int64(count), int64(count) * int64(p.Period)}, + Value: []int64{int64(count), int64(count) * p.Period}, Location: sloc, }) } @@ -488,7 +488,7 @@ func parseHeap(b []byte) (p *Profile, err error) { var period int64 if len(header[6]) > 0 { - if period, err = strconv.ParseInt(string(header[6]), 10, 64); err != nil { + if period, err = strconv.ParseInt(header[6], 10, 64); err != nil { return nil, errUnrecognized } } diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go index 6b4d73841b..cc81dc3f50 100644 --- a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go @@ -233,9 +233,9 @@ func decodeArg(aop instArg, x uint32) Arg { typ, count := decodeShift(x) // ROR #0 here means ROR #0, but decodeShift rewrites to RRX #1. if typ == RotateRightExt { - return Reg(Rm) + return Rm } - return RegShift{Rm, typ, uint8(count)} + return RegShift{Rm, typ, count} case arg_R_shift_R: Rm := Reg(x & (1<<4 - 1)) @@ -247,9 +247,9 @@ func decodeArg(aop instArg, x uint32) Arg { Rm := Reg(x & (1<<4 - 1)) typ, count := decodeShift(x) if typ == ShiftLeft && count == 0 { - return Reg(Rm) + return Rm } - return RegShift{Rm, typ, uint8(count)} + return RegShift{Rm, typ, count} case arg_R1_0: return Reg((x & (1<<4 - 1))) diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go index e4122c1e6d..9b3597300e 100644 --- a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go +++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go @@ -1041,7 +1041,7 @@ Decode: case xArgMoffs8, xArgMoffs16, xArgMoffs32, xArgMoffs64: // TODO(rsc): Can address be 64 bits? - mem = Mem{Disp: int64(immc)} + mem = Mem{Disp: immc} if segIndex >= 0 { mem.Segment = prefixToSegment(inst.Prefix[segIndex]) inst.Prefix[segIndex] |= PrefixImplicit diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go index a6dce6c2c9..ab96a59151 100644 --- a/src/cmd/link/internal/amd64/asm.go +++ b/src/cmd/link/internal/amd64/asm.go @@ -735,7 +735,7 @@ func asmb() { if sym != nil { ld.Lcsize = int32(len(sym.P)) for i := 0; int32(i) < ld.Lcsize; i++ { - ld.Cput(uint8(sym.P[i])) + ld.Cput(sym.P[i]) } ld.Cflush() diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go index 1188615716..69e1d8f317 100644 --- a/src/cmd/link/internal/arm/asm.go +++ b/src/cmd/link/internal/arm/asm.go @@ -649,7 +649,7 @@ func asmb() { if sym != nil { ld.Lcsize = int32(len(sym.P)) for i := 0; int32(i) < ld.Lcsize; i++ { - ld.Cput(uint8(sym.P[i])) + ld.Cput(sym.P[i]) } ld.Cflush() diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go index d3ba5ff3f3..d8ffffa157 100644 --- a/src/cmd/link/internal/arm64/asm.go +++ b/src/cmd/link/internal/arm64/asm.go @@ -488,7 +488,7 @@ func asmb() { if sym != nil { ld.Lcsize = int32(len(sym.P)) for i := 0; int32(i) < ld.Lcsize; i++ { - ld.Cput(uint8(sym.P[i])) + ld.Cput(sym.P[i]) } ld.Cflush() diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index cf51b0a908..105503f6ef 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -80,7 +80,7 @@ func setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 { case 4: ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(v)) case 8: - ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(v)) + ctxt.Arch.ByteOrder.PutUint64(s.P[off:], v) } return off + wid @@ -757,7 +757,7 @@ func blk(start *LSym, addr int64, size int64) { } Ctxt.Cursym = sym if sym.Value < addr { - Diag("phase error: addr=%#x but sym=%#x type=%d", int64(addr), int64(sym.Value), sym.Type) + Diag("phase error: addr=%#x but sym=%#x type=%d", addr, sym.Value, sym.Type) errorexit() } @@ -773,7 +773,7 @@ func blk(start *LSym, addr int64, size int64) { addr = sym.Value + sym.Size } if addr != sym.Value+sym.Size { - Diag("phase error: addr=%#x value+size=%#x", int64(addr), int64(sym.Value)+sym.Size) + Diag("phase error: addr=%#x value+size=%#x", addr, sym.Value+sym.Size) errorexit() } @@ -821,14 +821,14 @@ func Codeblk(addr int64, size int64) { } if addr < sym.Value { - fmt.Fprintf(Bso, "%-20s %.8x|", "_", uint64(int64(addr))) + fmt.Fprintf(Bso, "%-20s %.8x|", "_", uint64(addr)) for ; addr < sym.Value; addr++ { fmt.Fprintf(Bso, " %.2x", 0) } fmt.Fprintf(Bso, "\n") } - fmt.Fprintf(Bso, "%.6x\t%-20s\n", uint64(int64(addr)), sym.Name) + fmt.Fprintf(Bso, "%.6x\t%-20s\n", uint64(addr), sym.Name) q = sym.P for len(q) >= 16 { @@ -844,7 +844,7 @@ func Codeblk(addr int64, size int64) { } if addr < eaddr { - fmt.Fprintf(Bso, "%-20s %.8x|", "_", uint64(int64(addr))) + fmt.Fprintf(Bso, "%-20s %.8x|", "_", uint64(addr)) for ; addr < eaddr; addr++ { fmt.Fprintf(Bso, " %.2x", 0) } @@ -892,7 +892,7 @@ func Datblk(addr int64, size int64) { p = sym.P ep = p[len(sym.P):] for -cap(p) < -cap(ep) { - if -cap(p) > -cap(sym.P) && int(-cap(p)+cap(sym.P))%16 == 0 { + if -cap(p) > -cap(sym.P) && (-cap(p)+cap(sym.P))%16 == 0 { fmt.Fprintf(Bso, "\n\t%.8x|", uint(addr+int64(-cap(p)+cap(sym.P)))) } fmt.Fprintf(Bso, " %.2x", p[0]) @@ -924,7 +924,7 @@ func Datblk(addr int64, size int64) { typ = "call" } - fmt.Fprintf(Bso, "\treloc %.8x/%d %s %s+%#x [%#x]\n", uint(sym.Value+int64(r.Off)), r.Siz, typ, rsname, int64(r.Add), int64(r.Sym.Value+r.Add)) + fmt.Fprintf(Bso, "\treloc %.8x/%d %s %s+%#x [%#x]\n", uint(sym.Value+int64(r.Off)), r.Siz, typ, rsname, r.Add, r.Sym.Value+r.Add) } } } @@ -1279,7 +1279,7 @@ func dodata() { for s := datap; s != nil; s = s.Next { if int64(len(s.P)) > s.Size { - Diag("%s: initialize bounds (%d < %d)", s.Name, int64(s.Size), len(s.P)) + Diag("%s: initialize bounds (%d < %d)", s.Name, s.Size, len(s.P)) } } diff --git a/src/cmd/link/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go index 5fa8b4c81f..4725b91d01 100644 --- a/src/cmd/link/internal/ld/decodesym.go +++ b/src/cmd/link/internal/ld/decodesym.go @@ -53,12 +53,12 @@ func uncommonSize() int { return 2 * SysArch.PtrSize } // runtime.uncommont // Type.commonType.kind func decodetype_kind(s *LSym) uint8 { - return uint8(s.P[2*SysArch.PtrSize+7] & obj.KindMask) // 0x13 / 0x1f + return s.P[2*SysArch.PtrSize+7] & obj.KindMask // 0x13 / 0x1f } // Type.commonType.kind func decodetype_usegcprog(s *LSym) uint8 { - return uint8(s.P[2*SysArch.PtrSize+7] & obj.KindGCProg) // 0x13 / 0x1f + return s.P[2*SysArch.PtrSize+7] & obj.KindGCProg // 0x13 / 0x1f } // Type.commonType.size diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index b1208b63a8..bec9946ec5 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -615,7 +615,7 @@ func putattr(s *LSym, abbrev int, form int, cls int, value int64, data interface Adduint8(Ctxt, s, uint8(value)) p := data.([]byte) for i := 0; int64(i) < value; i++ { - Adduint8(Ctxt, s, uint8(p[i])) + Adduint8(Ctxt, s, p[i]) } case DW_FORM_block2: // block @@ -624,7 +624,7 @@ func putattr(s *LSym, abbrev int, form int, cls int, value int64, data interface Adduint16(Ctxt, s, uint16(value)) p := data.([]byte) for i := 0; int64(i) < value; i++ { - Adduint8(Ctxt, s, uint8(p[i])) + Adduint8(Ctxt, s, p[i]) } case DW_FORM_block4: // block @@ -633,7 +633,7 @@ func putattr(s *LSym, abbrev int, form int, cls int, value int64, data interface Adduint32(Ctxt, s, uint32(value)) p := data.([]byte) for i := 0; int64(i) < value; i++ { - Adduint8(Ctxt, s, uint8(p[i])) + Adduint8(Ctxt, s, p[i]) } case DW_FORM_block: // block @@ -641,7 +641,7 @@ func putattr(s *LSym, abbrev int, form int, cls int, value int64, data interface p := data.([]byte) for i := 0; int64(i) < value; i++ { - Adduint8(Ctxt, s, uint8(p[i])) + Adduint8(Ctxt, s, p[i]) } case DW_FORM_data1: // constant @@ -1179,7 +1179,7 @@ func synthesizemaptypes(die *DWDie) { // Construct type to represent an array of BucketSize keys keyname := nameFromDIESym(keytype) dwhks := mkinternaltype(DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *DWDie) { - newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(keysize), 0) + newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*keysize, 0) t := keytype if indirect_key { t = defptrto(keytype) @@ -1193,7 +1193,7 @@ func synthesizemaptypes(die *DWDie) { // Construct type to represent an array of BucketSize values valname := nameFromDIESym(valtype) dwhvs := mkinternaltype(DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *DWDie) { - newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(valsize), 0) + newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*valsize, 0) t := valtype if indirect_val { t = defptrto(valtype) @@ -1225,7 +1225,7 @@ func synthesizemaptypes(die *DWDie) { newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(SysArch.PtrSize)) } - newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize+BucketSize*int64(keysize)+BucketSize*int64(valsize)+int64(SysArch.RegSize), 0) + newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize+BucketSize*keysize+BucketSize*valsize+int64(SysArch.RegSize), 0) }) // Construct hash @@ -1269,7 +1269,7 @@ func synthesizechantypes(die *DWDie) { } else { elemsize = 0 } - newattr(dws, DW_AT_byte_size, DW_CLS_CONSTANT, int64(sudogsize)+int64(elemsize), nil) + newattr(dws, DW_AT_byte_size, DW_CLS_CONSTANT, int64(sudogsize)+elemsize, nil) }) // waitq @@ -1787,7 +1787,7 @@ func writeinfo(prev *LSym) *LSym { } setuint32(Ctxt, s, 0, uint32(cusize)) - newattr(compunit, DW_AT_byte_size, DW_CLS_CONSTANT, int64(cusize), 0) + newattr(compunit, DW_AT_byte_size, DW_CLS_CONSTANT, cusize, 0) } return prev } diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index 7c760775b5..02f7897db9 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -2026,7 +2026,7 @@ func doelf() { h.Write(l.hash) } addgonote(".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{})) - addgonote(".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, []byte(pkglistfornote)) + addgonote(".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote) var deplist []string for _, shlib := range Ctxt.Shlibs { deplist = append(deplist, filepath.Base(shlib.Path)) diff --git a/src/cmd/link/internal/ld/ldelf.go b/src/cmd/link/internal/ld/ldelf.go index d07a2a2c34..59e71f4dd4 100644 --- a/src/cmd/link/internal/ld/ldelf.go +++ b/src/cmd/link/internal/ld/ldelf.go @@ -500,7 +500,7 @@ func ldelf(f *bio.Reader, pkg string, length int64, pn string) { elfobj.e = e elfobj.f = f - elfobj.base = int64(base) + elfobj.base = base elfobj.length = length elfobj.name = pn @@ -612,7 +612,7 @@ func ldelf(f *bio.Reader, pkg string, length int64, pn string) { goto bad } - sect.nameoff = uint32(e.Uint32(b.Name[:])) + sect.nameoff = e.Uint32(b.Name[:]) sect.type_ = e.Uint32(b.Type[:]) sect.flags = e.Uint64(b.Flags[:]) sect.addr = e.Uint64(b.Addr[:]) @@ -629,7 +629,7 @@ func ldelf(f *bio.Reader, pkg string, length int64, pn string) { goto bad } - sect.nameoff = uint32(e.Uint32(b.Name[:])) + sect.nameoff = e.Uint32(b.Name[:]) sect.type_ = e.Uint32(b.Type[:]) sect.flags = uint64(e.Uint32(b.Flags[:])) sect.addr = uint64(e.Uint32(b.Addr[:])) diff --git a/src/cmd/link/internal/ld/ldmacho.go b/src/cmd/link/internal/ld/ldmacho.go index 8dc4033bbc..105fc137f9 100644 --- a/src/cmd/link/internal/ld/ldmacho.go +++ b/src/cmd/link/internal/ld/ldmacho.go @@ -399,8 +399,8 @@ func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int { return -1 } s.name = cstring(strbuf[v:]) - s.type_ = uint8(p[4]) - s.sectnum = uint8(p[5]) + s.type_ = p[4] + s.sectnum = p[5] s.desc = m.e.Uint16(p[6:]) if m.is64 { s.value = m.e.Uint64(p[8:]) @@ -460,8 +460,8 @@ func ldmacho(f *bio.Reader, pkg string, length int64, pn string) { } is64 = e.Uint32(hdr[:]) == 0xFEEDFACF - ncmd = e.Uint32([]byte(hdr[4*4:])) - cmdsz = e.Uint32([]byte(hdr[5*4:])) + ncmd = e.Uint32(hdr[4*4:]) + cmdsz = e.Uint32(hdr[5*4:]) if ncmd > 0x10000 || cmdsz >= 0x01000000 { err = fmt.Errorf("implausible mach-o header ncmd=%d cmdsz=%d", ncmd, cmdsz) goto bad @@ -475,11 +475,11 @@ func ldmacho(f *bio.Reader, pkg string, length int64, pn string) { m.f = f m.e = e - m.cputype = uint(e.Uint32([]byte(hdr[1*4:]))) - m.subcputype = uint(e.Uint32([]byte(hdr[2*4:]))) - m.filetype = e.Uint32([]byte(hdr[3*4:])) + m.cputype = uint(e.Uint32(hdr[1*4:])) + m.subcputype = uint(e.Uint32(hdr[2*4:])) + m.filetype = e.Uint32(hdr[3*4:]) m.ncmd = uint(ncmd) - m.flags = e.Uint32([]byte(hdr[6*4:])) + m.flags = e.Uint32(hdr[6*4:]) m.is64 = is64 m.base = base m.length = length diff --git a/src/cmd/link/internal/ld/ldpe.go b/src/cmd/link/internal/ld/ldpe.go index 7f7121ff94..c51479fb4e 100644 --- a/src/cmd/link/internal/ld/ldpe.go +++ b/src/cmd/link/internal/ld/ldpe.go @@ -175,14 +175,14 @@ func ldpe(f *bio.Reader, pkg string, length int64, pn string) { // TODO return error if found .cormeta // load string table - f.Seek(int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) + f.Seek(base+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) if _, err := io.ReadFull(f, symbuf[:4]); err != nil { goto bad } l = Le32(symbuf[:]) peobj.snames = make([]byte, l) - f.Seek(int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) + f.Seek(base+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0) if _, err := io.ReadFull(f, peobj.snames); err != nil { goto bad } @@ -203,9 +203,9 @@ func ldpe(f *bio.Reader, pkg string, length int64, pn string) { peobj.pesym = make([]PeSym, peobj.fh.NumberOfSymbols) peobj.npesym = uint(peobj.fh.NumberOfSymbols) - f.Seek(int64(base)+int64(peobj.fh.PointerToSymbolTable), 0) + f.Seek(base+int64(peobj.fh.PointerToSymbolTable), 0) for i := 0; uint32(i) < peobj.fh.NumberOfSymbols; i += numaux + 1 { - f.Seek(int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(i), 0) + f.Seek(base+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(i), 0) if _, err := io.ReadFull(f, symbuf[:]); err != nil { goto bad } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index bdcc84a129..a18098e7e7 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -765,7 +765,7 @@ func nextar(bp *bio.Reader, off int64, a *ArHdr) int64 { if arsize&1 != 0 { arsize++ } - return int64(arsize) + SAR_HDR + return arsize + SAR_HDR } func objfile(lib *Library) { @@ -1953,7 +1953,7 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) { continue } if len(s.P) > 0 { - Diag("%s should not be bss (size=%d type=%d special=%v)", s.Name, int(len(s.P)), s.Type, s.Attr.Special()) + Diag("%s should not be bss (size=%d type=%d special=%v)", s.Name, len(s.P), s.Type, s.Attr.Special()) } put(s, s.Name, 'B', Symaddr(s), s.Size, int(s.Version), s.Gotype) diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index 1d9a1a9324..46cce4c331 100644 --- a/src/cmd/link/internal/ld/macho.go +++ b/src/cmd/link/internal/ld/macho.go @@ -703,11 +703,11 @@ func machosymtab() { Addstring(symstr, s.Extname) } else { for p = s.Extname; p != ""; p = p[1:] { - if uint8(p[0]) == 0xc2 && uint8((p[1:])[0]) == 0xb7 { + if p[0] == 0xc2 && (p[1:])[0] == 0xb7 { Adduint8(Ctxt, symstr, '.') p = p[1:] } else { - Adduint8(Ctxt, symstr, uint8(p[0])) + Adduint8(Ctxt, symstr, p[0]) } } diff --git a/src/cmd/link/internal/ld/objfile.go b/src/cmd/link/internal/ld/objfile.go index b4d2a2184f..dffb7a3d9b 100644 --- a/src/cmd/link/internal/ld/objfile.go +++ b/src/cmd/link/internal/ld/objfile.go @@ -472,7 +472,7 @@ func (r *objReader) readInt64() int64 { } } - return int64(uv>>1) ^ (int64(uint64(uv)<<63) >> 63) + return int64(uv>>1) ^ (int64(uv<<63) >> 63) } func (r *objReader) readInt() int { diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 74ef8c2929..345eaa1ac2 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -179,7 +179,7 @@ func renumberfiles(ctxt *Link, files []*LSym, d *Pcdata) { dv = val - newval newval = val - v = (uint32(dv) << 1) ^ uint32(int32(dv>>31)) + v = (uint32(dv) << 1) ^ uint32(dv>>31) addvarint(&out, v) // pc delta @@ -378,7 +378,7 @@ func pclntab() { ftab.Size = int64(len(ftab.P)) if Debug['v'] != 0 { - fmt.Fprintf(Bso, "%5.2f pclntab=%d bytes, funcdata total %d bytes\n", obj.Cputime(), int64(ftab.Size), int64(funcdata_bytes)) + fmt.Fprintf(Bso, "%5.2f pclntab=%d bytes, funcdata total %d bytes\n", obj.Cputime(), ftab.Size, funcdata_bytes) } } diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 0204b8c8c2..8985c40588 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -877,7 +877,7 @@ func peemitreloc(text, data, ctors *IMAGE_SECTION_HEADER) { ctors.NumberOfRelocations = 1 ctors.PointerToRelocations = uint32(Cpos()) sectoff := ctors.VirtualAddress - Lputl(uint32(sectoff)) + Lputl(sectoff) Lputl(uint32(dottext.Dynid)) switch obj.Getgoarch() { default: @@ -1043,7 +1043,7 @@ func addpesymtable() { // write COFF string table Lputl(uint32(len(strtbl)) + 4) for i := 0; i < len(strtbl); i++ { - Cput(uint8(strtbl[i])) + Cput(strtbl[i]) } if Linkmode != LinkExternal { strnput("", int(h.SizeOfRawData-uint32(size))) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 60bec0d6c9..96e8de5030 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -236,10 +236,10 @@ func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ var i int if t == 'z' || t == 'Z' { - Cput(uint8(s[0])) + Cput(s[0]) for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 { - Cput(uint8(s[i])) - Cput(uint8(s[i+1])) + Cput(s[i]) + Cput(s[i+1]) } Cput(0) @@ -251,7 +251,7 @@ func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ s = s[1:] } for i = 0; i < len(s); i++ { - Cput(uint8(s[i])) + Cput(s[i]) } Cput(0) } diff --git a/src/cmd/link/internal/mips64/asm.go b/src/cmd/link/internal/mips64/asm.go index ad6a1f7524..785002b02c 100644 --- a/src/cmd/link/internal/mips64/asm.go +++ b/src/cmd/link/internal/mips64/asm.go @@ -193,7 +193,7 @@ func asmb() { if sym != nil { ld.Lcsize = int32(len(sym.P)) for i := 0; int32(i) < ld.Lcsize; i++ { - ld.Cput(uint8(sym.P[i])) + ld.Cput(sym.P[i]) } ld.Cflush() @@ -214,7 +214,7 @@ func asmb() { if ld.SysArch == sys.ArchMIPS64LE { magic = uint32(4*26*26 + 7) } - ld.Thearch.Lput(uint32(magic)) /* magic */ + ld.Thearch.Lput(magic) /* magic */ ld.Thearch.Lput(uint32(ld.Segtext.Filelen)) /* sizes */ ld.Thearch.Lput(uint32(ld.Segdata.Filelen)) ld.Thearch.Lput(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index 3970f3c5f9..562e0810e0 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -913,7 +913,7 @@ func asmb() { if sym != nil { ld.Lcsize = int32(len(sym.P)) for i := 0; int32(i) < ld.Lcsize; i++ { - ld.Cput(uint8(sym.P[i])) + ld.Cput(sym.P[i]) } ld.Cflush() diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go index 19a8917ec8..5231ad1f6c 100644 --- a/src/cmd/link/internal/x86/asm.go +++ b/src/cmd/link/internal/x86/asm.go @@ -699,7 +699,7 @@ func asmb() { if sym != nil { ld.Lcsize = int32(len(sym.P)) for i := 0; int32(i) < ld.Lcsize; i++ { - ld.Cput(uint8(sym.P[i])) + ld.Cput(sym.P[i]) } ld.Cflush() diff --git a/src/cmd/vet/structtag.go b/src/cmd/vet/structtag.go index e8164a46f9..abff14fb1d 100644 --- a/src/cmd/vet/structtag.go +++ b/src/cmd/vet/structtag.go @@ -111,7 +111,7 @@ func validateStructTag(tag string) error { if i >= len(tag) { return errTagValueSyntax } - qvalue := string(tag[:i+1]) + qvalue := tag[:i+1] tag = tag[i+1:] if _, err := strconv.Unquote(qvalue); err != nil { -- cgit v1.3 From 106b9d391518fe382162559e1520a8af72564130 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 14 Apr 2016 19:44:55 -0700 Subject: cmd/internal/obj, cmd/link: random style cleanups Identified during review of golang.org/cl/22103. Change-Id: I86bab4cc17204df1e45deefdb0d0f9a8f6e17073 Reviewed-on: https://go-review.googlesource.com/22106 Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- src/cmd/internal/obj/pcln.go | 13 ++++++------- src/cmd/link/internal/ld/macho.go | 23 +++-------------------- 2 files changed, 9 insertions(+), 27 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/internal/obj/pcln.go b/src/cmd/internal/obj/pcln.go index a086be9f66..b1536eb224 100644 --- a/src/cmd/internal/obj/pcln.go +++ b/src/cmd/internal/obj/pcln.go @@ -158,19 +158,18 @@ func pctofileline(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg return int32(pcln.Lastindex) } - var i int32 - for i = 0; i < int32(len(pcln.File)); i++ { - file := pcln.File[i] + for i, file := range pcln.File { if file == f { pcln.Lastfile = f - pcln.Lastindex = int(i) - return i + pcln.Lastindex = i + return int32(i) } } + i := len(pcln.File) pcln.File = append(pcln.File, f) pcln.Lastfile = f - pcln.Lastindex = int(i) - return i + pcln.Lastindex = i + return int32(i) } // pctospadj computes the sp adjustment in effect. diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index 46cce4c331..e7d9fb5fe4 100644 --- a/src/cmd/link/internal/ld/macho.go +++ b/src/cmd/link/internal/ld/macho.go @@ -682,15 +682,11 @@ func machosymorder() { } func machosymtab() { - var s *LSym - var o *LSym - var p string - symtab := Linklookup(Ctxt, ".machosymtab", 0) symstr := Linklookup(Ctxt, ".machosymstr", 0) for i := 0; i < nsortsym; i++ { - s = sortsym[i] + s := sortsym[i] Adduint32(Ctxt, symtab, uint32(symstr.Size)) // Only add _ to C symbols. Go symbols have dot in the name. @@ -699,20 +695,7 @@ func machosymtab() { } // replace "·" as ".", because DTrace cannot handle it. - if !strings.Contains(s.Extname, "·") { - Addstring(symstr, s.Extname) - } else { - for p = s.Extname; p != ""; p = p[1:] { - if p[0] == 0xc2 && (p[1:])[0] == 0xb7 { - Adduint8(Ctxt, symstr, '.') - p = p[1:] - } else { - Adduint8(Ctxt, symstr, p[0]) - } - } - - Adduint8(Ctxt, symstr, '\x00') - } + Addstring(symstr, strings.Replace(s.Extname, "·", ".", -1)) if s.Type == obj.SDYNIMPORT || s.Type == obj.SHOSTOBJ { Adduint8(Ctxt, symtab, 0x01) // type N_EXT, external symbol @@ -725,7 +708,7 @@ func machosymtab() { } else { Adduint8(Ctxt, symtab, 0x0e) } - o = s + o := s for o.Outer != nil { o = o.Outer } -- cgit v1.3 From 6b02a1924725688b4d264065454ac5287fbed535 Mon Sep 17 00:00:00 2001 From: Ilya Tocar Date: Thu, 21 Apr 2016 18:24:12 +0300 Subject: strings: use SSE4.2 in strings.Index on AMD64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use PCMPESTRI instruction if available. Index-4 21.1ns ± 0% 21.1ns ± 0% ~ (all samples are equal) IndexHard1-4 395µs ± 0% 105µs ± 0% -73.53% (p=0.000 n=19+20) IndexHard2-4 300µs ± 0% 147µs ± 0% -51.11% (p=0.000 n=19+20) IndexHard3-4 665µs ± 0% 665µs ± 0% ~ (p=0.942 n=16+19) Change-Id: I4f66794164740a2b939eb1c78934e2390b489064 Reviewed-on: https://go-review.googlesource.com/22337 Run-TryBot: Ilya Tocar TryBot-Result: Gobot Gobot Reviewed-by: Russ Cox --- src/cmd/internal/obj/x86/a.out.go | 2 + src/cmd/internal/obj/x86/anames.go | 1 + src/cmd/internal/obj/x86/asm6.go | 1 + src/runtime/asm_amd64.s | 157 +++++++++++++++++++++++-------------- 4 files changed, 103 insertions(+), 58 deletions(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/internal/obj/x86/a.out.go b/src/cmd/internal/obj/x86/a.out.go index 64bd865e42..c41fd953e7 100644 --- a/src/cmd/internal/obj/x86/a.out.go +++ b/src/cmd/internal/obj/x86/a.out.go @@ -739,6 +739,8 @@ const ( AUNPCKLPS AXORPD AXORPS + APCMPESTRI + ARETFW ARETFL ARETFQ diff --git a/src/cmd/internal/obj/x86/anames.go b/src/cmd/internal/obj/x86/anames.go index 3b59e2f36f..e3fef54e71 100644 --- a/src/cmd/internal/obj/x86/anames.go +++ b/src/cmd/internal/obj/x86/anames.go @@ -682,6 +682,7 @@ var Anames = []string{ "UNPCKLPS", "XORPD", "XORPS", + "PCMPESTRI", "RETFW", "RETFL", "RETFQ", diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index 57ef045b98..1c7fcf37be 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -1648,6 +1648,7 @@ var optab = {AROUNDSS, yaes2, Pq, [23]uint8{0x3a, 0x0a, 0}}, {APSHUFD, yxshuf, Pq, [23]uint8{0x70, 0}}, {APCLMULQDQ, yxshuf, Pq, [23]uint8{0x3a, 0x44, 0}}, + {APCMPESTRI, yxshuf, Pq, [23]uint8{0x3a, 0x61, 0}}, {AANDNL, yvex_r3, Pvex, [23]uint8{VEX_LZ_0F38_W0, 0xF2}}, {AANDNQ, yvex_r3, Pvex, [23]uint8{VEX_LZ_0F38_W1, 0xF2}}, diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 83db4d3e81..cdda29f347 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -1666,122 +1666,126 @@ big_loop_avx2_exit: // TODO: Also use this in bytes.Index TEXT strings·indexShortStr(SB),NOSPLIT,$0-40 MOVQ s+0(FP), DI - MOVQ s_len+8(FP), CX - MOVQ c+16(FP), AX - MOVQ c_len+24(FP), BX - CMPQ BX, CX + // We want len in DX and AX, because PCMPESTRI implicitly consumes them + MOVQ s_len+8(FP), DX + MOVQ c+16(FP), BP + MOVQ c_len+24(FP), AX + CMPQ AX, DX JA fail - CMPQ BX, $2 + CMPQ DX, $16 + JAE sse42 +no_sse42: + CMPQ AX, $2 JA _3_or_more - MOVW (AX), AX - LEAQ -1(DI)(CX*1), CX + MOVW (BP), BP + LEAQ -1(DI)(DX*1), DX loop2: MOVW (DI), SI - CMPW SI,AX + CMPW SI,BP JZ success ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop2 JMP fail _3_or_more: - CMPQ BX, $3 + CMPQ AX, $3 JA _4_or_more - MOVW 1(AX), DX - MOVW (AX), AX - LEAQ -2(DI)(CX*1), CX + MOVW 1(BP), BX + MOVW (BP), BP + LEAQ -2(DI)(DX*1), DX loop3: MOVW (DI), SI - CMPW SI,AX + CMPW SI,BP JZ partial_success3 ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop3 JMP fail partial_success3: MOVW 1(DI), SI - CMPW SI,DX + CMPW SI,BX JZ success ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop3 JMP fail _4_or_more: - CMPQ BX, $4 + CMPQ AX, $4 JA _5_or_more - MOVL (AX), AX - LEAQ -3(DI)(CX*1), CX + MOVL (BP), BP + LEAQ -3(DI)(DX*1), DX loop4: MOVL (DI), SI - CMPL SI,AX + CMPL SI,BP JZ success ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop4 JMP fail _5_or_more: - CMPQ BX, $7 + CMPQ AX, $7 JA _8_or_more - LEAQ 1(DI)(CX*1), CX - SUBQ BX, CX - MOVL -4(AX)(BX*1), DX - MOVL (AX), AX + LEAQ 1(DI)(DX*1), DX + SUBQ AX, DX + MOVL -4(BP)(AX*1), BX + MOVL (BP), BP loop5to7: MOVL (DI), SI - CMPL SI,AX + CMPL SI,BP JZ partial_success5to7 ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop5to7 JMP fail partial_success5to7: - MOVL -4(BX)(DI*1), SI - CMPL SI,DX + MOVL -4(AX)(DI*1), SI + CMPL SI,BX JZ success ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop5to7 JMP fail _8_or_more: - CMPQ BX, $8 + CMPQ AX, $8 JA _9_or_more - MOVQ (AX), AX - LEAQ -7(DI)(CX*1), CX + MOVQ (BP), BP + LEAQ -7(DI)(DX*1), DX loop8: MOVQ (DI), SI - CMPQ SI,AX + CMPQ SI,BP JZ success ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop8 JMP fail _9_or_more: - CMPQ BX, $16 + CMPQ AX, $16 JA _16_or_more - LEAQ 1(DI)(CX*1), CX - SUBQ BX, CX - MOVQ -8(AX)(BX*1), DX - MOVQ (AX), AX + LEAQ 1(DI)(DX*1), DX + SUBQ AX, DX + MOVQ -8(BP)(AX*1), BX + MOVQ (BP), BP loop9to15: MOVQ (DI), SI - CMPQ SI,AX + CMPQ SI,BP JZ partial_success9to15 ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop9to15 JMP fail partial_success9to15: - MOVQ -8(BX)(DI*1), SI - CMPQ SI,DX + MOVQ -8(AX)(DI*1), SI + CMPQ SI,BX JZ success ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop9to15 JMP fail _16_or_more: - CMPQ BX, $16 + CMPQ AX, $17 JA _17_to_31 - MOVOU (AX), X1 - LEAQ -15(DI)(CX*1), CX + MOVOU (BP), X1 + LEAQ -15(DI)(DX*1), DX loop16: MOVOU (DI), X2 PCMPEQB X1, X2 @@ -1789,14 +1793,14 @@ loop16: CMPQ SI, $0xffff JE success ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop16 JMP fail _17_to_31: - LEAQ 1(DI)(CX*1), CX - SUBQ BX, CX - MOVOU -16(AX)(BX*1), X0 - MOVOU (AX), X1 + LEAQ 1(DI)(DX*1), DX + SUBQ AX, DX + MOVOU -16(BP)(AX*1), X0 + MOVOU (BP), X1 loop17to31: MOVOU (DI), X2 PCMPEQB X1,X2 @@ -1804,21 +1808,58 @@ loop17to31: CMPQ SI, $0xffff JE partial_success17to31 ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop17to31 JMP fail partial_success17to31: - MOVOU -16(BX)(DI*1), X3 + MOVOU -16(AX)(DI*1), X3 PCMPEQB X0, X3 PMOVMSKB X3, SI CMPQ SI, $0xffff JE success ADDQ $1,DI - CMPQ DI,CX + CMPQ DI,DX JB loop17to31 fail: MOVQ $-1, ret+32(FP) RET +sse42: + MOVL runtime·cpuid_ecx(SB), CX + ANDL $0x100000, CX + JZ no_sse42 + CMPQ AX, $12 + // PCMPESTRI is slower than normal compare, + // so using it makes sense only if we advance 4+ bytes per compare + // This value was determined experimentally and is the ~same + // on Nehalem (first with SSE42) and Haswell. + JAE _9_or_more + LEAQ 16(BP), SI + TESTW $0xff0, SI + JEQ no_sse42 + MOVOU (BP), X1 + LEAQ -15(DI)(DX*1), SI + MOVQ $16, R9 + SUBQ AX, R9 // We advance by 16-len(sep) each iteration, so precalculate it into R9 +loop_sse42: + // 0x0c means: unsigned byte compare (bits 0,1 are 00) + // for equality (bits 2,3 are 11) + // result is not masked or inverted (bits 4,5 are 00) + // and corresponds to first matching byte (bit 6 is 0) + PCMPESTRI $0x0c, (DI), X1 + // CX == 16 means no match, + // CX > R9 means partial match at the end of the string, + // otherwise sep is at offset CX from X1 start + CMPQ CX, R9 + JBE sse42_success + ADDQ R9, DI + CMPQ DI, SI + JB loop_sse42 + PCMPESTRI $0x0c, -1(SI), X1 + CMPQ CX, R9 + JA fail + LEAQ -1(SI), DI +sse42_success: + ADDQ CX, DI success: SUBQ s+0(FP), DI MOVQ DI, ret+32(FP) -- cgit v1.3 From c9389a101b020b41a954ac35642ec254c8344238 Mon Sep 17 00:00:00 2001 From: Zhongwei Yao Date: Thu, 31 Mar 2016 15:34:12 +0800 Subject: cmd/asm: fix SIMD register name on arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current V-register range is V32~V63 on arm64. This patch changes it to V0~V31. fix #15465. Change-Id: I90dab42dea46825ec5d7a8321ec4f6550735feb8 Reviewed-on: https://go-review.googlesource.com/22520 Reviewed-by: Aram Hăvărneanu Run-TryBot: Aram Hăvărneanu TryBot-Result: Gobot Gobot --- src/cmd/internal/obj/arm64/list7.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/internal/obj/arm64/list7.go b/src/cmd/internal/obj/arm64/list7.go index 36f544b53a..ad9ff0965c 100644 --- a/src/cmd/internal/obj/arm64/list7.go +++ b/src/cmd/internal/obj/arm64/list7.go @@ -71,7 +71,7 @@ func Rconv(r int) string { case REG_F0 <= r && r <= REG_F31: return fmt.Sprintf("F%d", r-REG_F0) case REG_V0 <= r && r <= REG_V31: - return fmt.Sprintf("V%d", r-REG_F0) + return fmt.Sprintf("V%d", r-REG_V0) case COND_EQ <= r && r <= COND_NV: return strcond[r-COND_EQ] case r == REGSP: -- cgit v1.3 From 74a9bad63899ffb02b747678c2c181ffb13983b9 Mon Sep 17 00:00:00 2001 From: Zhongwei Yao Date: Mon, 25 Apr 2016 11:08:38 +0800 Subject: cmd/compile: enable const division for arm64 performance: benchmark old ns/op new ns/op delta BenchmarkDivconstI64-8 8.28 2.70 -67.39% BenchmarkDivconstU64-8 8.28 4.69 -43.36% BenchmarkDivconstI32-8 8.28 6.39 -22.83% BenchmarkDivconstU32-8 8.28 4.43 -46.50% BenchmarkDivconstI16-8 5.17 5.17 +0.00% BenchmarkDivconstU16-8 5.33 5.34 +0.19% BenchmarkDivconstI8-8 3.50 3.50 +0.00% BenchmarkDivconstU8-8 3.51 3.50 -0.28% Fixes #15382 Change-Id: Ibce7b28f0586d593b33c4d4ecc5d5e7e7c905d13 Reviewed-on: https://go-review.googlesource.com/22292 Reviewed-by: Michael Munday Reviewed-by: David Chase --- src/cmd/compile/internal/arm64/galign.go | 2 + src/cmd/compile/internal/arm64/ggen.go | 47 ++++++++++++++++++++ src/cmd/compile/internal/arm64/gsubr.go | 12 ------ src/cmd/compile/internal/arm64/peep.go | 3 ++ src/cmd/compile/internal/arm64/prog.go | 3 ++ src/cmd/compile/internal/gc/cgen.go | 49 +++++++++++++++++---- src/cmd/compile/internal/gc/go.go | 36 ++++++++-------- src/cmd/compile/internal/gc/walk.go | 12 +++++- src/cmd/internal/obj/arm64/asm7.go | 4 ++ src/runtime/vlrt.go | 1 - test/bench/go1/divconst_test.go | 73 ++++++++++++++++++++++++++++++++ 11 files changed, 202 insertions(+), 40 deletions(-) create mode 100644 test/bench/go1/divconst_test.go (limited to 'src/cmd/internal/obj') diff --git a/src/cmd/compile/internal/arm64/galign.go b/src/cmd/compile/internal/arm64/galign.go index 17c851cb14..7acc4e08eb 100644 --- a/src/cmd/compile/internal/arm64/galign.go +++ b/src/cmd/compile/internal/arm64/galign.go @@ -29,6 +29,8 @@ func Main() { gc.Thearch.Betypeinit = betypeinit gc.Thearch.Cgen_hmul = cgen_hmul + gc.Thearch.AddSetCarry = AddSetCarry + gc.Thearch.RightShiftWithCarry = RightShiftWithCarry gc.Thearch.Cgen_shift = cgen_shift gc.Thearch.Clearfat = clearfat gc.Thearch.Defframe = defframe diff --git a/src/cmd/compile/internal/arm64/ggen.go b/src/cmd/compile/internal/arm64/ggen.go index 9abd901d7a..bddfed631a 100644 --- a/src/cmd/compile/internal/arm64/ggen.go +++ b/src/cmd/compile/internal/arm64/ggen.go @@ -252,6 +252,53 @@ func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) { } } +// RightShiftWithCarry generates a constant unsigned +// right shift with carry. +// +// res = n >> shift // with carry +func RightShiftWithCarry(n *gc.Node, shift uint, res *gc.Node) { + // Extra 1 is for carry bit. + maxshift := uint(n.Type.Width*8 + 1) + if shift == 0 { + gmove(n, res) + } else if shift < maxshift { + // 1. clear rightmost bit of target + var n1 gc.Node + gc.Nodconst(&n1, n.Type, 1) + gins(optoas(gc.ORSH, n.Type), &n1, n) + gins(optoas(gc.OLSH, n.Type), &n1, n) + // 2. add carry flag to target + var n2 gc.Node + gc.Nodconst(&n1, n.Type, 0) + gc.Regalloc(&n2, n.Type, nil) + gins(optoas(gc.OAS, n.Type), &n1, &n2) + gins(arm64.AADC, &n2, n) + // 3. right rotate 1 bit + gc.Nodconst(&n1, n.Type, 1) + gins(arm64.AROR, &n1, n) + + // ARM64 backend doesn't eliminate shifts by 0. It is manually checked here. + if shift > 1 { + var n3 gc.Node + gc.Nodconst(&n3, n.Type, int64(shift-1)) + cgen_shift(gc.ORSH, true, n, &n3, res) + } else { + gmove(n, res) + } + gc.Regfree(&n2) + } else { + gc.Fatalf("RightShiftWithCarry: shift(%v) is bigger than max size(%v)", shift, maxshift) + } +} + +// AddSetCarry generates add and set carry. +// +// res = nl + nr // with carry flag set +func AddSetCarry(nl *gc.Node, nr *gc.Node, res *gc.Node) { + gins(arm64.AADDS, nl, nr) + gmove(nr, res) +} + /* * generate high multiply: * res = (nl*nr) >> width diff --git a/src/cmd/compile/internal/arm64/gsubr.go b/src/cmd/compile/internal/arm64/gsubr.go index efa66a09d3..f193291d01 100644 --- a/src/cmd/compile/internal/arm64/gsubr.go +++ b/src/cmd/compile/internal/arm64/gsubr.go @@ -890,18 +890,6 @@ func optoas(op gc.Op, t *gc.Type) obj.As { ORSH_ | gc.TINT64: a = arm64.AASR - // TODO(minux): handle rotates - //case CASE(ORROTC, TINT8): - //case CASE(ORROTC, TUINT8): - //case CASE(ORROTC, TINT16): - //case CASE(ORROTC, TUINT16): - //case CASE(ORROTC, TINT32): - //case CASE(ORROTC, TUINT32): - //case CASE(ORROTC, TINT64): - //case CASE(ORROTC, TUINT64): - // a = 0//??? RLDC?? - // break; - case OHMUL_ | gc.TINT64: a = arm64.ASMULH diff --git a/src/cmd/compile/internal/arm64/peep.go b/src/cmd/compile/internal/arm64/peep.go index 887353c889..22be1afebc 100644 --- a/src/cmd/compile/internal/arm64/peep.go +++ b/src/cmd/compile/internal/arm64/peep.go @@ -534,10 +534,13 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int { return 0 case arm64.AADD, /* read p->from, read p->reg, write p->to */ + arm64.AADDS, arm64.ASUB, + arm64.AADC, arm64.AAND, arm64.AORR, arm64.AEOR, + arm64.AROR, arm64.AMUL, arm64.ASMULL, arm64.AUMULL, diff --git a/src/cmd/compile/internal/arm64/prog.go b/src/cmd/compile/internal/arm64/prog.go index 3091c4a840..d504d0f0ee 100644 --- a/src/cmd/compile/internal/arm64/prog.go +++ b/src/cmd/compile/internal/arm64/prog.go @@ -59,6 +59,9 @@ var progtable = [arm64.ALAST & obj.AMask]obj.ProgInfo{ arm64.ALSR & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite}, arm64.AASR & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite}, arm64.ACMP & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead}, + arm64.AADC & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite | gc.UseCarry}, + arm64.AROR & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite}, + arm64.AADDS & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite | gc.SetCarry}, // Floating point. arm64.AFADDD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite}, diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go index bb7487c958..8db752ec51 100644 --- a/src/cmd/compile/internal/gc/cgen.go +++ b/src/cmd/compile/internal/gc/cgen.go @@ -2642,9 +2642,9 @@ func cgen_ret(n *Node) { // signed and unsigned high multiplication (OHMUL). func hasHMUL64() bool { switch Ctxt.Arch.Family { - case sys.AMD64, sys.S390X: + case sys.AMD64, sys.S390X, sys.ARM64: return true - case sys.ARM, sys.ARM64, sys.I386, sys.MIPS64, sys.PPC64: + case sys.ARM, sys.I386, sys.MIPS64, sys.PPC64: return false } Fatalf("unknown architecture") @@ -2664,6 +2664,28 @@ func hasRROTC64() bool { return false } +func hasRightShiftWithCarry() bool { + switch Ctxt.Arch.Family { + case sys.ARM64: + return true + case sys.AMD64, sys.ARM, sys.I386, sys.MIPS64, sys.PPC64, sys.S390X: + return false + } + Fatalf("unknown architecture") + return false +} + +func hasAddSetCarry() bool { + switch Ctxt.Arch.Family { + case sys.ARM64: + return true + case sys.AMD64, sys.ARM, sys.I386, sys.MIPS64, sys.PPC64, sys.S390X: + return false + } + Fatalf("unknown architecture") + return false +} + // generate division according to op, one of: // res = nl / nr // res = nl % nr @@ -2699,8 +2721,9 @@ func cgen_div(op Op, nl *Node, nr *Node, res *Node) { // the MSB. For now this needs the RROTC instruction. // TODO(mundaym): Hacker's Delight 2nd ed. chapter 10 proposes // an alternative sequence of instructions for architectures - // that do not have a shift right with carry instruction. - if m.Ua != 0 && !hasRROTC64() { + // (TODO: MIPS64, PPC64, S390X) that do not have a shift + // right with carry instruction. + if m.Ua != 0 && !hasRROTC64() && !hasRightShiftWithCarry() { goto longdiv } if op == OMOD { @@ -2717,12 +2740,20 @@ func cgen_div(op Op, nl *Node, nr *Node, res *Node) { if m.Ua != 0 { // Need to add numerator accounting for overflow. - Thearch.Gins(Thearch.Optoas(OADD, nl.Type), &n1, &n3) + if hasAddSetCarry() { + Thearch.AddSetCarry(&n1, &n3, &n3) + } else { + Thearch.Gins(Thearch.Optoas(OADD, nl.Type), &n1, &n3) + } - Nodconst(&n2, nl.Type, 1) - Thearch.Gins(Thearch.Optoas(ORROTC, nl.Type), &n2, &n3) - Nodconst(&n2, nl.Type, int64(m.S)-1) - Thearch.Gins(Thearch.Optoas(ORSH, nl.Type), &n2, &n3) + if !hasRROTC64() { + Thearch.RightShiftWithCarry(&n3, uint(m.S), &n3) + } else { + Nodconst(&n2, nl.Type, 1) + Thearch.Gins(Thearch.Optoas(ORROTC, nl.Type), &n2, &n3) + Nodconst(&n2, nl.Type, int64(m.S)-1) + Thearch.Gins(Thearch.Optoas(ORSH, nl.Type), &n2, &n3) + } } else { Nodconst(&n2, nl.Type, int64(m.S)) Thearch.Gins(Thearch.Optoas(ORSH, nl.Type), &n2, &n3) // shift dx diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index 87b6121c8e..f9a372dcce 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -378,23 +378,25 @@ type Arch struct { MAXWIDTH int64 ReservedRegs []int - AddIndex func(*Node, int64, *Node) bool // optional - Betypeinit func() - Bgen_float func(*Node, bool, int, *obj.Prog) // optional - Cgen64 func(*Node, *Node) // only on 32-bit systems - Cgenindex func(*Node, *Node, bool) *obj.Prog - Cgen_bmul func(Op, *Node, *Node, *Node) bool - Cgen_float func(*Node, *Node) // optional - Cgen_hmul func(*Node, *Node, *Node) - Cgen_shift func(Op, bool, *Node, *Node, *Node) - Clearfat func(*Node) - Cmp64 func(*Node, *Node, Op, int, *obj.Prog) // only on 32-bit systems - Defframe func(*obj.Prog) - Dodiv func(Op, *Node, *Node, *Node) - Excise func(*Flow) - Expandchecks func(*obj.Prog) - Getg func(*Node) - Gins func(obj.As, *Node, *Node) *obj.Prog + AddIndex func(*Node, int64, *Node) bool // optional + Betypeinit func() + Bgen_float func(*Node, bool, int, *obj.Prog) // optional + Cgen64 func(*Node, *Node) // only on 32-bit systems + Cgenindex func(*Node, *Node, bool) *obj.Prog + Cgen_bmul func(Op, *Node, *Node, *Node) bool + Cgen_float func(*Node, *Node) // optional + Cgen_hmul func(*Node, *Node, *Node) + RightShiftWithCarry func(*Node, uint, *Node) // only on systems without RROTC instruction + AddSetCarry func(*Node, *Node, *Node) // only on systems when ADD does not update carry flag + Cgen_shift func(Op, bool, *Node, *Node, *Node) + Clearfat func(*Node) + Cmp64 func(*Node, *Node, Op, int, *obj.Prog) // only on 32-bit systems + Defframe func(*obj.Prog) + Dodiv func(Op, *Node, *Node, *Node) + Excise func(*Flow) + Expandchecks func(*obj.Prog) + Getg func(*Node) + Gins func(obj.As, *Node, *Node) *obj.Prog // Ginscmp generates code comparing n1 to n2 and jumping away if op is satisfied. // The returned prog should be Patch'ed with the jump target. diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index bce34374e8..cc9a50e6a8 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -3424,7 +3424,7 @@ func walkdiv(n *Node, init *Nodes) *Node { // if >= 0, nr is 1<