Compiler projects using llvm
//===-- CSKYAttributeParser.cpp - CSKY Attribute Parser -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/CSKYAttributeParser.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Errc.h"

using namespace llvm;

const CSKYAttributeParser::DisplayHandler
    CSKYAttributeParser::displayRoutines[] = {
        {
            CSKYAttrs::CSKY_ARCH_NAME,
            &ELFAttributeParser::stringAttribute,
        },
        {
            CSKYAttrs::CSKY_CPU_NAME,
            &ELFAttributeParser::stringAttribute,
        },
        {
            CSKYAttrs::CSKY_ISA_FLAGS,
            &ELFAttributeParser::integerAttribute,
        },
        {
            CSKYAttrs::CSKY_ISA_EXT_FLAGS,
            &ELFAttributeParser::integerAttribute,
        },
        {
            CSKYAttrs::CSKY_DSP_VERSION,
            &CSKYAttributeParser::dspVersion,
        },
        {
            CSKYAttrs::CSKY_VDSP_VERSION,
            &CSKYAttributeParser::vdspVersion,
        },
        {
            CSKYAttrs::CSKY_FPU_VERSION,
            &CSKYAttributeParser::fpuVersion,
        },
        {
            CSKYAttrs::CSKY_FPU_ABI,
            &CSKYAttributeParser::fpuABI,
        },
        {
            CSKYAttrs::CSKY_FPU_ROUNDING,
            &CSKYAttributeParser::fpuRounding,
        },
        {
            CSKYAttrs::CSKY_FPU_DENORMAL,
            &CSKYAttributeParser::fpuDenormal,
        },
        {
            CSKYAttrs::CSKY_FPU_EXCEPTION,
            &CSKYAttributeParser::fpuException,
        },
        {
            CSKYAttrs::CSKY_FPU_NUMBER_MODULE,
            &ELFAttributeParser::stringAttribute,
        },
        {
            CSKYAttrs::CSKY_FPU_HARDFP,
            &CSKYAttributeParser::fpuHardFP,
        }};

Error CSKYAttributeParser::handler(uint64_t tag, bool &handled) {
  handled = false;
  for (unsigned AHI = 0, AHE = array_lengthof(displayRoutines); AHI != AHE;
       ++AHI) {
    if (uint64_t(displayRoutines[AHI].attribute) == tag) {
      if (Error e = (this->*displayRoutines[AHI].routine)(tag))
        return e;
      handled = true;
      break;
    }
  }

  return Error::success();
}

Error CSKYAttributeParser::dspVersion(unsigned tag) {
  static const char *strings[] = {"Error", "DSP Extension", "DSP 2.0"};
  return parseStringAttribute("Tag_CSKY_DSP_VERSION", tag,
                              makeArrayRef(strings));
}

Error CSKYAttributeParser::vdspVersion(unsigned tag) {
  static const char *strings[] = {"Error", "VDSP Version 1", "VDSP Version 2"};
  return parseStringAttribute("Tag_CSKY_VDSP_VERSION", tag,
                              makeArrayRef(strings));
}

Error CSKYAttributeParser::fpuVersion(unsigned tag) {
  static const char *strings[] = {"Error", "FPU Version 1", "FPU Version 2",
                                  "FPU Version 3"};
  return parseStringAttribute("Tag_CSKY_FPU_VERSION", tag,
                              makeArrayRef(strings));
}

Error CSKYAttributeParser::fpuABI(unsigned tag) {
  static const char *strings[] = {"Error", "Soft", "SoftFP", "Hard"};
  return parseStringAttribute("Tag_CSKY_FPU_ABI", tag, makeArrayRef(strings));
}

Error CSKYAttributeParser::fpuRounding(unsigned tag) {
  static const char *strings[] = {"None", "Needed"};
  return parseStringAttribute("Tag_CSKY_FPU_ROUNDING", tag,
                              makeArrayRef(strings));
}

Error CSKYAttributeParser::fpuDenormal(unsigned tag) {
  static const char *strings[] = {"None", "Needed"};
  return parseStringAttribute("Tag_CSKY_FPU_DENORMAL", tag,
                              makeArrayRef(strings));
}

Error CSKYAttributeParser::fpuException(unsigned tag) {
  static const char *strings[] = {"None", "Needed"};
  return parseStringAttribute("Tag_CSKY_FPU_EXCEPTION", tag,
                              makeArrayRef(strings));
}

Error CSKYAttributeParser::fpuHardFP(unsigned tag) {
  uint64_t value = de.getULEB128(cursor);
  ListSeparator LS(" ");

  std::string description;

  if (value & 0x1) {
    description += LS;
    description += "Half";
  }
  if ((value >> 1) & 0x1) {
    description += LS;
    description += "Single";
  }
  if ((value >> 2) & 0x1) {
    description += LS;
    description += "Double";
  }

  if (description.empty()) {
    printAttribute(tag, value, "");
    return createStringError(errc::invalid_argument,
                             "unknown Tag_CSKY_FPU_HARDFP value: " +
                                 Twine(value));
  }

  printAttribute(tag, value, description);
  return Error::success();
}