// parameters.h -- general parameters for a link using gold  -*- C++ -*-

// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.

// This file is part of gold.

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.

#ifndef GOLD_PARAMETERS_H
#define GOLD_PARAMETERS_H

namespace gold
{

class General_options;
class Errors;
class Target;
template<int size, bool big_endian>
class Sized_target;
class Set_parameters_target_once;

// Here we define the Parameters class which simply holds simple
// general parameters which apply to the entire link.  We use a global
// variable for this.  The parameters class holds three types of data:
//    1) An Errors struct.  Any part of the code that wants to log an
//       error can use parameters->errors().
//    2) A const General_options.  These are the options as read on
//       the commandline.
//    3) Target information, such as size and endian-ness.  This is
//       available as soon as we've decided on the Target (after
//       parsing the first .o file).
//    4) Whether we're doing a static link or not.  This is set
//       after all inputs have been read and we know if any is a
//       dynamic library.

class Parameters
{
 public:
  Parameters();

  // These should be called as soon as they are known.
  void
  set_errors(Errors* errors);

  void
  set_options(const General_options* options);

  void
  set_target(Target* target);

  void
  set_doing_static_link(bool doing_static_link);

  // Return the error object.
  Errors*
  errors() const
  { return this->errors_; }

  // Whether the options are valid.  This should not normally be
  // called, but it is needed by gold_exit.
  bool
  options_valid() const
  { return this->options_ != NULL; }

  // Return the options object.
  const General_options&
  options() const
  {
    gold_assert(this->options_valid());
    return *this->options_;
  }

  // Return whether the target field has been set.
  bool
  target_valid() const
  { return this->target_ != NULL; }

  // The target of the output file we are generating.
  const Target&
  target() const
  {
    gold_assert(this->target_valid());
    return *this->target_;
  }

  // The Sized_target of the output file.  The caller must request the
  // right size and endianness.
  template<int size, bool big_endian>
  Sized_target<size, big_endian>*
  sized_target() const
  {
    gold_assert(this->target_valid());
    return static_cast<Sized_target<size, big_endian>*>(this->target_);
  }

  // Clear the target, for testing.
  void
  clear_target();

  // Return true if TARGET is compatible with the current target.
  bool
  is_compatible_target(const Target*) const;

  bool
  doing_static_link() const
  {
    gold_assert(this->doing_static_link_valid_);
    return this->doing_static_link_;
  }

  // This is just a copy of options().debug().  We make a copy so we
  // don't have to #include options.h in order to inline
  // is_debugging_enabled, below.
  int
  debug() const
  {
    // This can be called before the options are set up.
    if (!this->options_valid())
      return 0;
    return debug_;
  }

  // Return the name of the entry symbol.
  const char*
  entry() const;

  // A convenience routine for combining size and endianness.  It also
  // checks the HAVE_TARGET_FOO configure options and dies if the
  // current target's size/endianness is not supported according to
  // HAVE_TARGET_FOO.  Otherwise it returns this enum
  enum Target_size_endianness
  { TARGET_32_LITTLE, TARGET_32_BIG, TARGET_64_LITTLE, TARGET_64_BIG };

  Target_size_endianness
  size_and_endianness() const;

  // Set the incremental linking mode to INCREMENTAL_FULL.  Used when
  // the linker determines that an incremental update is not possible.
  // Returns false if the incremental mode was INCREMENTAL_UPDATE,
  // indicating that the linker should exit if an update is not possible.
  bool
  set_incremental_full();

  // Return true if we need to prepare incremental linking information.
  bool
  incremental() const;

  // Return true if we are doing a full incremental link.
  bool
  incremental_full() const;

  // Return true if we are doing an incremental update.
  bool
  incremental_update() const;

 private:
  void
  set_target_once(Target*);

  void
  check_target_endianness();

  friend class Set_parameters_target_once;

  Errors* errors_;
  const General_options* options_;
  Target* target_;
  bool doing_static_link_valid_;
  bool doing_static_link_;
  int debug_;
  int incremental_mode_;
  Set_parameters_target_once* set_parameters_target_once_;
};

// This is a global variable.
extern const Parameters* parameters;

// We use free functions for these since they affect a global variable
// that is internal to parameters.cc.

extern void
set_parameters_errors(Errors* errors);

extern void
set_parameters_options(const General_options* options);

extern void
set_parameters_target(Target* target);

extern void
set_parameters_doing_static_link(bool doing_static_link);

extern bool
set_parameters_incremental_full();

// Ensure that the target to be valid by using the default target if
// necessary.

extern void
parameters_force_valid_target();

// Clear the current target, for testing.

extern void
parameters_clear_target();

// Return whether we are doing a particular debugging type.  The
// argument is one of the flags from debug.h.

inline bool
is_debugging_enabled(unsigned int type)
{ return (parameters->debug() & type) != 0; }

} // End namespace gold.

#endif // !defined(GOLD_PARAMETERS_H)
