void ARMAttributeParser::ParseAttributeList(const uint8_t *Data,
                                            uint32_t &Offset, uint32_t Length) {
  while (Offset < Length) {
    unsigned Length;
    uint64_t Tag = decodeULEB128(Data + Offset, &Length);
    Offset += Length;

    bool Handled = false;
    for (unsigned AHI = 0, AHE = array_lengthof(DisplayRoutines);
         AHI != AHE && !Handled; ++AHI) {
      if (DisplayRoutines[AHI].Attribute == Tag) {
        (this->*DisplayRoutines[AHI].Routine)(ARMBuildAttrs::AttrType(Tag),
                                              Data, Offset);
        Handled = true;
        break;
      }
    }
    if (!Handled) {
      if (Tag < 32) {
        errs() << "unhandled AEABI Tag " << Tag
               << " (" << ARMBuildAttrs::AttrTypeAsString(Tag) << ")\n";
        continue;
      }

      if (Tag % 2 == 0)
        IntegerAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset);
      else
        StringAttribute(ARMBuildAttrs::AttrType(Tag), Data, Offset);
    }
  }
}
void ARMAttributeParser::CPU_unaligned_access(AttrType Tag, const uint8_t *Data,
                                              uint32_t &Offset) {
  static const char *const Strings[] = { "Not Permitted", "v6-style" };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::FP_HP_extension(AttrType Tag, const uint8_t *Data,
                                         uint32_t &Offset) {
  static const char *const Strings[] = { "If Available", "Permitted" };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_FP_rounding(AttrType Tag, const uint8_t *Data,
                                         uint32_t &Offset) {
  static const char *Strings[] = { "IEEE-754", "Runtime" };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_WMMX_args(AttrType Tag, const uint8_t *Data,
                                       uint32_t &Offset) {
  static const char *Strings[] = { "AAPCS", "iWMMX", "Custom" };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_FP_denormal(AttrType Tag, const uint8_t *Data,
                                         uint32_t &Offset) {
  static const char *Strings[] = { "Unsupported", "IEEE-754", "Sign Only" };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_FP_16bit_format(AttrType Tag, const uint8_t *Data,
                                             uint32_t &Offset) {
  static const char *Strings[] = { "Not Permitted", "IEEE-754", "VFPv3" };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_PCS_R9_use(AttrType Tag, const uint8_t *Data,
                                        uint32_t &Offset) {
  static const char *Strings[] = { "v6", "Static Base", "TLS", "Unused" };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::T2EE_use(AttrType Tag, const uint8_t *Data,
                                  uint32_t &Offset) {
  static const char *Strings[] = { "Not Permitted", "Permitted" };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_enum_size(AttrType Tag, const uint8_t *Data,
                                       uint32_t &Offset) {
  static const char *const Strings[] = {
    "Not Permitted", "Packed", "Int32", "External Int32"
  };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_PCS_RW_data(AttrType Tag, const uint8_t *Data,
                                         uint32_t &Offset) {
  static const char *Strings[] = {
    "Absolute", "PC-relative", "SB-relative", "Not Permitted"
  };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::Advanced_SIMD_arch(AttrType Tag, const uint8_t *Data,
                                            uint32_t &Offset) {
  static const char *Strings[] = {
    "Not Permitted", "NEONv1", "NEONv2+FMA", "ARMv8-a NEON"
  };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_HardFP_use(AttrType Tag, const uint8_t *Data,
                                        uint32_t &Offset) {
  static const char *Strings[] = {
    "Tag_FP_arch", "Single-Precision", "Reserved", "Tag_FP_arch (deprecated)"
  };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_FP_number_model(AttrType Tag, const uint8_t *Data,
                                             uint32_t &Offset) {
  static const char *Strings[] = {
    "Not Permitted", "Finite Only", "RTABI", "IEEE-754"
  };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_PCS_wchar_t(AttrType Tag, const uint8_t *Data,
                                         uint32_t &Offset) {
  static const char *const Strings[] = {
    "Not Permitted", "Unknown", "2-byte", "Unknown", "4-byte"
  };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::Virtualization_use(AttrType Tag, const uint8_t *Data,
                                            uint32_t &Offset) {
  static const char *Strings[] = {
    "Not Permitted", "TrustZone", "Virtualization Extensions",
    "TrustZone + Virtualization Extensions"
  };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::PCS_config(AttrType Tag, const uint8_t *Data,
                                    uint32_t &Offset) {
  static const char *Strings[] = {
    "None", "Bare Platform", "Linux Application", "Linux DSO", "Palm OS 2004",
    "Reserved (Palm OS)", "Symbian OS 2004", "Reserved (Symbian OS)"
  };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::FP_arch(AttrType Tag, const uint8_t *Data,
                                 uint32_t &Offset) {
  static const char *Strings[] = {
    "Not Permitted", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4",
    "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16"
  };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::CPU_arch(AttrType Tag, const uint8_t *Data,
                                  uint32_t &Offset) {
  static const char *Strings[] = {
    "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", "ARM v6",
    "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", "ARM v6S-M",
    "ARM v7E-M", "ARM v8"
  };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_FP_optimization_goals(AttrType Tag,
                                                   const uint8_t *Data,
                                                   uint32_t &Offset) {
  static const char *Strings[] = {
    "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Accuracy",
    "Best Accuracy"
  };

  uint64_t Value = ParseInteger(Data, Offset);
  StringRef ValueDesc =
    (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr;
  PrintAttribute(Tag, Value, ValueDesc);
}
void ARMAttributeParser::ABI_align_needed(AttrType Tag, const uint8_t *Data,
                                          uint32_t &Offset) {
  static const char *Strings[] = {
    "Not Permitted", "8-byte alignment", "4-byte alignment", "Reserved"
  };

  uint64_t Value = ParseInteger(Data, Offset);

  std::string Description;
  if (Value < array_lengthof(Strings))
    Description = std::string(Strings[Value]);
  else if (Value <= 12)
    Description = std::string("8-byte alignment, ") + utostr(1 << Value)
                + std::string("-byte extended alignment");
  else
    Description = "Invalid";

  PrintAttribute(Tag, Value, Description);
}