github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/asm/asm.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/asm/asm.go 2 3 // Inferno utils/6a/a.h and lex.c. 4 // http://code.google.com/p/inferno-os/source/browse/utils/6a/a.h 5 // http://code.google.com/p/inferno-os/source/browse/utils/6a/lex.c 6 // 7 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 8 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 9 // Portions Copyright © 1997-1999 Vita Nuova Limited 10 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 11 // Portions Copyright © 2004,2006 Bruce Ellis 12 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 13 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 14 // Portions Copyright © 2009 The Go Authors. All rights reserved. 15 // 16 // Permission is hereby granted, free of charge, to any person obtaining a copy 17 // of this software and associated documentation files (the "Software"), to deal 18 // in the Software without restriction, including without limitation the rights 19 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 // copies of the Software, and to permit persons to whom the Software is 21 // furnished to do so, subject to the following conditions: 22 // 23 // The above copyright notice and this permission notice shall be included in 24 // all copies or substantial portions of the Software. 25 // 26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 32 // THE SOFTWARE. 33 34 // Package asm holds code shared among the assemblers. 35 package asm 36 37 import ( 38 "flag" 39 "fmt" 40 "log" 41 "os" 42 "path/filepath" 43 "strconv" 44 "strings" 45 46 "rsc.io/tmp/bootstrap/internal/obj" 47 ) 48 49 // Initialized by client. 50 var ( 51 LSCONST int 52 LCONST int 53 LFCONST int 54 LNAME int 55 LVAR int 56 LLAB int 57 58 Thechar rune 59 Thestring string 60 Thelinkarch *obj.LinkArch 61 62 Arches map[string]*obj.LinkArch 63 64 Cclean func() 65 Yyparse func() 66 Syminit func(*Sym) 67 68 Lexinit []Lextab 69 ) 70 71 type Lextab struct { 72 Name string 73 Type int 74 Value int64 75 } 76 77 const ( 78 MAXALIGN = 7 79 FPCHIP = 1 80 NSYMB = 500 81 BUFSIZ = 8192 82 HISTSZ = 20 83 EOF = -1 84 IGN = -2 85 NHASH = 503 86 NMACRO = 10 87 ) 88 89 const ( 90 CLAST = iota 91 CMACARG 92 CMACRO 93 CPREPROC 94 ) 95 96 type Macro struct { 97 Text string 98 Narg int 99 Dots bool 100 } 101 102 type Sym struct { 103 Link *Sym 104 Ref *Ref 105 Macro *Macro 106 Value int64 107 Type int 108 Name string 109 Labelname string 110 Sym int8 111 } 112 113 type Ref struct { 114 Class int 115 } 116 117 type Io struct { 118 Link *Io 119 P []byte 120 F *os.File 121 B [1024]byte 122 } 123 124 var fi struct { 125 P []byte 126 } 127 128 var ( 129 debug [256]int 130 hash = map[string]*Sym{} 131 Dlist []string 132 newflag int 133 hunk string 134 include []string 135 iofree *Io 136 ionext *Io 137 iostack *Io 138 Lineno int32 139 nerrors int 140 nhunk int32 141 ninclude int 142 nsymb int32 143 nullgen obj.Addr 144 outfile string 145 Pass int 146 PC int32 147 peekc int = IGN 148 sym int 149 symb string 150 thunk int32 151 obuf obj.Biobuf 152 Ctxt *obj.Link 153 bstdout obj.Biobuf 154 ) 155 156 func dodef(p string) { 157 Dlist = append(Dlist, p) 158 } 159 160 func usage() { 161 fmt.Printf("usage: %ca [options] file.c...\n", Thechar) 162 flag.PrintDefaults() 163 errorexit() 164 } 165 166 func Main() { 167 // Allow GOARCH=Thestring or GOARCH=Thestringsuffix, 168 // but not other values. 169 p := obj.Getgoarch() 170 171 if !strings.HasPrefix(p, Thestring) { 172 log.Fatalf("cannot use %cc with GOARCH=%s", Thechar, p) 173 } 174 if p != Thestring { 175 Thelinkarch = Arches[p] 176 if Thelinkarch == nil { 177 log.Fatalf("unknown arch %s", p) 178 } 179 } 180 181 Ctxt = obj.Linknew(Thelinkarch) 182 Ctxt.Diag = Yyerror 183 Ctxt.Bso = &bstdout 184 Ctxt.Enforce_data_order = 1 185 bstdout = *obj.Binitw(os.Stdout) 186 187 debug = [256]int{} 188 cinit() 189 outfile = "" 190 setinclude(".") 191 192 flag.Var(flagFn(dodef), "D", "name[=value]: add #define") 193 flag.Var(flagFn(setinclude), "I", "dir: add dir to include path") 194 flag.Var((*count)(&debug['S']), "S", "print assembly and machine code") 195 flag.Var((*count)(&debug['m']), "m", "debug preprocessor macros") 196 flag.StringVar(&outfile, "o", "", "file: set output file") 197 flag.StringVar(&Ctxt.LineHist.TrimPathPrefix, "trimpath", "", "prefix: remove prefix from recorded source file paths") 198 199 flag.Parse() 200 201 Ctxt.Debugasm = int32(debug['S']) 202 203 if flag.NArg() < 1 { 204 usage() 205 } 206 if flag.NArg() > 1 { 207 fmt.Printf("can't assemble multiple files\n") 208 errorexit() 209 } 210 211 if assemble(flag.Arg(0)) != 0 { 212 errorexit() 213 } 214 obj.Bflush(&bstdout) 215 if nerrors > 0 { 216 errorexit() 217 } 218 } 219 220 func assemble(file string) int { 221 if outfile == "" { 222 outfile = strings.TrimSuffix(filepath.Base(file), ".s") + "." + string(Thechar) 223 } 224 225 of, err := os.Create(outfile) 226 if err != nil { 227 Yyerror("%ca: cannot create %s", Thechar, outfile) 228 errorexit() 229 } 230 231 obuf = *obj.Binitw(of) 232 fmt.Fprintf(&obuf, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion()) 233 fmt.Fprintf(&obuf, "!\n") 234 235 var i int 236 for Pass = 1; Pass <= 2; Pass++ { 237 pinit(file) 238 for i = 0; i < len(Dlist); i++ { 239 dodefine(Dlist[i]) 240 } 241 Yyparse() 242 Cclean() 243 if nerrors != 0 { 244 return nerrors 245 } 246 } 247 248 obj.Writeobjdirect(Ctxt, &obuf) 249 obj.Bflush(&obuf) 250 return 0 251 } 252 253 func cinit() { 254 for i := 0; i < len(Lexinit); i++ { 255 s := Lookup(Lexinit[i].Name) 256 if s.Type != LNAME { 257 Yyerror("double initialization %s", Lexinit[i].Name) 258 } 259 s.Type = Lexinit[i].Type 260 s.Value = Lexinit[i].Value 261 } 262 } 263 264 func syminit(s *Sym) { 265 s.Type = LNAME 266 s.Value = 0 267 } 268 269 type flagFn func(string) 270 271 func (flagFn) String() string { 272 return "<arg>" 273 } 274 275 func (f flagFn) Set(s string) error { 276 f(s) 277 return nil 278 } 279 280 type yyImpl struct{} 281 282 // count is a flag.Value that is like a flag.Bool and a flag.Int. 283 // If used as -name, it increments the count, but -name=x sets the count. 284 // Used for verbose flag -v. 285 type count int 286 287 func (c *count) String() string { 288 return fmt.Sprint(int(*c)) 289 } 290 291 func (c *count) Set(s string) error { 292 switch s { 293 case "true": 294 *c++ 295 case "false": 296 *c = 0 297 default: 298 n, err := strconv.Atoi(s) 299 if err != nil { 300 return fmt.Errorf("invalid count %q", s) 301 } 302 *c = count(n) 303 } 304 return nil 305 } 306 307 func (c *count) IsBoolFlag() bool { 308 return true 309 }