// Copyright 2014 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.

// Initial scan of packages making up a program.

// TODO(rsc): Rename goobj.SymID.Version to StaticID to avoid confusion with the ELF meaning of version.
// TODO(rsc): Fix file format so that SBSS/SNOPTRBSS with data is listed as SDATA/SNOPTRDATA.
// TODO(rsc): Parallelize scan to overlap file i/o where possible.

package main

import (
	"cmd/internal/goobj"
	"os"
	"sort"
	"strings"
)

// scan scans all packages making up the program, starting with package main defined in mainfile.
func (p *Prog) scan(mainfile string) {
	p.initScan()
	p.scanFile("main", mainfile)
	if len(p.Missing) > 0 && !p.omitRuntime {
		p.scanImport("runtime")
	}

	var missing []string
	for sym := range p.Missing {
		if !p.isAuto(sym) {
			missing = append(missing, sym.String())
		}
	}

	if missing != nil {
		sort.Strings(missing)
		for _, sym := range missing {
			p.errorf("undefined: %s", sym)
		}
	}

	// TODO(rsc): Walk import graph to diagnose cycles.
}

// initScan initializes the Prog fields needed by scan.
func (p *Prog) initScan() {
	p.Packages = make(map[string]*Package)
	p.Syms = make(map[goobj.SymID]*Sym)
	p.Missing = make(map[goobj.SymID]bool)
	p.Missing[p.startSym] = true
}

// scanFile reads file to learn about the package with the given import path.
func (p *Prog) scanFile(pkgpath string, file string) {
	pkg := &Package{
		File: file,
	}
	p.Packages[pkgpath] = pkg

	f, err := os.Open(file)
	if err != nil {
		p.errorf("%v", err)
		return
	}
	gp, err := goobj.Parse(f, pkgpath)
	f.Close()
	if err != nil {
		p.errorf("reading %s: %v", file, err)
		return
	}

	// TODO(rsc): Change cmd/internal/goobj to record package name as gp.Name.
	// TODO(rsc): If pkgpath == "main", check that gp.Name == "main".

	pkg.Package = gp

	for _, gs := range gp.Syms {
		// TODO(rsc): Fix file format instead of this workaround.
		if gs.Data.Size > 0 {
			switch gs.Kind {
			case goobj.SBSS:
				gs.Kind = goobj.SDATA
			case goobj.SNOPTRBSS:
				gs.Kind = goobj.SNOPTRDATA
			}
		}

		if gs.Version != 0 {
			gs.Version += p.MaxVersion
		}
		for i := range gs.Reloc {
			r := &gs.Reloc[i]
			if r.Sym.Version != 0 {
				r.Sym.Version += p.MaxVersion
			}
			if p.Syms[r.Sym] == nil {
				p.Missing[r.Sym] = true
			}
		}
		if gs.Func != nil {
			for i := range gs.Func.FuncData {
				fdata := &gs.Func.FuncData[i]
				if fdata.Sym.Name != "" {
					if fdata.Sym.Version != 0 {
						fdata.Sym.Version += p.MaxVersion
					}
					if p.Syms[fdata.Sym] == nil {
						p.Missing[fdata.Sym] = true
					}
				}
			}
		}
		if old := p.Syms[gs.SymID]; old != nil {
			// Duplicate definition of symbol. Is it okay?
			// TODO(rsc): Write test for this code.
			switch {
			// If both symbols are BSS (no data), take max of sizes
			// but otherwise ignore second symbol.
			case old.Data.Size == 0 && gs.Data.Size == 0:
				if old.Size < gs.Size {
					old.Size = gs.Size
				}
				continue

			// If one is in BSS and one is not, use the one that is not.
			case old.Data.Size > 0 && gs.Data.Size == 0:
				continue
			case gs.Data.Size > 0 && old.Data.Size == 0:
				break // install gs as new symbol below

			// If either is marked as DupOK, we can keep either one.
			// Keep the one that we saw first.
			case old.DupOK || gs.DupOK:
				continue

			// Otherwise, there's an actual conflict:
			default:
				p.errorf("symbol %s defined in both %s and %s %v %v", gs.SymID, old.Package.File, file, old.Data, gs.Data)
				continue
			}
		}
		s := &Sym{
			Sym:     gs,
			Package: pkg,
		}
		p.addSym(s)
		delete(p.Missing, gs.SymID)

		if s.Data.Size > int64(s.Size) {
			p.errorf("%s: initialized data larger than symbol (%d > %d)", s, s.Data.Size, s.Size)
		}
	}
	p.MaxVersion += pkg.MaxVersion

	for i, pkgpath := range pkg.Imports {
		// TODO(rsc): Fix file format to drop .a from recorded import path.
		pkgpath = strings.TrimSuffix(pkgpath, ".a")
		pkg.Imports[i] = pkgpath

		p.scanImport(pkgpath)
	}
}

func (p *Prog) addSym(s *Sym) {
	pkg := s.Package
	if pkg == nil {
		pkg = p.Packages[""]
		if pkg == nil {
			pkg = &Package{}
			p.Packages[""] = pkg
		}
		s.Package = pkg
	}
	pkg.Syms = append(pkg.Syms, s)
	p.Syms[s.SymID] = s
	p.SymOrder = append(p.SymOrder, s)
}

// scanImport finds the object file for the given import path and then scans it.
func (p *Prog) scanImport(pkgpath string) {
	if p.Packages[pkgpath] != nil {
		return // already loaded
	}

	// TODO(rsc): Implement correct search to find file.
	p.scanFile(pkgpath, p.pkgdir+"/"+pkgpath+".a")
}
