187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===- ARMELFAttributeData.h ----------------------------------------------===//
287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//
387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//                     The MCLinker Project
487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//
587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// This file is distributed under the University of Illinois Open Source
687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// License. See LICENSE.TXT for details.
787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//
887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include "ARMELFAttributeData.h"
1087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/Input.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/LEB128.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <llvm/ADT/STLExtras.h>
1687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
1887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst ELFAttributeValue* ARMELFAttributeData::getAttributeValue(
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    TagType pTag) const {
2187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pTag <= Tag_Max) {
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const ELFAttributeValue& attr_value = m_Attrs[pTag];
2387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
2487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (attr_value.isInitialized()) {
2587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return &attr_value;
2687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    } else {
2787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Don't return uninitialized attribute value.
2887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return NULL;
2987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } else {
3187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    UnknownAttrsMap::const_iterator attr_it = m_UnknownAttrs.find(pTag);
3287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
3387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (attr_it == m_UnknownAttrs.end()) {
3487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return NULL;
3587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    } else {
3687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return &attr_it->second;
3787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
3887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
4087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstd::pair<ELFAttributeValue*, bool>
4237b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMELFAttributeData::getOrCreateAttributeValue(TagType pTag) {
4337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ELFAttributeValue* attr_value = NULL;
4487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pTag <= Tag_Max) {
4687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    attr_value = &m_Attrs[pTag];
4787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } else {
4887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // An unknown tag encounterred.
4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    attr_value = &m_UnknownAttrs[pTag];
5087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
5187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(attr_value != NULL);
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Setup the value type.
5587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!attr_value->isUninitialized()) {
5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return std::make_pair(attr_value, false);
5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } else {
5887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    attr_value->setType(GetAttributeValueType(pTag));
5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return std::make_pair(attr_value, true);
6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesunsigned int ARMELFAttributeData::GetAttributeValueType(TagType pTag) {
6487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // See ARM [ABI-addenda], 2.2.6.
6587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  switch (pTag) {
6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_compatibility: {
6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return (ELFAttributeValue::Int | ELFAttributeValue::String);
6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_nodefaults: {
7087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return (ELFAttributeValue::Int | ELFAttributeValue::NoDefault);
7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
7287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_CPU_raw_name:
7387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_CPU_name: {
7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return ELFAttributeValue::String;
7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
7687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    default: {
7787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pTag < 32)
7887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        return ELFAttributeValue::Int;
7987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      else
8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        return ((pTag & 1) ? ELFAttributeValue::String
8137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           : ELFAttributeValue::Int);
8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
8387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // unreachable
8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Helper Functions for merge()
8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesnamespace {
9287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/*
9487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Helper function to decode value in Tag_also_compatible_with.
9587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *
9687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * @ref ARM [ABI-addenda], 2.3.7.3
9787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines */
9837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic int decode_secondary_compatibility_attribute(
9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const ELFAttributeValue& pValue) {
10087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // The encoding of Tag_also_compatible_with is:
10187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //
10287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Tag_also_compatible_with (=65), NTSB: data
10387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //
10487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // The data can be either an ULEB128-encoded number followed by a NULL byte or
10587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // a NULL-terminated string. Currently, only the following byte sequence in
10687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // data are currently defined:
10787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //
10887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Tag_CPU_arch (=6) [The arch] 0
10987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert((pValue.type() == ELFAttributeValue::String) &&
11087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "Value of Tag_also_compatible_with must be a string!");
11187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
11237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const std::string& data = pValue.getStringValue();
11387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
11487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Though the integer is in LEB128 format, but they occupy only 1 byte in
11587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // currently defined value.
11687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (data.length() < 2)
11787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Must have a byte for Tag_CPU_arch (=6)
11887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    //           a byte for specifying the CPU architecture (CPU_Arch_ARM_*)
11987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    //
12087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Currently, the 2nd byte can only be v4T (=2) or v6-M (=11).
12187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return -1;
12287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
12387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if ((static_cast<uint8_t>(data[0]) == ARMELFAttributeData::Tag_CPU_arch) &&
12487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      ((data[1] == ARMELFAttributeData::CPU_Arch_ARM_V4T) ||
12587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines       (data[1] == ARMELFAttributeData::CPU_Arch_ARM_V6_M)))
12687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return static_cast<uint32_t>(data[1]);
12787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
12887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Tag_also_compatible_with can be safely ignored.
12987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return -1;
13087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
13187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
13287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/*
13387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * This helper array keeps the ordering of the values in attributes such as
13487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Tag_ABI_align_needed which are sored as 1 > 2 > 0.
13587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines */
13637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic const int value_ordering_120[] = {0, 2, 1};
13787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
13837b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // anonymous namespace
13987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
14087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
14187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// End Helper Functions for merge()
14287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
14387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
14487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool ARMELFAttributeData::merge(const LinkerConfig& pConfig,
14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                const Input& pInput,
14637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                TagType pTag,
14737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                const ELFAttributeValue& pInAttr) {
14887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Pre-condition
14987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //  1. The out_attr must be initailized and has value of the same type as
15087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //     pInAttr.
15187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //  2. The value helf by out_attr and pInAttr must be different.
15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ELFAttributeValue& out_attr = m_Attrs[pTag];
15387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
15487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Attribute in the output must have value assigned.
15587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(out_attr.isInitialized() && "No output attribute to be merged!");
15687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
15787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  switch (pTag) {
15887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_CPU_arch: {
15987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Need value of Tag_also_compatible_with in the input for merge.
16087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() <= CPU_Arch_Max) {
16187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        m_CPUArch = pInAttr.getIntValue();
16287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      } else {
16387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        error(diag::error_unknown_cpu_arch) << pInput.name();
16487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        return false;
16587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
16687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
16787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
16887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_CPU_name: {
16987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // need value of Tag_CPU_arch in the input for merge
17087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_CPUName = pInAttr.getStringValue();
17187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
17287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
17387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_CPU_raw_name: {
17487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // need value of Tag_CPU_arch in the input for merge
17587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_CPURawName = pInAttr.getStringValue();
17687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
17787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
17887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_FP_arch: {
17987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // need value of Tag_HardFP_use in the input for merge
18087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_FPArch = pInAttr.getIntValue();
18187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
18287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
18387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_HardFP_use: {
18487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // need value of Tag_FP_arch in the input for merge
18587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_HardFPUse = pInAttr.getIntValue();
18687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
18787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
18887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_also_compatible_with: {
18987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // need value of Tag_CPU_arch in the input for merge
19087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_SecondaryCPUArch = decode_secondary_compatibility_attribute(pInAttr);
19187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
19287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
19387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_VFP_args: {
19487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // need value of Tag_ABI_FP_number_model in the input for merge
19587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_VFPArgs = pInAttr.getIntValue();
19687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
19787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
19887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // The value of these tags are integers and after merge, only the greatest
19987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // value held by pInAttr and out_attr goes into output.
20087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ARM_ISA_use:
20187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_THUMB_ISA_use:
20287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_WMMX_arch:
20387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_Advanced_SIMD_arch:
20487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_FP_rounding:
20587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_FP_exceptions:
20687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_FP_user_exceptions:
20787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_FP_number_model:
20887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_FP_HP_extension:
20987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_CPU_unaligned_access:
21087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_T2EE_use: {
21187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      assert((out_attr.type() == ELFAttributeValue::Int) &&
21287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines             (pInAttr.type() == ELFAttributeValue::Int) &&
21337b74a387bb3993387029859c2d9d051c41c724eStephen Hines             "should have integer parameeter!");
21487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() > out_attr.getIntValue())
21587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        out_attr.setIntValue(pInAttr.getIntValue());
21687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
21787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
21887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // The value of these tags are integers and after merge, only the smallest
21987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // value held by pInAttr and out_attr goes into output.
22087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_align_preserved:
22187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_PCS_RO_data: {
22287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      assert((out_attr.type() == ELFAttributeValue::Int) &&
22387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines             (pInAttr.type() == ELFAttributeValue::Int) &&
22437b74a387bb3993387029859c2d9d051c41c724eStephen Hines             "should have integer parameeter!");
22587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() < out_attr.getIntValue())
22687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        out_attr.setIntValue(pInAttr.getIntValue());
22787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
22887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
22987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // The values of these attributes are sorted as 1 > 2 > 0. And the greater
23087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // value becomes output.
23187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_align_needed:
23287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_FP_denormal:
23387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_PCS_GOT_use: {
23487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      const int in_val = pInAttr.getIntValue();
23587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      const int out_val = out_attr.getIntValue();
23687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
23787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (in_val <= 2) {
23887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (out_val <= 2) {
23987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // Use value_ordering_120 to determine the ordering.
24087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (value_ordering_120[in_val] > value_ordering_120[out_val]) {
24187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            out_attr.setIntValue(in_val);
24287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          }
24387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
24487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      } else {
24587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // input value > 2, for future-proofing
24687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (in_val > out_val) {
24787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_attr.setIntValue(in_val);
24887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
24987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
25087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
25187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
25287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // These tags use the first value ever seen.
25387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_optimization_goals:
25487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_FP_optimization_goals: {
25587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
25687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
25787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_CPU_arch_profile
25887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_CPU_arch_profile: {
25987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() == Arch_Profile_None)
26087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        return true;
26187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
26287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      switch (out_attr.getIntValue()) {
26387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        case Arch_Profile_None: {
26487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_attr.setIntValue(pInAttr.getIntValue());
26587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          break;
26687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
26787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        case Arch_Profile_RealOrApp: {
26887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (pInAttr.getIntValue() != Arch_Profile_Microcontroller)
26987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            out_attr.setIntValue(pInAttr.getIntValue());
27087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          else
27187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            warning(diag::warn_mismatch_cpu_arch_profile)
27287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                << pInAttr.getIntValue() << pInput.name();
27387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          break;
27487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
27587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        default: {
27687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // out_attr is Arch_Profile_Application or Arch_Profile_Realtime or
27787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // Arch_Profile_Microcontroller.
27887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if ((pInAttr.getIntValue() == Arch_Profile_RealOrApp) &&
27987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              (out_attr.getIntValue() != Arch_Profile_Microcontroller)) {
28087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            // do nothing
28187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          } else {
28287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            if (pConfig.options().warnMismatch())
28387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              warning(diag::warn_mismatch_cpu_arch_profile)
28487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                  << pInAttr.getIntValue() << pInput.name();
28587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          }
28687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          break;
28787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
28887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
28987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
29087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
29187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_MPextension_use and Tag_MPextension_use_legacy
29287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_MPextension_use:
29387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_MPextension_use_legacy: {
29487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (m_MPextensionUse < 0) {
29587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        m_MPextensionUse = pInAttr.getIntValue();
29687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      } else {
29787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (static_cast<unsigned>(m_MPextensionUse) != pInAttr.getIntValue()) {
29887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          warning(diag::error_mismatch_mpextension_use) << pInput.name();
29987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
30087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
30187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
30287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
30387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_DIV_use
30487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_DIV_use: {
30587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() == 2) {
30687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // 2 means the code was permitted to use SDIV/UDIV in anyway.
30787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        out_attr.setIntValue(2);
30887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      } else {
30987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Merge until settling down Tag_CPU_arch.
31087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        m_DIVUse = pInAttr.getIntValue();
31187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
31287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
31387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
31487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_ABI_enum_size
31587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_enum_size: {
31687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if ((out_attr.getIntValue() == Enum_Unused) ||
31787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          (out_attr.getIntValue() == Enum_Containerized_As_Possible))
31887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        out_attr.setIntValue(pInAttr.getIntValue());
31987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      else if (pInAttr.getIntValue() != Enum_Containerized_As_Possible &&
32087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines               pConfig.options().warnMismatch())
32187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        warning(diag::warn_mismatch_enum_size)
32237b74a387bb3993387029859c2d9d051c41c724eStephen Hines            << pInput.name() << pInAttr.getIntValue() << out_attr.getIntValue();
32387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
32487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
32587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_ABI_FP_16bit_format
32687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_FP_16bit_format: {
32787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 0: doesn't use any 16-bit FP number
32887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 1: use IEEE 754 format 16-bit FP number
32987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 2: use VFPv3/Advanced SIMD "alternative format" 16-bit FP number
33087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() != 0) {
33187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (out_attr.getIntValue() == 0) {
33287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_attr.setIntValue(pInAttr.getIntValue());
33387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        } else {
33487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (pConfig.options().warnMismatch())
33587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            warning(diag::warn_mismatch_fp16_format) << pInput.name();
33687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
33787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
33887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
33987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
34087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_nodefaults
34187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_nodefaults: {
34287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // There's nothing to do for this tag. It doesn't have an actual value.
34387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
34487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
34587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_conformance
34687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_conformance: {
34787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Throw away the value if the attribute value doesn't match.
34887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (out_attr.getStringValue() != pInAttr.getStringValue())
34987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        out_attr.setStringValue("");
35087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
35187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
35287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_Virtualization_use
35387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_Virtualization_use: {
35487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 0: No use of any virtualization extension
35587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 1: TrustZone
35687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 2: Virtualization extension such as HVC and ERET
35787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 3: TrustZone and virtualization extension are permitted
35887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() != 0) {
35987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (out_attr.getIntValue() == 0) {
36087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_attr.setIntValue(pInAttr.getIntValue());
36187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        } else {
36287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if ((out_attr.getIntValue() <= 3) && (pInAttr.getIntValue() <= 3)) {
36387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            // Promote to 3
36487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            out_attr.setIntValue(3);
36587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          } else {
36687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            warning(diag::warn_unrecognized_virtualization_use)
36787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                << pInput.name() << pInAttr.getIntValue();
36887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          }
36987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
37087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
37187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
37287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
37387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_ABI_WMMX_args
37487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_WMMX_args: {
37587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // There's no way to merge this value (i.e., objects contain different
37687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // value in this tag are definitely incompatible.)
37787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pConfig.options().warnMismatch())
37887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        warning(diag::warn_mismatch_abi_wmmx_args) << pInput.name();
37987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
38087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
38187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_PCS_config
38287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_PCS_config: {
38387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 0 means no standard configuration used or no information recorded.
38487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() != 0) {
38587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (out_attr.getIntValue() == 0)
38687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_attr.setIntValue(pInAttr.getIntValue());
38787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        else {
38887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // Different values in these attribute are conflict
38987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (pConfig.options().warnMismatch())
39087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            warning(diag::warn_mismatch_pcs_config) << pInput.name();
39187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
39287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
39387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
39487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
39587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_ABI_PCS_R9_use
39687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_PCS_R9_use: {
39787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() != R9_Unused) {
39887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (out_attr.getIntValue() == R9_Unused)
39987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_attr.setIntValue(pInAttr.getIntValue());
40087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        else {
40187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (pConfig.options().warnMismatch())
40287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            warning(diag::warn_mismatch_r9_use) << pInput.name();
40387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
40487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
40587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
40687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
40787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_ABI_PCS_RW_data
40887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_PCS_RW_data: {
40987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() == RW_data_SB_Relative) {
41087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Require using R9 as SB (global Static Base register).
41187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if ((out_attr.getIntValue() != R9_Unused) &&
41287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            (out_attr.getIntValue() != R9_SB) &&
41387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            pConfig.options().warnMismatch())
41487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          warning(diag::warn_mismatch_r9_use) << pInput.name();
41587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
41687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Choose the smaller value
41787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() < out_attr.getIntValue())
41887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        out_attr.setIntValue(pInAttr.getIntValue());
41987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
42087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
42187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_ABI_PCS_wchar_t
42287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case Tag_ABI_PCS_wchar_t: {
42387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 0: no use of wchar_t
42487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 2: sizeof(wchar_t) = 2
42587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 4: sizeof(wchar_t) = 4
42687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pInAttr.getIntValue() != 0) {
42787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (out_attr.getIntValue() == 0)
42887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_attr.setIntValue(pInAttr.getIntValue());
42987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        else {
43087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (pConfig.options().warnMismatch())
43137b74a387bb3993387029859c2d9d051c41c724eStephen Hines            warning(diag::warn_mismatch_wchar_size) << pInput.name()
43237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                    << pInAttr.getIntValue()
43337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                    << out_attr.getIntValue();
43487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
43587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
43687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
43787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
43887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    default: {
43987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Handle unknown attributes:
44087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      //
44187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Since we don't know how to merge the value of unknown attribute, we
44287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // have to ignore it. There're two rules related to the processing (See
44387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // ARM [ABI-addenda] 2.2.6, Coding extensibility and compatibility.):
44487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      //
44587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 1. For tag N where N >= 128, tag N has the same properties as
44687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      //    tag N % 128.
44787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 2. Tag 64-127 can be safely ignored.
44887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 3. Tag 0-63 must be comprehended, therefore we cannot ignore.
44987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pConfig.options().warnMismatch()) {
45087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if ((pTag & 127) < 64) {
45187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          warning(diag::warn_unknown_mandatory_attribute) << pTag
45287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                          << pInput.name();
45387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        } else {
45487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          warning(diag::warn_unknown_attribute) << pTag << pInput.name();
45587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
45687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
45787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
45887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
45987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
46087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
46187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
46287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
46387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
46487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Helper Functions for postMerge()
46587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
46687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
46787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesnamespace {
46887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
46987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/*
47087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Helper function to encode value in Tag_also_compatible_with.
47187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *
47287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * @ref ARM [ABI-addenda], 2.3.7.3
47387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines */
47437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic void encode_secondary_compatibility_attribute(ELFAttributeValue& pValue,
47537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                     int pArch) {
47687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if ((pArch < 0) || (pArch > ARMELFAttributeData::CPU_Arch_Max)) {
47787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pValue.setStringValue("");
47887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } else {
47987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    char new_value[] = {
48037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ARMELFAttributeData::Tag_CPU_arch, static_cast<char>(pArch), 0};
48187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pValue.setStringValue(std::string(new_value, sizeof(new_value)));
48287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
48387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return;
48487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
48587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
48687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/*
48787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Combine the main and secondary CPU arch value
48887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines */
48937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic int calculate_cpu_arch(int cpu_arch, int secondary_arch) {
49087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // short-circuit
49187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if ((secondary_arch < 0) ||
49287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      ((cpu_arch + secondary_arch) != (ARMELFAttributeData::CPU_Arch_ARM_V4T +
49387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                       ARMELFAttributeData::CPU_Arch_ARM_V6_M)))
49487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return cpu_arch;
49587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
49687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if ((cpu_arch == ARMELFAttributeData::CPU_Arch_ARM_V4T) &&
49787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      (secondary_arch == ARMELFAttributeData::CPU_Arch_ARM_V6_M))
49887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return ARMELFAttributeData::CPU_Arch_ARM_V4T_Plus_V6_M;
49987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else if ((cpu_arch == ARMELFAttributeData::CPU_Arch_ARM_V6_M) &&
50087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines           (secondary_arch == ARMELFAttributeData::CPU_Arch_ARM_V4T))
50187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return ARMELFAttributeData::CPU_Arch_ARM_V4T_Plus_V6_M;
50287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
50387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return cpu_arch;
50487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
50587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
50687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/*
50787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Given a CPU arch X and a CPU arch Y in which Y is newer than X, the value in
50887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * cpu_compatibility_table[X][Y] is the CPU arch required to run ISA both from X
50987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * and Y. 0 in the table means unreachable and -1 means conflict architecture
51087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * profile.
51187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines */
51287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#define CPU(C)  ARMELFAttributeData::CPU_Arch_ARM_ ## C
51337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic const int cpu_compatibility_table[][CPU(V4T_Plus_V6_M) + 1] = {
51437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* old\new          ARM v6T2    ARM v6K   ARM v7   ARM v6-M   ARM v6S-M   ARM v7E-M    ARMv8, ARM v4t + v6-M     */  // NOLINT
51537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* Pre v4     */ { CPU(V6T2),  CPU(V6K), CPU(V7),        -1,         -1,         -1,      -1,       -1           },  // NOLINT
51637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v4     */ { CPU(V6T2),  CPU(V6K), CPU(V7),        -1,         -1,         -1,      -1,       -1           },  // NOLINT
51737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v4T    */ { CPU(V6T2),  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V4T)           },  // NOLINT
51837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v5T    */ { CPU(V6T2),  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V5T)           },  // NOLINT
51937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v5TE   */ { CPU(V6T2),  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V5TE)          },  // NOLINT
52037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v5TEJ  */ { CPU(V6T2),  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V5TEJ)         },  // NOLINT
52137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6     */ { CPU(V6T2),  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V6)            },  // NOLINT
52237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6KZ   */ {   CPU(V7), CPU(V6KZ), CPU(V7), CPU(V6KZ),  CPU(V6KZ), CPU(V7E_M), CPU(V8), CPU(V6KZ)          },  // NOLINT
52337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6T2   */ { CPU(V6T2),   CPU(V7), CPU(V7),   CPU(V7),    CPU(V7), CPU(V7E_M), CPU(V8), CPU(V6T2)          },  // NOLINT
52437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6K    */ {         0,  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V6K)           },  // NOLINT
52537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v7     */ {         0,         0, CPU(V7),   CPU(V7),    CPU(V7), CPU(V7E_M), CPU(V8), CPU(V7)            },  // NOLINT
52637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6-M   */ {         0,         0,       0, CPU(V6_M), CPU(V6S_M), CPU(V7E_M), CPU(V8), CPU(V6_M)          },  // NOLINT
52737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6S-M  */ {         0,         0,       0,         0, CPU(V6S_M), CPU(V7E_M), CPU(V8), CPU(V6S_M)         },  // NOLINT
52837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v7E-M  */ {         0,         0,       0,         0,          0, CPU(V7E_M), CPU(V8), CPU(V7E_M)         },  // NOLINT
52937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v8     */ {         0,         0,       0,         0,          0,          0, CPU(V8), CPU(V8)            },  // NOLINT
53037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* v4T + v6-M */ {         0,         0,       0,         0,          0,          0,       0, CPU(V4T_Plus_V6_M) }   // NOLINT
53187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
53287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
53387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/*
53487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Helper function to determine the merge of two different CPU arch.
53587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines */
53637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic int merge_cpu_arch(int out_cpu_arch, int in_cpu_arch) {
53787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (out_cpu_arch > CPU(V4T_Plus_V6_M))
53887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return in_cpu_arch;
53987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
54087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int new_cpu_arch, old_cpu_arch;
54187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (out_cpu_arch > in_cpu_arch) {
54287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    new_cpu_arch = out_cpu_arch;
54387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    old_cpu_arch = in_cpu_arch;
54487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } else {
54587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    new_cpu_arch = in_cpu_arch;
54687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    old_cpu_arch = out_cpu_arch;
54787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
54887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
54987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // No need to check the compatibility since the CPU architectures before
55087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // V6KZ add features monotonically.
55187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (new_cpu_arch <= CPU(V6KZ))
55287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return new_cpu_arch;
55387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
55487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return cpu_compatibility_table[old_cpu_arch][new_cpu_arch - CPU(V6T2)];
55587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
55687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#undef CPU
55787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
55887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/*
55987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Generic CPU name is used when Tag_CPU_name is unable to guess during the
56087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * merge of Tag_CPU_arch.
56187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines */
56287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic const char* generic_cpu_name_table[] = {
56337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* Pre v4    */ "Pre v4",
56437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* Pre v4    */ "ARM v4",
56537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v4T   */ "ARM v4T",
56637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v5T   */ "ARM v5T",
56737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v5TE  */ "ARM v5TE",
56837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v5TEJ */ "ARM v5TEJ",
56937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6    */ "ARM v6",
57037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6KZ  */ "ARM v6KZ",
57137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6T2  */ "ARM v6T2",
57237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6K   */ "ARM v6K",
57337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v7    */ "ARM v7",
57437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6-M  */ "ARM v6-M",
57537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v6S-M */ "ARM v6S-M",
57637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v7E-M */ "ARM v7E-M",
57737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* ARM v8    */ "ARM v8",
57887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
57987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
58087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic const char* get_generic_cpu_name(int cpu_arch) {
581533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  assert(static_cast<size_t>(cpu_arch) <
582533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines         (sizeof(generic_cpu_name_table) / sizeof(generic_cpu_name_table[0])));
58387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return generic_cpu_name_table[cpu_arch];
58487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
58587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
58687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/*
58787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Helper functions & data used in the merge of two different FP arch.
58887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines */
58987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic const struct fp_config_data {
59087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int version;
59187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int regs;
59287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines} fp_configs[] = {
59337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      {0, 0},
59437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      {1, 16},
59537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      {2, 16},
59637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      {3, 32},
59737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      {3, 16},
59837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      {4, 32},
59937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      {4, 16},
60037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      {8, 32},
60137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      {8, 16},
60287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
60387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
60487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic const size_t num_fp_configs =
60587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    sizeof(fp_configs) / sizeof(fp_config_data);
60687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
60787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Given h(x, y) = (x * (y >> 4) + (y >> 5))
60887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//
60987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// fp_config_hash_table[ h(0, 0)  =  0 ] = 0
61087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// fp_config_hash_table[ h(1, 16) =  1 ] = 1
61187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// fp_config_hash_table[ h(2, 16) =  2 ] = 2
61287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// fp_config_hash_table[ h(3, 32) =  7 ] = 3
61387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// fp_config_hash_table[ h(3, 16) =  3 ] = 4
61487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// fp_config_hash_table[ h(4, 32) =  9 ] = 5
61587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// fp_config_hash_table[ h(4, 16) =  4 ] = 6
61687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// fp_config_hash_table[ h(8, 32) = 17 ] = 7
61787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// fp_config_hash_table[ h(8, 16) =  8 ] = 8
61887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//
61987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// h(0, 0) = 0
62037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic const uint8_t fp_config_hash_table[] = {
62187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#define UND static_cast<uint8_t>(-1)
62237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /*  0 */ 0,
62337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /*  1 */ 1,
62437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /*  2 */ 2,
62537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /*  3 */ 4,
62637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /*  4 */ 6,
62737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /*  5 */ UND,
62837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /*  6 */ UND,
62937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /*  7 */ 3,
63037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /*  8 */ 8,
63137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /*  9 */ 5,
63237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* 10 */ UND,
63337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* 11 */ UND,
63437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* 12 */ UND,
63537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* 13 */ UND,
63637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* 14 */ UND,
63737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* 15 */ UND,
63837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* 16 */ UND,
63937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    /* 17 */ 7,
64087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#undef UND
64187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
64287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
64337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic int calculate_fp_config_hash(const struct fp_config_data& pConfig) {
64487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int x = pConfig.version;
64587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int y = pConfig.regs;
64687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return (x * (y >> 4) + (y >> 5));
64787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
64887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
64937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic int get_fp_arch_of_config(const struct fp_config_data& pConfig) {
65087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int hash = calculate_fp_config_hash(pConfig);
65137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(static_cast<size_t>(hash) <
65237b74a387bb3993387029859c2d9d051c41c724eStephen Hines         llvm::array_lengthof(fp_config_hash_table));
65387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return fp_config_hash_table[hash];
65487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
65587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
65637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic bool is_allowed_use_of_div(int cpu_arch,
65737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  int cpu_arch_profile,
65887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                  int div_use) {
65987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // 0: The code was permitted to use SDIV and UDIV in the Thumb ISA on v7-R or
66087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //    v7-M.
66187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // 1: The code was not permitted to use SDIV and UDIV.
66287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // 2: The code was explicitly permitted to use SDIV and UDIV.
66387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  switch (div_use) {
66487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case 0: {
66587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if ((cpu_arch == ARMELFAttributeData::CPU_Arch_ARM_V7) &&
66687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          ((cpu_arch_profile == 'R') || (cpu_arch_profile == 'M'))) {
66787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        return true;
66887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      } else {
66987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        return (cpu_arch >= ARMELFAttributeData::CPU_Arch_ARM_V7E_M);
67087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
67187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
67287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case 1: {
67387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return false;
67487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
67587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case 2:
67687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // For future proofing
67737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    default: { return true; }
67887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
67987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
68087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
68137b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // anonymous namespace
68287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
68387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
68487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// End Helper Functions for postMerge()
68587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
68687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
68787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool ARMELFAttributeData::postMerge(const LinkerConfig& pConfig,
68837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    const Input& pInput) {
68987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Process Tag_CPU_arch, Tag_CPU_name, Tag_CPU_raw_name, and
69087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Tag_also_compatible_with.
69137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ELFAttributeValue& out_cpu_arch_attr = m_Attrs[Tag_CPU_arch];
69237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ELFAttributeValue& out_secondary_compatibility_attr =
69387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Attrs[Tag_also_compatible_with];
69487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
69587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if ((m_CurrentCPUArch < 0) && out_cpu_arch_attr.isInitialized()) {
69687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Current input initializes the value of Tag_CPU_arch. Validate it.
69787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int out_cpu_arch = out_cpu_arch_attr.getIntValue();
69887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
69987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (out_cpu_arch > CPU_Arch_Max) {
70087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      error(diag::error_unknown_cpu_arch) << pInput.name();
70187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return false;
70287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
70387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
70487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Initialize m_CurrentCPUArch.
70587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int out_secondary_arch = -1;
70687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (out_secondary_compatibility_attr.isInitialized())
70787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      out_secondary_arch = decode_secondary_compatibility_attribute(
70837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          out_secondary_compatibility_attr);
70987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
71087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_CurrentCPUArch = calculate_cpu_arch(out_cpu_arch, out_secondary_arch);
71187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
71287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
71387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (m_CPUArch >= 0) {
71487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(out_cpu_arch_attr.isInitialized() && "CPU arch has never set!");
71587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(m_CurrentCPUArch >= 0);
71687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
71787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int in_cpu_arch = calculate_cpu_arch(m_CPUArch, m_SecondaryCPUArch);
71887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int result_cpu_arch = merge_cpu_arch(m_CurrentCPUArch, in_cpu_arch);
71987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
72087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (result_cpu_arch < 0) {
72137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      warning(diag::warn_mismatch_cpu_arch_profile) << in_cpu_arch
72237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                    << pInput.name();
72387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    } else {
72487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (result_cpu_arch != m_CurrentCPUArch) {
72587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Value of Tag_CPU_arch are going to changea.
72687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        m_CurrentCPUArch = result_cpu_arch;
72787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
72887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Write the result value to the output.
72987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (result_cpu_arch == CPU_Arch_ARM_V4T_Plus_V6_M) {
73087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_cpu_arch_attr.setIntValue(CPU_Arch_ARM_V4T);
73187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          encode_secondary_compatibility_attribute(
73287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              out_secondary_compatibility_attr, CPU_Arch_ARM_V6_M);
73387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        } else {
73487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_cpu_arch_attr.setIntValue(result_cpu_arch);
73587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          encode_secondary_compatibility_attribute(
73687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              out_secondary_compatibility_attr, -1);
73787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
73887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
73937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ELFAttributeValue& out_cpu_name = m_Attrs[Tag_CPU_name];
74037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ELFAttributeValue& out_cpu_raw_name = m_Attrs[Tag_CPU_raw_name];
74187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
74287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (m_CurrentCPUArch != in_cpu_arch) {
74387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // Unable to guess the Tag_CPU_name. Use the generic name.
74487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (out_cpu_name.isInitialized()) {
74587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            out_cpu_name.setStringValue(get_generic_cpu_name(m_CurrentCPUArch));
74687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          }
74787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
74887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // Tag_CPU_raw_name becomes unknown. Set to default value to disable
74987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // it.
75087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_cpu_raw_name.setStringValue("");
75187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        } else {
75287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // Use the value of Tag_CPU_name and Tag_CPU_raw_name from the input.
75387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (!m_CPUName.empty()) {
75437b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ELFAttributeValue& out_cpu_name = m_Attrs[Tag_CPU_name];
75587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            assert(out_cpu_name.isInitialized() && "CPU name has never set!");
75687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            out_cpu_name.setStringValue(m_CPUName);
75787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          }
75887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
75987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (!m_CPURawName.empty()) {
76037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ELFAttributeValue& out_cpu_raw_name = m_Attrs[Tag_CPU_raw_name];
76187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            assert(out_cpu_raw_name.isInitialized() &&
76287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                   "CPU raw name has never set!");
76387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            out_cpu_raw_name.setStringValue(m_CPURawName);
76487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          }
76587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
76687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
76787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
76837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // (m_CPUArch >= 0)
76987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
77087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Process Tag_ABI_VFP_args.
77187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (m_VFPArgs >= 0) {
77237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    ELFAttributeValue& out_attr = m_Attrs[Tag_ABI_VFP_args];
77337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    ELFAttributeValue& out_float_number_model_attr =
77487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        m_Attrs[Tag_ABI_FP_number_model];
77587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
77687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(out_attr.isInitialized() && "VFP args has never set!");
77787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
77887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // If the output is not permitted to use floating number, this attribute
77987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // is ignored (migrate the value from input directly.)
78087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (out_float_number_model_attr.isUninitialized() ||
78187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (out_float_number_model_attr.getIntValue() == 0)) {
78287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Inherit requirement from input.
78387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      out_attr.setIntValue(m_VFPArgs);
78487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    } else {
78587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (pConfig.options().warnMismatch())
78687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        warning(diag::warn_mismatch_vfp_args) << pInput.name();
78787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
78887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
78987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
79087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Process Tag_FP_arch.
79137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ELFAttributeValue& out_fp_arch_attr = m_Attrs[Tag_FP_arch];
79287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (m_FPArch >= 0) {
79387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(out_fp_arch_attr.isInitialized() && "FP arch has never set!");
79487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
79587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_FP_arch
79687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    //  0: instructions requiring FP hardware are not permitted
79787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    //  1: VFP1
79887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    //  2: VFP2
79987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    //  3: VFP3 D32
80087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    //  4: VFP3 D16
80187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    //  5: VFP4 D32
80287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    //  6: VFP4 D16
80387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    //  7: ARM v8-A D32
80487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    //  8: ARM v8-A D16
80587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (out_fp_arch_attr.getIntValue() == 0) {
80687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Output has no constraints on FP hardware. Copy the requirement from
80787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // input.
80887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      out_fp_arch_attr.setIntValue(m_FPArch);
80987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    } else if (m_FPArch == 0) {
81087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Input has no constraints on FP hardware. Do nothing.
81187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    } else {
81287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // If here, both output and input contain non-zero value of Tag_FP_arch.
81387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
81487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Version greater than num_fp_configs is not defined. Choose the greater
81587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // one for future-proofing.
81687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (static_cast<unsigned>(m_FPArch) > num_fp_configs) {
81787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (static_cast<unsigned>(m_FPArch) > out_fp_arch_attr.getIntValue()) {
81887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_fp_arch_attr.setIntValue(m_FPArch);
81987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
82087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      } else {
82187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (out_fp_arch_attr.getIntValue() < num_fp_configs) {
82237b74a387bb3993387029859c2d9d051c41c724eStephen Hines          const struct fp_config_data& input_fp_config = fp_configs[m_FPArch];
82387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
82437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          const struct fp_config_data& output_fp_config =
82537b74a387bb3993387029859c2d9d051c41c724eStephen Hines              fp_configs[out_fp_arch_attr.getIntValue()];
82687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
82787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          const struct fp_config_data result_fp_config = {
82837b74a387bb3993387029859c2d9d051c41c724eStephen Hines              /*version*/ ((output_fp_config.version > input_fp_config.version)
82937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               ? output_fp_config.version
83037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               : input_fp_config.version),
83137b74a387bb3993387029859c2d9d051c41c724eStephen Hines              /* regs */ ((output_fp_config.regs > input_fp_config.regs)
83237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                              ? output_fp_config.regs
83337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                              : input_fp_config.regs),
83487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          };
83587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // Find the attribute value corresponding the result_fp_config
83687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_fp_arch_attr.setIntValue(get_fp_arch_of_config(result_fp_config));
83787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
83887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
83987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
84037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // (m_FPArch >= 0)
84187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
84287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Process Tag_ABI_HardFP_use.
84337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ELFAttributeValue& out_hardfp_use_attr = m_Attrs[Tag_ABI_HardFP_use];
84487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
84587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!m_HardFPUseInitialized && out_hardfp_use_attr.isInitialized()) {
84687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_HardFPUse = out_hardfp_use_attr.getIntValue();
84787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_HardFPUseInitialized = true;
84887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
84987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
85087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (m_HardFPUse >= 0) {
85187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Tag_ABI_HardFP_use depends on the meaning of Tag_FP_arch when it's 0.
85287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(out_hardfp_use_attr.isInitialized() && "HardFP use has never set!");
85387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
85487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (out_fp_arch_attr.isUninitialized() ||
85587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (out_fp_arch_attr.getIntValue() == 0)) {
85687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Has no constraints on FP hardware.
85787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      out_hardfp_use_attr.setIntValue(m_HardFPUse);
85887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    } else {
85987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Both output and input contain non-zero value of Tag_FP_arch and we have
86087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // different Tag_ABI_HaedFP_Use settings other than 0.
86187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if ((out_fp_arch_attr.getIntValue() > 0) && (m_HardFPUse > 0))
86287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Promote to 3 (The user permitted this entity to use both SP and DP
86387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // VFP instruction.)
86487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        out_hardfp_use_attr.setIntValue(3);
86587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
86687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
86787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
86887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Move the value of Tag_MPextension_use_legacy to Tag_MPextension_use.
86937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ELFAttributeValue& out_mpextension_use_legacy =
87087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_Attrs[Tag_MPextension_use_legacy];
87187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
87237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ELFAttributeValue& out_mpextension_use = m_Attrs[Tag_MPextension_use];
87387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
87487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // If Tag_MPextension_use_legacy has value, it must be introduced by current
87587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // input since it is reset every time after the merge completed.
87687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (out_mpextension_use_legacy.isInitialized()) {
87787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (out_mpextension_use.isInitialized()) {
87887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (m_MPextensionUse < 0) {
87987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // The value of Tag_MPextension_use is introduced by the current input.
88087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Check whether it is consistent with the one set in legacy.
88187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        m_MPextensionUse = out_mpextension_use.getIntValue();
88287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      } else {
88387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Current input introduces value of Tag_MPextension_use in
88487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // m_MPextensionUse.
88587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
88687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
88787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Check the consistency between m_MPextensionUse and the value of
88887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Tag_MPextension_use_legacy.
88987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (static_cast<unsigned>(m_MPextensionUse) !=
89037b74a387bb3993387029859c2d9d051c41c724eStephen Hines          out_mpextension_use_legacy.getIntValue()) {
89187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        error(diag::error_mismatch_mpextension_use) << pInput.name();
89287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        return false;
89387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
89487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    } else {
89587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (m_MPextensionUse < 0) {
89687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Tag_MPextension_use is not set. Initialize it and move the value.
89787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        out_mpextension_use.setType(ELFAttributeValue::Int);
89887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        out_mpextension_use.setIntValue(out_mpextension_use.getIntValue());
89987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      } else {
90087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Unreachable case since the value to unitialized attribute is directly
90187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // assigned in ELFAttribute::Subsection::merge().
90287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        assert(false && "Tag_MPextension_use is uninitialized but have value?");
90387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
90487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
90587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
90687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Reset the attribute to uninitialized so it won't be included in the
90787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // output.
90887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    out_mpextension_use_legacy.setType(ELFAttributeValue::Uninitialized);
90987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
91087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
91187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Process Tag_MPextension_use.
91287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (m_MPextensionUse > 0) {
91387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(out_mpextension_use.isInitialized());
91487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
91587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (static_cast<unsigned>(m_MPextensionUse) >
91637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        out_mpextension_use.getIntValue()) {
91787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      out_mpextension_use.setIntValue(m_MPextensionUse);
91887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
91987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
92087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
92187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Process Tag_DIV_use.
92237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ELFAttributeValue& out_div_use_attr = m_Attrs[Tag_DIV_use];
92387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
92487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!m_DIVUseInitialized && out_div_use_attr.isInitialized()) {
92587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Perform the merge by reverting value of Tag_DIV_use and setup m_DIVUse.
92687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_DIVUse = out_div_use_attr.getIntValue();
92787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    out_div_use_attr.setIntValue(0);
92887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_DIVUseInitialized = true;
92987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
93087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
93187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (m_DIVUse >= 0) {
93287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(out_div_use_attr.isInitialized());
93387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
93437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const ELFAttributeValue& out_cpu_arch_profile_attr =
93587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        m_Attrs[Tag_CPU_arch_profile];
93687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
93787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int out_cpu_arch_profile = Arch_Profile_None;
93887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (out_cpu_arch_profile_attr.isInitialized()) {
93987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      out_cpu_arch_profile = out_cpu_arch_profile_attr.getIntValue();
94087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
94187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
94287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (m_DIVUse == 1) {
94387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Input (=1) was not permitted to use SDIV and UDIV. See whether current
94487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // output was explicitly permitted the use.
94537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (!is_allowed_use_of_div(m_CurrentCPUArch,
94637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                 out_cpu_arch_profile,
94787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                 out_div_use_attr.getIntValue())) {
94887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        out_div_use_attr.setIntValue(1);
94987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
95087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    } else {
95187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (out_div_use_attr.getIntValue() != 1) {
95287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Output does not explicitly forbid the use of SDIV/UDIV. See whether
95387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // the input attribute can allow it under current CPU architecture
95487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // profile.
95537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (is_allowed_use_of_div(
95637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                m_CurrentCPUArch, out_cpu_arch_profile, m_DIVUse)) {
95787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          out_div_use_attr.setIntValue(m_DIVUse);
95887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
95987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
96087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
96187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
96287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
96387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
96487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
96587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
96687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinessize_t ARMELFAttributeData::sizeOutput() const {
96787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  size_t result = 0;
96887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
96987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Size contributed by known attributes
97087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (unsigned i = 0; i <= Tag_Max; ++i) {
97187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    TagType tag = static_cast<TagType>(i);
97237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const ELFAttributeValue& value = m_Attrs[tag];
97387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
97487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (value.shouldEmit()) {
97587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      result += leb128::size(static_cast<uint32_t>(tag));
97687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      result += value.getSize();
97787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
97887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
97987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
98087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Size contributed by unknown attributes
98187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (UnknownAttrsMap::const_iterator unknown_attr_it = m_UnknownAttrs.begin(),
98237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       unknown_attr_end = m_UnknownAttrs.end();
98337b74a387bb3993387029859c2d9d051c41c724eStephen Hines       unknown_attr_it != unknown_attr_end;
98437b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++unknown_attr_it) {
98587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    TagType tag = unknown_attr_it->first;
98637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const ELFAttributeValue& value = unknown_attr_it->second;
98787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
98887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (value.shouldEmit()) {
98987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      result += leb128::size(static_cast<uint32_t>(tag));
99087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      result += value.getSize();
99187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
99287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
99387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
99487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return result;
99587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
99687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
99737b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t ARMELFAttributeData::emit(char* pBuf) const {
99837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  char* buffer = pBuf;
99987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
100087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Tag_conformance "should be emitted first in a file-scope sub-subsection of
100187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // the first public subsection of the attribute section."
100287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //
100387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // See ARM [ABI-addenda], 2.3.7.4 Conformance tag
100437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const ELFAttributeValue& attr_conformance = m_Attrs[Tag_conformance];
100587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
100687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (attr_conformance.shouldEmit()) {
100737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (!ELFAttributeData::WriteAttribute(
100837b74a387bb3993387029859c2d9d051c41c724eStephen Hines            Tag_conformance, attr_conformance, buffer)) {
100987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return 0;
101087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
101187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
101287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
101387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Tag_nodefaults "should be emitted before any other tag in an attribute
101487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // subsection other that the conformance tag"
101587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //
101687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // See ARM [ABI-addenda], 2.3.7.5 No defaults tag
101737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const ELFAttributeValue& attr_nodefaults = m_Attrs[Tag_nodefaults];
101887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
101987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (attr_nodefaults.shouldEmit()) {
102037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (!ELFAttributeData::WriteAttribute(
102137b74a387bb3993387029859c2d9d051c41c724eStephen Hines            Tag_nodefaults, attr_nodefaults, buffer)) {
102287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return 0;
102387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
102487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
102587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
102687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Tag_conformance (=67)
102787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Tag_nodefaults (=64)
102887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (unsigned i = 0; i < Tag_nodefaults; ++i) {
102987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    TagType tag = static_cast<TagType>(i);
103037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const ELFAttributeValue& value = m_Attrs[tag];
103187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
103287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (value.shouldEmit() &&
103387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        !ELFAttributeData::WriteAttribute(tag, value, buffer)) {
103487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return 0;
103587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
103687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
103787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
103887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (unsigned i = (Tag_nodefaults + 1); i <= Tag_Max; ++i) {
103987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    TagType tag = static_cast<TagType>(i);
104037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const ELFAttributeValue& value = m_Attrs[tag];
104187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
104287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (value.shouldEmit() && (i != Tag_conformance) &&
104387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        !ELFAttributeData::WriteAttribute(tag, value, buffer)) {
104487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return 0;
104587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
104687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
104787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
104887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (UnknownAttrsMap::const_iterator unknown_attr_it = m_UnknownAttrs.begin(),
104937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       unknown_attr_end = m_UnknownAttrs.end();
105037b74a387bb3993387029859c2d9d051c41c724eStephen Hines       unknown_attr_it != unknown_attr_end;
105137b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++unknown_attr_it) {
105287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    TagType tag = unknown_attr_it->first;
105337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const ELFAttributeValue& value = unknown_attr_it->second;
105487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
105587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (value.shouldEmit() &&
105687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        !ELFAttributeData::WriteAttribute(tag, value, buffer)) {
105787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return 0;
105887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
105987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
106087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
106187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return (buffer - pBuf);
106287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
10630dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
106437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ARMELFAttributeData::usingThumb() const {
10650dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  int arch = m_Attrs[Tag_CPU_arch].getIntValue();
10660dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  if ((arch == CPU_Arch_ARM_V6_M) || (arch == CPU_Arch_ARM_V6S_M))
10670dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    return true;
10680dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  if ((arch != CPU_Arch_ARM_V7) && (arch != CPU_Arch_ARM_V7E_M))
10690dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    return false;
10700dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
10710dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  arch = m_Attrs[Tag_CPU_arch_profile].getIntValue();
10720dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  return arch == Arch_Profile_Microcontroller;
10730dea6bc96bb52346737966839ac68644f7939f58Stephen Hines}
10740dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
107537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ARMELFAttributeData::usingThumb2() const {
10760dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  int arch = m_Attrs[Tag_CPU_arch].getIntValue();
10770dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  return (arch == CPU_Arch_ARM_V6T2) || (arch == CPU_Arch_ARM_V7);
10780dea6bc96bb52346737966839ac68644f7939f58Stephen Hines}
107937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
108037b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
1081