How many place you need to modify when implementing a new extension for RISC-V? At least 7 places as I know: - Add new SubtargetFeature at RISCV.td - -march parser in RISCV.cpp - RISCVTargetInfo::initFeatureMap@RISCV.cpp for handling feature vector. - RISCVTargetInfo::getTargetDefines@RISCV.cpp for pre-define marco. - Arch string parser for ELF attribute in RISCVAsmParser.cpp - ELF attribute emittion in RISCVAsmParser.cpp, and make sure it's in canonical order... - ELF attribute emittion in RISCVTargetStreamer.cpp, and again, must in canonical order... And now, this patch provide an unified infrastructure for handling (almost) everything of RISC-V arch string. After this patch, you only need to update 2 places for implement an extension for RISC-V: - Add new SubtargetFeature at RISCV.td, hmmm, it's hard to avoid. - Add new entry to RISCVSupportedExtension@RISCVISAInfo.cpp or SupportedExperimentalExtensions@RISCVISAInfo.cpp . Most codes are come from existing -march parser, but with few new feature/bug fixes: - Accept version for -march, e.g. -march=rv32i2p0. - Reject version info with `p` but without minor version number like `rv32i2p`. Differential Revision: https://reviews.llvm.org/D105168
114 lines
4.1 KiB
C++
114 lines
4.1 KiB
C++
//===-- RISCVTargetStreamer.cpp - RISCV Target Streamer Methods -----------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file provides RISCV specific target streamer methods.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "RISCVTargetStreamer.h"
|
|
#include "RISCVBaseInfo.h"
|
|
#include "RISCVMCTargetDesc.h"
|
|
#include "llvm/Support/FormattedStream.h"
|
|
#include "llvm/Support/RISCVAttributes.h"
|
|
#include "llvm/Support/RISCVISAInfo.h"
|
|
|
|
using namespace llvm;
|
|
|
|
RISCVTargetStreamer::RISCVTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
|
|
|
|
void RISCVTargetStreamer::finish() { finishAttributeSection(); }
|
|
|
|
void RISCVTargetStreamer::emitDirectiveOptionPush() {}
|
|
void RISCVTargetStreamer::emitDirectiveOptionPop() {}
|
|
void RISCVTargetStreamer::emitDirectiveOptionPIC() {}
|
|
void RISCVTargetStreamer::emitDirectiveOptionNoPIC() {}
|
|
void RISCVTargetStreamer::emitDirectiveOptionRVC() {}
|
|
void RISCVTargetStreamer::emitDirectiveOptionNoRVC() {}
|
|
void RISCVTargetStreamer::emitDirectiveOptionRelax() {}
|
|
void RISCVTargetStreamer::emitDirectiveOptionNoRelax() {}
|
|
void RISCVTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {}
|
|
void RISCVTargetStreamer::finishAttributeSection() {}
|
|
void RISCVTargetStreamer::emitTextAttribute(unsigned Attribute,
|
|
StringRef String) {}
|
|
void RISCVTargetStreamer::emitIntTextAttribute(unsigned Attribute,
|
|
unsigned IntValue,
|
|
StringRef StringValue) {}
|
|
|
|
void RISCVTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) {
|
|
if (STI.hasFeature(RISCV::FeatureRV32E))
|
|
emitAttribute(RISCVAttrs::STACK_ALIGN, RISCVAttrs::ALIGN_4);
|
|
else
|
|
emitAttribute(RISCVAttrs::STACK_ALIGN, RISCVAttrs::ALIGN_16);
|
|
|
|
unsigned XLen = STI.hasFeature(RISCV::Feature64Bit) ? 64 : 32;
|
|
std::vector<std::string> FeatureVector;
|
|
RISCVFeatures::toFeatureVector(FeatureVector, STI.getFeatureBits());
|
|
|
|
auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeatureVector);
|
|
if (!ParseResult) {
|
|
/* Assume any error about features should handled earlier. */
|
|
consumeError(ParseResult.takeError());
|
|
llvm_unreachable("Parsing feature error when emitTargetAttributes?");
|
|
} else {
|
|
auto &ISAInfo = *ParseResult;
|
|
emitTextAttribute(RISCVAttrs::ARCH, ISAInfo->toString());
|
|
}
|
|
}
|
|
|
|
// This part is for ascii assembly output
|
|
RISCVTargetAsmStreamer::RISCVTargetAsmStreamer(MCStreamer &S,
|
|
formatted_raw_ostream &OS)
|
|
: RISCVTargetStreamer(S), OS(OS) {}
|
|
|
|
void RISCVTargetAsmStreamer::emitDirectiveOptionPush() {
|
|
OS << "\t.option\tpush\n";
|
|
}
|
|
|
|
void RISCVTargetAsmStreamer::emitDirectiveOptionPop() {
|
|
OS << "\t.option\tpop\n";
|
|
}
|
|
|
|
void RISCVTargetAsmStreamer::emitDirectiveOptionPIC() {
|
|
OS << "\t.option\tpic\n";
|
|
}
|
|
|
|
void RISCVTargetAsmStreamer::emitDirectiveOptionNoPIC() {
|
|
OS << "\t.option\tnopic\n";
|
|
}
|
|
|
|
void RISCVTargetAsmStreamer::emitDirectiveOptionRVC() {
|
|
OS << "\t.option\trvc\n";
|
|
}
|
|
|
|
void RISCVTargetAsmStreamer::emitDirectiveOptionNoRVC() {
|
|
OS << "\t.option\tnorvc\n";
|
|
}
|
|
|
|
void RISCVTargetAsmStreamer::emitDirectiveOptionRelax() {
|
|
OS << "\t.option\trelax\n";
|
|
}
|
|
|
|
void RISCVTargetAsmStreamer::emitDirectiveOptionNoRelax() {
|
|
OS << "\t.option\tnorelax\n";
|
|
}
|
|
|
|
void RISCVTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
|
|
OS << "\t.attribute\t" << Attribute << ", " << Twine(Value) << "\n";
|
|
}
|
|
|
|
void RISCVTargetAsmStreamer::emitTextAttribute(unsigned Attribute,
|
|
StringRef String) {
|
|
OS << "\t.attribute\t" << Attribute << ", \"" << String << "\"\n";
|
|
}
|
|
|
|
void RISCVTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute,
|
|
unsigned IntValue,
|
|
StringRef StringValue) {}
|
|
|
|
void RISCVTargetAsmStreamer::finishAttributeSection() {}
|