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

package obj

import (
	"fmt"
	"log"
	"strings"
)

type Plist struct {
	Firstpc *Prog
}

/*
 * start a new Prog list.
 */
func Linknewplist(ctxt *Link) *Plist {
	pl := new(Plist)
	ctxt.Plists = append(ctxt.Plists, pl)
	return pl
}

func Flushplist(ctxt *Link) {
	flushplist(ctxt, ctxt.Debugasm == 0)
}
func FlushplistNoFree(ctxt *Link) {
	flushplist(ctxt, false)
}
func flushplist(ctxt *Link, freeProgs bool) {
	// Build list of symbols, and assign instructions to lists.
	// Ignore ctxt->plist boundaries. There are no guarantees there,
	// and the assemblers just use one big list.
	var curtext *LSym
	var etext *Prog
	var text []*LSym

	for _, pl := range ctxt.Plists {
		var plink *Prog
		for p := pl.Firstpc; p != nil; p = plink {
			if ctxt.Debugasm != 0 && ctxt.Debugvlog != 0 {
				fmt.Printf("obj: %v\n", p)
			}
			plink = p.Link
			p.Link = nil

			switch p.As {
			case AEND:
				continue

			case ATYPE:
				// Assume each TYPE instruction describes
				// a different local variable or parameter,
				// so no dedup.
				// Using only the TYPE instructions means
				// that we discard location information about local variables
				// in C and assembly functions; that information is inferred
				// from ordinary references, because there are no TYPE
				// instructions there. Without the type information, gdb can't
				// use the locations, so we don't bother to save them.
				// If something else could use them, we could arrange to
				// preserve them.
				if curtext == nil {
					continue
				}
				a := new(Auto)
				a.Asym = p.From.Sym
				a.Aoffset = int32(p.From.Offset)
				a.Name = int16(p.From.Name)
				a.Gotype = p.From.Gotype
				a.Link = curtext.Autom
				curtext.Autom = a
				continue

			case ATEXT:
				s := p.From.Sym
				if s == nil {
					// func _() { }
					curtext = nil

					continue
				}

				if s.Text != nil {
					log.Fatalf("duplicate TEXT for %s", s.Name)
				}
				if s.Onlist {
					log.Fatalf("symbol %s listed multiple times", s.Name)
				}
				s.Onlist = true
				text = append(text, s)
				flag := int(p.From3Offset())
				if flag&DUPOK != 0 {
					s.Dupok = true
				}
				if flag&NOSPLIT != 0 {
					s.Nosplit = true
				}
				if flag&REFLECTMETHOD != 0 {
					s.ReflectMethod = true
				}
				s.Type = STEXT
				s.Text = p
				etext = p
				curtext = s
				continue

			case AFUNCDATA:
				// Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information.
				if curtext == nil { // func _() {}
					continue
				}
				if p.To.Sym.Name == "go_args_stackmap" {
					if p.From.Type != TYPE_CONST || p.From.Offset != FUNCDATA_ArgsPointerMaps {
						ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps")
					}
					p.To.Sym = Linklookup(ctxt, fmt.Sprintf("%s.args_stackmap", curtext.Name), int(curtext.Version))
				}

			}

			if curtext == nil {
				etext = nil
				continue
			}
			etext.Link = p
			etext = p
		}
	}

	// Add reference to Go arguments for C or assembly functions without them.
	for _, s := range text {
		if !strings.HasPrefix(s.Name, "\"\".") {
			continue
		}
		found := false
		var p *Prog
		for p = s.Text; p != nil; p = p.Link {
			if p.As == AFUNCDATA && p.From.Type == TYPE_CONST && p.From.Offset == FUNCDATA_ArgsPointerMaps {
				found = true
				break
			}
		}

		if !found {
			p = Appendp(ctxt, s.Text)
			p.As = AFUNCDATA
			p.From.Type = TYPE_CONST
			p.From.Offset = FUNCDATA_ArgsPointerMaps
			p.To.Type = TYPE_MEM
			p.To.Name = NAME_EXTERN
			p.To.Sym = Linklookup(ctxt, fmt.Sprintf("%s.args_stackmap", s.Name), int(s.Version))
		}
	}

	// Turn functions into machine code images.
	for _, s := range text {
		mkfwd(s)
		linkpatch(ctxt, s)
		if ctxt.Flag_optimize {
			ctxt.Arch.Follow(ctxt, s)
		}
		ctxt.Arch.Preprocess(ctxt, s)
		ctxt.Arch.Assemble(ctxt, s)
		fieldtrack(ctxt, s)
		linkpcln(ctxt, s)
		if freeProgs {
			s.Text = nil
		}
	}

	// Add to running list in ctxt.
	ctxt.Text = append(ctxt.Text, text...)
	ctxt.Data = append(ctxt.Data, gendwarf(ctxt, text)...)
	ctxt.Plists = nil
	ctxt.Curp = nil
	if freeProgs {
		ctxt.freeProgs()
	}
}

func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
	if s.Seenglobl {
		fmt.Printf("duplicate %v\n", s)
	}
	s.Seenglobl = true
	if s.Onlist {
		log.Fatalf("symbol %s listed multiple times", s.Name)
	}
	s.Onlist = true
	ctxt.Data = append(ctxt.Data, s)
	s.Size = size
	if s.Type == 0 || s.Type == SXREF {
		s.Type = SBSS
	}
	if flag&DUPOK != 0 {
		s.Dupok = true
	}
	if flag&RODATA != 0 {
		s.Type = SRODATA
	} else if flag&NOPTR != 0 {
		s.Type = SNOPTRBSS
	} else if flag&TLSBSS != 0 {
		s.Type = STLSBSS
	}
}
