github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/obj.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/gc/obj.go 2 3 // Copyright 2009 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 package gc 8 9 import ( 10 "rsc.io/tmp/bootstrap/internal/obj" 11 "fmt" 12 "strconv" 13 ) 14 15 /* 16 * architecture-independent object file output 17 */ 18 const ( 19 ArhdrSize = 60 20 ) 21 22 func formathdr(arhdr []byte, name string, size int64) { 23 copy(arhdr[:], fmt.Sprintf("%-16s%-12d%-6d%-6d%-8o%-10d`\n", name, 0, 0, 0, 0644, size)) 24 } 25 26 func dumpobj() { 27 var err error 28 bout, err = obj.Bopenw(outfile) 29 if err != nil { 30 Flusherrors() 31 fmt.Printf("can't create %s: %v\n", outfile, err) 32 errorexit() 33 } 34 35 startobj := int64(0) 36 var arhdr [ArhdrSize]byte 37 if writearchive != 0 { 38 obj.Bwritestring(bout, "!<arch>\n") 39 arhdr = [ArhdrSize]byte{} 40 obj.Bwrite(bout, arhdr[:]) 41 startobj = obj.Boffset(bout) 42 } 43 44 fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) 45 dumpexport() 46 47 if writearchive != 0 { 48 obj.Bflush(bout) 49 size := obj.Boffset(bout) - startobj 50 if size&1 != 0 { 51 obj.Bputc(bout, 0) 52 } 53 obj.Bseek(bout, startobj-ArhdrSize, 0) 54 formathdr(arhdr[:], "__.PKGDEF", size) 55 obj.Bwrite(bout, arhdr[:]) 56 obj.Bflush(bout) 57 58 obj.Bseek(bout, startobj+size+(size&1), 0) 59 arhdr = [ArhdrSize]byte{} 60 obj.Bwrite(bout, arhdr[:]) 61 startobj = obj.Boffset(bout) 62 fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) 63 } 64 65 if pragcgobuf != "" { 66 if writearchive != 0 { 67 // write empty export section; must be before cgo section 68 fmt.Fprintf(bout, "\n$$\n\n$$\n\n") 69 } 70 71 fmt.Fprintf(bout, "\n$$ // cgo\n") 72 fmt.Fprintf(bout, "%s\n$$\n\n", pragcgobuf) 73 } 74 75 fmt.Fprintf(bout, "\n!\n") 76 77 var externs *NodeList 78 if externdcl != nil { 79 externs = externdcl.End 80 } 81 82 dumpglobls() 83 dumptypestructs() 84 85 // Dump extra globals. 86 tmp := externdcl 87 88 if externs != nil { 89 externdcl = externs.Next 90 } 91 dumpglobls() 92 externdcl = tmp 93 94 zero := Pkglookup("zerovalue", Runtimepkg) 95 ggloblsym(zero, int32(zerosize), obj.DUPOK|obj.RODATA) 96 97 dumpdata() 98 obj.Writeobjdirect(Ctxt, bout) 99 100 if writearchive != 0 { 101 obj.Bflush(bout) 102 size := obj.Boffset(bout) - startobj 103 if size&1 != 0 { 104 obj.Bputc(bout, 0) 105 } 106 obj.Bseek(bout, startobj-ArhdrSize, 0) 107 name := fmt.Sprintf("_go_.%c", Thearch.Thechar) 108 formathdr(arhdr[:], name, size) 109 obj.Bwrite(bout, arhdr[:]) 110 } 111 112 obj.Bterm(bout) 113 } 114 115 func dumpglobls() { 116 var n *Node 117 118 // add globals 119 for l := externdcl; l != nil; l = l.Next { 120 n = l.N 121 if n.Op != ONAME { 122 continue 123 } 124 125 if n.Type == nil { 126 Fatal("external %v nil type\n", n) 127 } 128 if n.Class == PFUNC { 129 continue 130 } 131 if n.Sym.Pkg != localpkg { 132 continue 133 } 134 dowidth(n.Type) 135 136 ggloblnod(n) 137 } 138 139 for l := funcsyms; l != nil; l = l.Next { 140 n = l.N 141 dsymptr(n.Sym, 0, n.Sym.Def.Func.Shortname.Sym, 0) 142 ggloblsym(n.Sym, int32(Widthptr), obj.DUPOK|obj.RODATA) 143 } 144 145 // Do not reprocess funcsyms on next dumpglobls call. 146 funcsyms = nil 147 } 148 149 func Bputname(b *obj.Biobuf, s *obj.LSym) { 150 obj.Bwritestring(b, s.Name) 151 obj.Bputc(b, 0) 152 } 153 154 func Linksym(s *Sym) *obj.LSym { 155 if s == nil { 156 return nil 157 } 158 if s.Lsym != nil { 159 return s.Lsym 160 } 161 var name string 162 if isblanksym(s) { 163 name = "_" 164 } else if s.Linkname != "" { 165 name = s.Linkname 166 } else { 167 name = s.Pkg.Prefix + "." + s.Name 168 } 169 170 ls := obj.Linklookup(Ctxt, name, 0) 171 s.Lsym = ls 172 return ls 173 } 174 175 func duintxx(s *Sym, off int, v uint64, wid int) int { 176 // Update symbol data directly instead of generating a 177 // DATA instruction that liblink will have to interpret later. 178 // This reduces compilation time and memory usage. 179 off = int(Rnd(int64(off), int64(wid))) 180 181 return int(obj.Setuintxx(Ctxt, Linksym(s), int64(off), v, int64(wid))) 182 } 183 184 func duint8(s *Sym, off int, v uint8) int { 185 return duintxx(s, off, uint64(v), 1) 186 } 187 188 func duint16(s *Sym, off int, v uint16) int { 189 return duintxx(s, off, uint64(v), 2) 190 } 191 192 func duint32(s *Sym, off int, v uint32) int { 193 return duintxx(s, off, uint64(v), 4) 194 } 195 196 func duint64(s *Sym, off int, v uint64) int { 197 return duintxx(s, off, v, 8) 198 } 199 200 func duintptr(s *Sym, off int, v uint64) int { 201 return duintxx(s, off, v, Widthptr) 202 } 203 204 var stringsym_gen int 205 206 func stringsym(s string) *Sym { 207 var symname string 208 var pkg *Pkg 209 if len(s) > 100 { 210 // huge strings are made static to avoid long names 211 stringsym_gen++ 212 symname = fmt.Sprintf(".gostring.%d", stringsym_gen) 213 214 pkg = localpkg 215 } else { 216 // small strings get named by their contents, 217 // so that multiple modules using the same string 218 // can share it. 219 symname = strconv.Quote(s) 220 pkg = gostringpkg 221 } 222 223 sym := Pkglookup(symname, pkg) 224 225 // SymUniq flag indicates that data is generated already 226 if sym.Flags&SymUniq != 0 { 227 return sym 228 } 229 sym.Flags |= SymUniq 230 sym.Def = newname(sym) 231 232 off := 0 233 234 // string header 235 off = dsymptr(sym, off, sym, Widthptr+Widthint) 236 off = duintxx(sym, off, uint64(len(s)), Widthint) 237 238 // string data 239 var m int 240 for n := 0; n < len(s); n += m { 241 m = 8 242 if m > len(s)-n { 243 m = len(s) - n 244 } 245 off = dsname(sym, off, s[n:n+m]) 246 } 247 248 off = duint8(sym, off, 0) // terminating NUL for runtime 249 off = (off + Widthptr - 1) &^ (Widthptr - 1) // round to pointer alignment 250 ggloblsym(sym, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL) 251 252 return sym 253 } 254 255 var slicebytes_gen int 256 257 func slicebytes(nam *Node, s string, len int) { 258 var m int 259 260 slicebytes_gen++ 261 symname := fmt.Sprintf(".gobytes.%d", slicebytes_gen) 262 sym := Pkglookup(symname, localpkg) 263 sym.Def = newname(sym) 264 265 off := 0 266 for n := 0; n < len; n += m { 267 m = 8 268 if m > len-n { 269 m = len - n 270 } 271 off = dsname(sym, off, s[n:n+m]) 272 } 273 274 ggloblsym(sym, int32(off), obj.NOPTR|obj.LOCAL) 275 276 if nam.Op != ONAME { 277 Fatal("slicebytes %v", nam) 278 } 279 off = int(nam.Xoffset) 280 off = dsymptr(nam.Sym, off, sym, 0) 281 off = duintxx(nam.Sym, off, uint64(len), Widthint) 282 duintxx(nam.Sym, off, uint64(len), Widthint) 283 } 284 285 func dstringptr(s *Sym, off int, str string) int { 286 off = int(Rnd(int64(off), int64(Widthptr))) 287 p := Thearch.Gins(obj.ADATA, nil, nil) 288 p.From.Type = obj.TYPE_MEM 289 p.From.Name = obj.NAME_EXTERN 290 p.From.Sym = Linksym(s) 291 p.From.Offset = int64(off) 292 p.From3.Type = obj.TYPE_CONST 293 p.From3.Offset = int64(Widthptr) 294 295 Datastring(str+"\x00", &p.To) // TODO(rsc): Remove NUL 296 p.To.Type = obj.TYPE_ADDR 297 p.To.Etype = Simtype[TINT] 298 off += Widthptr 299 300 return off 301 } 302 303 func Datastring(s string, a *obj.Addr) { 304 sym := stringsym(s) 305 a.Type = obj.TYPE_MEM 306 a.Name = obj.NAME_EXTERN 307 a.Sym = Linksym(sym) 308 a.Node = sym.Def 309 a.Offset = int64(Widthptr) + int64(Widthint) // skip header 310 a.Etype = Simtype[TINT] 311 } 312 313 func datagostring(sval string, a *obj.Addr) { 314 sym := stringsym(sval) 315 a.Type = obj.TYPE_MEM 316 a.Name = obj.NAME_EXTERN 317 a.Sym = Linksym(sym) 318 a.Node = sym.Def 319 a.Offset = 0 // header 320 a.Etype = TSTRING 321 } 322 323 func dgostringptr(s *Sym, off int, str string) int { 324 if str == "" { 325 return duintptr(s, off, 0) 326 } 327 return dgostrlitptr(s, off, &str) 328 } 329 330 func dgostrlitptr(s *Sym, off int, lit *string) int { 331 if lit == nil { 332 return duintptr(s, off, 0) 333 } 334 off = int(Rnd(int64(off), int64(Widthptr))) 335 p := Thearch.Gins(obj.ADATA, nil, nil) 336 p.From.Type = obj.TYPE_MEM 337 p.From.Name = obj.NAME_EXTERN 338 p.From.Sym = Linksym(s) 339 p.From.Offset = int64(off) 340 p.From3.Type = obj.TYPE_CONST 341 p.From3.Offset = int64(Widthptr) 342 datagostring(*lit, &p.To) 343 p.To.Type = obj.TYPE_ADDR 344 p.To.Etype = Simtype[TINT] 345 off += Widthptr 346 347 return off 348 } 349 350 func dsname(s *Sym, off int, t string) int { 351 p := Thearch.Gins(obj.ADATA, nil, nil) 352 p.From.Type = obj.TYPE_MEM 353 p.From.Name = obj.NAME_EXTERN 354 p.From.Offset = int64(off) 355 p.From.Sym = Linksym(s) 356 p.From3.Type = obj.TYPE_CONST 357 p.From3.Offset = int64(len(t)) 358 359 p.To.Type = obj.TYPE_SCONST 360 p.To.Val = t 361 return off + len(t) 362 } 363 364 func dsymptr(s *Sym, off int, x *Sym, xoff int) int { 365 off = int(Rnd(int64(off), int64(Widthptr))) 366 367 p := Thearch.Gins(obj.ADATA, nil, nil) 368 p.From.Type = obj.TYPE_MEM 369 p.From.Name = obj.NAME_EXTERN 370 p.From.Sym = Linksym(s) 371 p.From.Offset = int64(off) 372 p.From3.Type = obj.TYPE_CONST 373 p.From3.Offset = int64(Widthptr) 374 p.To.Type = obj.TYPE_ADDR 375 p.To.Name = obj.NAME_EXTERN 376 p.To.Sym = Linksym(x) 377 p.To.Offset = int64(xoff) 378 off += Widthptr 379 380 return off 381 } 382 383 func gdata(nam *Node, nr *Node, wid int) { 384 if nr.Op == OLITERAL { 385 switch nr.Val.Ctype { 386 case CTCPLX: 387 gdatacomplex(nam, nr.Val.U.Cval) 388 return 389 390 case CTSTR: 391 gdatastring(nam, nr.Val.U.Sval) 392 return 393 } 394 } 395 396 p := Thearch.Gins(obj.ADATA, nam, nr) 397 p.From3.Type = obj.TYPE_CONST 398 p.From3.Offset = int64(wid) 399 } 400 401 func gdatacomplex(nam *Node, cval *Mpcplx) { 402 w := cplxsubtype(int(nam.Type.Etype)) 403 w = int(Types[w].Width) 404 405 p := Thearch.Gins(obj.ADATA, nam, nil) 406 p.From3.Type = obj.TYPE_CONST 407 p.From3.Offset = int64(w) 408 p.To.Type = obj.TYPE_FCONST 409 p.To.Val = mpgetflt(&cval.Real) 410 411 p = Thearch.Gins(obj.ADATA, nam, nil) 412 p.From3.Type = obj.TYPE_CONST 413 p.From3.Offset = int64(w) 414 p.From.Offset += int64(w) 415 p.To.Type = obj.TYPE_FCONST 416 p.To.Val = mpgetflt(&cval.Imag) 417 } 418 419 func gdatastring(nam *Node, sval string) { 420 var nod1 Node 421 422 p := Thearch.Gins(obj.ADATA, nam, nil) 423 Datastring(sval, &p.To) 424 p.From3.Type = obj.TYPE_CONST 425 p.From3.Offset = Types[Tptr].Width 426 p.To.Type = obj.TYPE_ADDR 427 428 //print("%P\n", p); 429 430 Nodconst(&nod1, Types[TINT], int64(len(sval))) 431 432 p = Thearch.Gins(obj.ADATA, nam, &nod1) 433 p.From3.Type = obj.TYPE_CONST 434 p.From3.Offset = int64(Widthint) 435 p.From.Offset += int64(Widthptr) 436 }