]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/internal/asm/asm.go
[dev.cc] cmd/new5a etc, cmd/internal/asm: edit to produce working Go code
[gostls13.git] / src / cmd / internal / asm / asm.go
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         STRINGSZ = 200
85         NMACRO   = 10
86 )
87
88 const (
89         CLAST = iota
90         CMACARG
91         CMACRO
92         CPREPROC
93 )
94
95 type Macro struct {
96         Text string
97         Narg int
98         Dots bool
99 }
100
101 type Sym struct {
102         Link      *Sym
103         Ref       *Ref
104         Macro     *Macro
105         Value     int64
106         Type      int
107         Name      string
108         Labelname string
109         Sym       int8
110 }
111
112 type Ref struct {
113         Class int
114 }
115
116 type Io struct {
117         Link *Io
118         P    []byte
119         F    *os.File
120         B    [1024]byte
121 }
122
123 var fi struct {
124         P []byte
125 }
126
127 var (
128         debug    [256]int
129         hash     = map[string]*Sym{}
130         Dlist    []string
131         newflag  int
132         hunk     string
133         include  []string
134         iofree   *Io
135         ionext   *Io
136         iostack  *Io
137         Lineno   int32
138         nerrors  int
139         nhunk    int32
140         ninclude int
141         nsymb    int32
142         nullgen  obj.Addr
143         outfile  string
144         Pass     int
145         PC       int32
146         peekc    int = IGN
147         sym      int
148         symb     string
149         thunk    int32
150         obuf     obj.Biobuf
151         Ctxt     *obj.Link
152         bstdout  obj.Biobuf
153 )
154
155 func dodef(p string) {
156         Dlist = append(Dlist, p)
157 }
158
159 func usage() {
160         fmt.Printf("usage: %ca [options] file.c...\n", Thechar)
161         flag.PrintDefaults()
162         errorexit()
163 }
164
165 func Main() {
166         var p string
167
168         // Allow GOARCH=Thestring or GOARCH=Thestringsuffix,
169         // but not other values.
170         p = obj.Getgoarch()
171
172         if !strings.HasPrefix(p, Thestring) {
173                 log.Fatalf("cannot use %cc with GOARCH=%s", Thechar, p)
174         }
175         if p != Thestring {
176                 Thelinkarch = Arches[p]
177                 if Thelinkarch == nil {
178                         log.Fatalf("unknown arch %s", p)
179                 }
180         }
181
182         Ctxt = obj.Linknew(Thelinkarch)
183         Ctxt.Diag = Yyerror
184         Ctxt.Bso = &bstdout
185         Ctxt.Enforce_data_order = 1
186         bstdout = *obj.Binitw(os.Stdout)
187
188         debug = [256]int{}
189         cinit()
190         outfile = ""
191         setinclude(".")
192
193         flag.Var(flagFn(dodef), "D", "name[=value]: add #define")
194         flag.Var(flagFn(setinclude), "I", "dir: add dir to include path")
195         flag.Var((*count)(&debug['S']), "S", "print assembly and machine code")
196         flag.Var((*count)(&debug['m']), "m", "debug preprocessor macros")
197         flag.StringVar(&outfile, "o", "", "file: set output file")
198         flag.StringVar(&Ctxt.Trimpath, "trimpath", "", "prefix: remove prefix from recorded source file paths")
199
200         flag.Parse()
201
202         Ctxt.Debugasm = int32(debug['S'])
203
204         if flag.NArg() < 1 {
205                 usage()
206         }
207         if flag.NArg() > 1 {
208                 fmt.Printf("can't assemble multiple files\n")
209                 errorexit()
210         }
211
212         if assemble(flag.Arg(0)) != 0 {
213                 errorexit()
214         }
215         obj.Bflush(&bstdout)
216         if nerrors > 0 {
217                 errorexit()
218         }
219 }
220
221 func assemble(file string) int {
222         var i int
223
224         if outfile == "" {
225                 outfile = strings.TrimSuffix(filepath.Base(file), ".s") + "." + string(Thechar)
226         }
227
228         of, err := os.Create(outfile)
229         if err != nil {
230                 Yyerror("%ca: cannot create %s", Thechar, outfile)
231                 errorexit()
232         }
233
234         obuf = *obj.Binitw(of)
235         fmt.Fprintf(&obuf, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion())
236         fmt.Fprintf(&obuf, "!\n")
237
238         for Pass = 1; Pass <= 2; Pass++ {
239                 pinit(file)
240                 for i = 0; i < len(Dlist); i++ {
241                         dodefine(Dlist[i])
242                 }
243                 Yyparse()
244                 Cclean()
245                 if nerrors != 0 {
246                         return nerrors
247                 }
248         }
249
250         obj.Writeobjdirect(Ctxt, &obuf)
251         obj.Bflush(&obuf)
252         return 0
253 }
254
255 func cinit() {
256         for i := 0; i < len(Lexinit); i++ {
257                 s := Lookup(Lexinit[i].Name)
258                 if s.Type != LNAME {
259                         Yyerror("double initialization %s", Lexinit[i].Name)
260                 }
261                 s.Type = Lexinit[i].Type
262                 s.Value = Lexinit[i].Value
263         }
264 }
265
266 func syminit(s *Sym) {
267         s.Type = LNAME
268         s.Value = 0
269 }
270
271 type flagFn func(string)
272
273 func (flagFn) String() string {
274         return "<arg>"
275 }
276
277 func (f flagFn) Set(s string) error {
278         f(s)
279         return nil
280 }
281
282 type yyImpl struct{}
283
284 // count is a flag.Value that is like a flag.Bool and a flag.Int.
285 // If used as -name, it increments the count, but -name=x sets the count.
286 // Used for verbose flag -v.
287 type count int
288
289 func (c *count) String() string {
290         return fmt.Sprint(int(*c))
291 }
292
293 func (c *count) Set(s string) error {
294         switch s {
295         case "true":
296                 *c++
297         case "false":
298                 *c = 0
299         default:
300                 n, err := strconv.Atoi(s)
301                 if err != nil {
302                         return fmt.Errorf("invalid count %q", s)
303                 }
304                 *c = count(n)
305         }
306         return nil
307 }
308
309 func (c *count) IsBoolFlag() bool {
310         return true
311 }