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

// Debug arguments, set by -d flag.

package base

import (
	"fmt"
	"log"
	"os"
	"reflect"
	"strconv"
	"strings"
)

// Debug holds the parsed debugging configuration values.
var Debug DebugFlags

// DebugFlags defines the debugging configuration values (see var Debug).
// Each struct field is a different value, named for the lower-case of the field name.
// Each field must be an int or string and must have a `help` struct tag.
//
// The -d option takes a comma-separated list of settings.
// Each setting is name=value; for ints, name is short for name=1.
type DebugFlags struct {
	Append               int    `help:"print information about append compilation"`
	Checkptr             int    `help:"instrument unsafe pointer conversions"`
	Closure              int    `help:"print information about closure compilation"`
	DclStack             int    `help:"run internal dclstack check"`
	Defer                int    `help:"print information about defer compilation"`
	DisableNil           int    `help:"disable nil checks"`
	DumpPtrs             int    `help:"show Node pointers values in dump output"`
	DwarfInl             int    `help:"print information about DWARF inlined function creation"`
	Export               int    `help:"print export data"`
	GCProg               int    `help:"print dump of GC programs"`
	InlFuncsWithClosures int    `help:"allow functions with closures to be inlined"`
	Libfuzzer            int    `help:"enable coverage instrumentation for libfuzzer"`
	LocationLists        int    `help:"print information about DWARF location list creation"`
	Nil                  int    `help:"print information about nil checks"`
	NoOpenDefer          int    `help:"disable open-coded defers"`
	PCTab                string `help:"print named pc-value table"`
	Panic                int    `help:"show all compiler panics"`
	Slice                int    `help:"print information about slice compilation"`
	SoftFloat            int    `help:"force compiler to emit soft-float code"`
	SyncFrames           int    `help:"how many writer stack frames to include at sync points in unified export data"`
	TypeAssert           int    `help:"print information about type assertion inlining"`
	TypecheckInl         int    `help:"eager typechecking of inline function bodies"`
	Unified              int    `help:"enable unified IR construction"`
	UnifiedQuirks        int    `help:"enable unified IR construction's quirks mode"`
	WB                   int    `help:"print information about write barriers"`
	ABIWrap              int    `help:"print information about ABI wrapper generation"`

	any bool // set when any of the values have been set
}

// Any reports whether any of the debug flags have been set.
func (d *DebugFlags) Any() bool { return d.any }

type debugField struct {
	name string
	help string
	val  interface{} // *int or *string
}

var debugTab []debugField

func init() {
	v := reflect.ValueOf(&Debug).Elem()
	t := v.Type()
	for i := 0; i < t.NumField(); i++ {
		f := t.Field(i)
		if f.Name == "any" {
			continue
		}
		name := strings.ToLower(f.Name)
		help := f.Tag.Get("help")
		if help == "" {
			panic(fmt.Sprintf("base.Debug.%s is missing help text", f.Name))
		}
		ptr := v.Field(i).Addr().Interface()
		switch ptr.(type) {
		default:
			panic(fmt.Sprintf("base.Debug.%s has invalid type %v (must be int or string)", f.Name, f.Type))
		case *int, *string:
			// ok
		}
		debugTab = append(debugTab, debugField{name, help, ptr})
	}
}

// DebugSSA is called to set a -d ssa/... option.
// If nil, those options are reported as invalid options.
// If DebugSSA returns a non-empty string, that text is reported as a compiler error.
var DebugSSA func(phase, flag string, val int, valString string) string

// parseDebug parses the -d debug string argument.
func parseDebug(debugstr string) {
	// parse -d argument
	if debugstr == "" {
		return
	}
	Debug.any = true
Split:
	for _, name := range strings.Split(debugstr, ",") {
		if name == "" {
			continue
		}
		// display help about the -d option itself and quit
		if name == "help" {
			fmt.Print(debugHelpHeader)
			maxLen := len("ssa/help")
			for _, t := range debugTab {
				if len(t.name) > maxLen {
					maxLen = len(t.name)
				}
			}
			for _, t := range debugTab {
				fmt.Printf("\t%-*s\t%s\n", maxLen, t.name, t.help)
			}
			// ssa options have their own help
			fmt.Printf("\t%-*s\t%s\n", maxLen, "ssa/help", "print help about SSA debugging")
			fmt.Print(debugHelpFooter)
			os.Exit(0)
		}
		val, valstring, haveInt := 1, "", true
		if i := strings.IndexAny(name, "=:"); i >= 0 {
			var err error
			name, valstring = name[:i], name[i+1:]
			val, err = strconv.Atoi(valstring)
			if err != nil {
				val, haveInt = 1, false
			}
		}
		for _, t := range debugTab {
			if t.name != name {
				continue
			}
			switch vp := t.val.(type) {
			case nil:
				// Ignore
			case *string:
				*vp = valstring
			case *int:
				if !haveInt {
					log.Fatalf("invalid debug value %v", name)
				}
				*vp = val
			default:
				panic("bad debugtab type")
			}
			continue Split
		}
		// special case for ssa for now
		if DebugSSA != nil && strings.HasPrefix(name, "ssa/") {
			// expect form ssa/phase/flag
			// e.g. -d=ssa/generic_cse/time
			// _ in phase name also matches space
			phase := name[4:]
			flag := "debug" // default flag is debug
			if i := strings.Index(phase, "/"); i >= 0 {
				flag = phase[i+1:]
				phase = phase[:i]
			}
			err := DebugSSA(phase, flag, val, valstring)
			if err != "" {
				log.Fatalf(err)
			}
			continue Split
		}
		log.Fatalf("unknown debug key -d %s\n", name)
	}
}

const debugHelpHeader = `usage: -d arg[,arg]* and arg is <key>[=<value>]

<key> is one of:

`

const debugHelpFooter = `
<value> is key-specific.

Key "checkptr" supports values:
	"0": instrumentation disabled
	"1": conversions involving unsafe.Pointer are instrumented
	"2": conversions to unsafe.Pointer force heap allocation

Key "pctab" supports values:
	"pctospadj", "pctofile", "pctoline", "pctoinline", "pctopcdata"
`
