// icf.h --  Identical Code Folding

// Copyright 2009, 2010 Free Software Foundation, Inc.
// Written by Sriraman Tallam <tmsriram@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_ICF_H
#define GOLD_ICF_H

#include <vector>

#include "elfcpp.h"
#include "symtab.h"
#include "object.h"

namespace gold
{

class Object;
class Input_objects;
class Symbol_table;

class Icf
{
 public:
  typedef std::vector<Section_id> Sections_reachable_info;
  typedef std::vector<Symbol*> Symbol_info;
  typedef std::vector<std::pair<long long, long long> > Addend_info;
  typedef std::vector<uint64_t> Offset_info;
  typedef std::vector<unsigned int> Reloc_addend_size_info;
  typedef Unordered_map<Section_id,
                        unsigned int,
                        Section_id_hash> Uniq_secn_id_map;
  typedef Unordered_set<Section_id, Section_id_hash> Secn_fptr_taken_set;

  typedef struct
  {
    // This stores the section corresponding to the reloc.
    Sections_reachable_info section_info;
    // This stores the symbol corresponding to the reloc.
    Symbol_info symbol_info;
    // This stores the symbol value and the addend for a reloc.
    Addend_info addend_info;
    Offset_info offset_info;
    Reloc_addend_size_info reloc_addend_size_info;
  } Reloc_info;

  typedef Unordered_map<Section_id, Reloc_info,
                        Section_id_hash> Reloc_info_list;

  Icf()
  : id_section_(), section_id_(), kept_section_id_(),
    fptr_section_id_(),
    num_tracked_relocs(NULL), icf_ready_(false),
    reloc_info_list_()
  { }

  // Returns the kept folded identical section corresponding to
  // dup_obj and dup_shndx.
  Section_id
  get_folded_section(Object* dup_obj, unsigned int dup_shndx);

  // Forms groups of identical sections where the first member
  // of each group is the kept section during folding.
  void
  find_identical_sections(const Input_objects* input_objects,
                          Symbol_table* symtab);

  // This is set when ICF has been run and the groups of
  // identical sections have been formed.
  void
  icf_ready()
  { this->icf_ready_ = true; }

  // Returns true if ICF has been run.
  bool
  is_icf_ready()
  { return this->icf_ready_; }

  // Unfolds the section denoted by OBJ and SHNDX if folded.
  void
  unfold_section(Object* obj, unsigned int shndx);

  // Returns the kept section corresponding to the 
  // given section.
  bool
  is_section_folded(Object* obj, unsigned int shndx);

  // Given an object and a section index, this returns true if the
  // pointer of the function defined in this section is taken.
  bool
  section_has_function_pointers(Object* obj, unsigned int shndx)
  {
    return (this->fptr_section_id_.find(Section_id(obj, shndx))
            != this->fptr_section_id_.end());
  }

  // Records that a pointer of the function defined in this section
  // is taken.
  void
  set_section_has_function_pointers(Object* obj, unsigned int shndx)
  {
    this->fptr_section_id_.insert(Section_id(obj, shndx));
  }

  // Checks if the section_name should be searched for relocs
  // corresponding to taken function pointers.  Ignores eh_frame
  // and vtable sections.
  inline bool
  check_section_for_function_pointers(const std::string& section_name,
                                      Target* target)
  {
    return (parameters->options().icf_safe_folding()
	    && target->can_check_for_function_pointers()
	    && target->section_may_have_icf_unsafe_pointers(
	        section_name.c_str()));
  }

  // Returns a map of a section to info (Reloc_info) about its relocations.
  Reloc_info_list&
  reloc_info_list()
  { return this->reloc_info_list_; }
  
  // Returns a mapping of each section to a unique integer.
  Uniq_secn_id_map&
  section_to_int_map()
  { return this->section_id_; }

 private:

  // Maps integers to sections.
  std::vector<Section_id> id_section_;
  // Does the reverse.
  Uniq_secn_id_map section_id_;
  // Given a section id, this maps it to the id of the kept
  // section.  If the id's are the same then this section is
  // not folded.
  std::vector<unsigned int> kept_section_id_;
  // Given a section id, this says if the pointer to this
  // function is taken in which case it is dangerous to fold
  // this function.
  Secn_fptr_taken_set fptr_section_id_;
  unsigned int* num_tracked_relocs;
  // Flag to indicate if ICF has been run.
  bool icf_ready_;
  // This list is populated by gc_process_relocs in gc.h.
  Reloc_info_list reloc_info_list_;
};

// This function returns true if this section corresponds to a function that
// should be considered by icf as a possible candidate for folding.  Some
// earlier gcc versions, like 4.0.3, put constructors and destructors in
// .gnu.linkonce.t sections and hence should be included too.
inline bool
is_section_foldable_candidate(const std::string& section_name)
{
  const char* section_name_cstr = section_name.c_str();
  return (is_prefix_of(".text", section_name_cstr)
          || is_prefix_of(".gnu.linkonce.t", section_name_cstr));
}

} // End of namespace gold.

#endif
