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