// Copyright 2019 The ChromiumOS 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 main

import (
	"bytes"
	"os"
	"path"
	"path/filepath"
	"strings"
)

func processClangFlags(builder *commandBuilder) error {
	env := builder.env
	clangDir, _ := env.getenv("CLANG")

	if clangDir == "" {
		if builder.cfg.isHostWrapper {
			clangDir = filepath.Dir(builder.absWrapperPath)
		} else {
			clangDir = filepath.Join(builder.rootPath, "usr/bin/")
			if !filepath.IsAbs(builder.path) {
				// If sysroot_wrapper is invoked by relative path, call actual compiler in
				// relative form. This is neccesary to remove absolute path from compile
				// outputs.
				var err error
				clangDir, err = filepath.Rel(env.getwd(), clangDir)
				if err != nil {
					return wrapErrorwithSourceLocf(err, "failed to make clangDir %s relative to %s.", clangDir, env.getwd())
				}
			}
		}
	} else {
		clangDir = filepath.Dir(clangDir)
	}

	clangBasename := "clang"
	if strings.HasSuffix(builder.target.compiler, "++") {
		clangBasename = "clang++"
	}

	// GCC flags to remove from the clang command line.
	// TODO: Once clang supports GCC compatibility mode, remove
	// these checks.
	//
	// Use of -Qunused-arguments allows this set to be small, just those
	// that clang still warns about.
	unsupported := make(map[string]bool)

	unsupportedPrefixes := []string{"-Wstrict-aliasing=", "-finline-limit="}

	// clang with '-ftrapv' generates 'call __mulodi4', which is only implemented
	// in compiler-rt library. However compiler-rt library only has i386/x86_64
	// backends (see '/usr/lib/clang/3.7.0/lib/linux/libclang_rt.*'). GCC, on the
	// other hand, generate 'call __mulvdi3', which is implemented in libgcc. See
	// bug chromium:503229.
	armUnsupported := map[string]bool{"-ftrapv": true}
	if builder.cfg.isHostWrapper {
		unsupported["-ftrapv"] = true
	}

	// Clang may use different options for the same or similar functionality.
	gccToClang := map[string]string{
		"-Wno-error=cpp":                 "-Wno-#warnings",
		"-Wno-error=maybe-uninitialized": "-Wno-error=uninitialized",
	}

	// Note: not using builder.transformArgs as we need to add multiple arguments
	// based on a single input argument, and also be able to return errors.
	newArgs := []builderArg{}

	for _, arg := range builder.args {
		// Adds an argument with the given value, preserving the
		// fromUser value of the original argument.
		addNewArg := func(value string) {
			newArgs = append(newArgs, builderArg{
				fromUser: arg.fromUser,
				value:    value,
			})
		}

		if mapped, ok := gccToClang[arg.value]; ok {
			addNewArg(mapped)
			continue
		}

		if unsupported[arg.value] {
			continue
		}

		if hasAtLeastOnePrefix(arg.value, unsupportedPrefixes) {
			continue
		}

		if builder.target.arch == "armv7a" && builder.target.sys == "linux" {
			if armUnsupported[arg.value] {
				continue
			}
		}

		if clangOnly := "-Xclang-only="; strings.HasPrefix(arg.value, clangOnly) {
			addNewArg(arg.value[len(clangOnly):])
			continue
		}

		if clangPath := "-Xclang-path="; strings.HasPrefix(arg.value, clangPath) {
			clangPathValue := arg.value[len(clangPath):]
			resourceDir, err := getClangResourceDir(env, filepath.Join(clangDir, clangBasename))
			if err != nil {
				return err
			}
			clangDir = clangPathValue

			addNewArg("-resource-dir=" + resourceDir)
			addNewArg("--gcc-toolchain=/usr")
			continue
		}

		addNewArg(arg.value)
	}
	builder.args = newArgs

	builder.path = filepath.Join(clangDir, clangBasename)

	// Specify the target for clang.
	if !builder.cfg.isHostWrapper {
		linkerPath := getLinkerPath(env, builder.target.target+"-ld.bfd", builder.rootPath)
		relLinkerPath, err := filepath.Rel(env.getwd(), linkerPath)
		if err != nil {
			return wrapErrorwithSourceLocf(err, "failed to make linker path %s relative to %s",
				linkerPath, env.getwd())
		}
		prefixPath := path.Join(relLinkerPath, builder.target.target+"-")
		builder.addPreUserArgs("--prefix=" + prefixPath)
		builder.addPostUserArgs("-B" + relLinkerPath)
		builder.addPostUserArgs("-target", builder.target.target)
	}
	return nil
}

func getClangResourceDir(env env, clangPath string) (string, error) {
	readResourceCmd := &command{
		Path: clangPath,
		Args: []string{"--print-resource-dir"},
	}
	stdoutBuffer := bytes.Buffer{}
	if err := env.run(readResourceCmd, nil, &stdoutBuffer, env.stderr()); err != nil {
		return "", wrapErrorwithSourceLocf(err,
			"failed to call clang to read the resouce-dir: %#v",
			readResourceCmd)
	}
	resourceDir := strings.TrimRight(stdoutBuffer.String(), "\n")
	return resourceDir, nil
}

// Return the a directory which contains an 'ld' that gcc is using.
func getLinkerPath(env env, linkerCmd string, rootPath string) string {
	// We did not pass the tuple i686-pc-linux-gnu to x86-32 clang. Instead,
	// we passed '-m32' to clang. As a result, clang does not want to use the
	// i686-pc-linux-gnu-ld, so we need to add this to help clang find the right
	// linker.
	if linkerPath, err := resolveAgainstPathEnv(env, linkerCmd); err == nil {
		// FIXME: We are not using filepath.EvalSymlinks to only unpack
		// one layer of symlinks to match the old wrapper. Investigate
		// why this is important or simplify to filepath.EvalSymlinks.
		if fi, err := os.Lstat(linkerPath); err == nil {
			if fi.Mode()&os.ModeSymlink != 0 {
				if linkPath, err := os.Readlink(linkerPath); err == nil {
					linkerPath = linkPath
				}
			}
			return filepath.Dir(linkerPath)
		}
	}

	// When using the sdk outside chroot, we need to provide the cross linker path
	// to the compiler via -B ${linker_path}. This is because for gcc, it can
	// find the right linker via searching its internal paths. Clang does not have
	// such feature, and it falls back to $PATH search only. However, the path of
	// ${SDK_LOCATION}/bin is not necessarily in the ${PATH}. To fix this, we
	// provide the directory that contains the cross linker wrapper to clang.
	// Outside chroot, it is the top bin directory form the sdk tarball.
	return filepath.Join(rootPath, "bin")
}

func hasAtLeastOnePrefix(s string, prefixes []string) bool {
	for _, prefix := range prefixes {
		if strings.HasPrefix(s, prefix) {
			return true
		}
	}
	return false
}
