106c3fb27SDimitry Andric //===-- RISCVTargetStreamer.cpp - RISC-V Target Streamer Methods ----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
906c3fb27SDimitry Andric // This file provides RISC-V specific target streamer methods.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "RISCVTargetStreamer.h"
14349cc55cSDimitry Andric #include "RISCVBaseInfo.h"
15e8d8bef9SDimitry Andric #include "RISCVMCTargetDesc.h"
16bdd1243dSDimitry Andric #include "llvm/MC/MCSymbol.h"
17*0fca6ea1SDimitry Andric #include "llvm/Support/CommandLine.h"
180b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h"
195ffd83dbSDimitry Andric #include "llvm/Support/RISCVAttributes.h"
20*0fca6ea1SDimitry Andric #include "llvm/TargetParser/RISCVISAInfo.h"
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric
24*0fca6ea1SDimitry Andric // This option controls wether or not we emit ELF attributes for ABI features,
25*0fca6ea1SDimitry Andric // like RISC-V atomics or X3 usage.
26*0fca6ea1SDimitry Andric static cl::opt<bool> RiscvAbiAttr(
27*0fca6ea1SDimitry Andric "riscv-abi-attributes",
28*0fca6ea1SDimitry Andric cl::desc("Enable emitting RISC-V ELF attributes for ABI features"),
29*0fca6ea1SDimitry Andric cl::Hidden);
30*0fca6ea1SDimitry Andric
RISCVTargetStreamer(MCStreamer & S)310b57cec5SDimitry Andric RISCVTargetStreamer::RISCVTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
320b57cec5SDimitry Andric
finish()335ffd83dbSDimitry Andric void RISCVTargetStreamer::finish() { finishAttributeSection(); }
reset()3481ad6265SDimitry Andric void RISCVTargetStreamer::reset() {}
355ffd83dbSDimitry Andric
emitDirectiveOptionPush()365ffd83dbSDimitry Andric void RISCVTargetStreamer::emitDirectiveOptionPush() {}
emitDirectiveOptionPop()375ffd83dbSDimitry Andric void RISCVTargetStreamer::emitDirectiveOptionPop() {}
emitDirectiveOptionPIC()385ffd83dbSDimitry Andric void RISCVTargetStreamer::emitDirectiveOptionPIC() {}
emitDirectiveOptionNoPIC()395ffd83dbSDimitry Andric void RISCVTargetStreamer::emitDirectiveOptionNoPIC() {}
emitDirectiveOptionRVC()405ffd83dbSDimitry Andric void RISCVTargetStreamer::emitDirectiveOptionRVC() {}
emitDirectiveOptionNoRVC()415ffd83dbSDimitry Andric void RISCVTargetStreamer::emitDirectiveOptionNoRVC() {}
emitDirectiveOptionRelax()425ffd83dbSDimitry Andric void RISCVTargetStreamer::emitDirectiveOptionRelax() {}
emitDirectiveOptionNoRelax()435ffd83dbSDimitry Andric void RISCVTargetStreamer::emitDirectiveOptionNoRelax() {}
emitDirectiveOptionArch(ArrayRef<RISCVOptionArchArg> Args)4406c3fb27SDimitry Andric void RISCVTargetStreamer::emitDirectiveOptionArch(
4506c3fb27SDimitry Andric ArrayRef<RISCVOptionArchArg> Args) {}
emitDirectiveVariantCC(MCSymbol & Symbol)46bdd1243dSDimitry Andric void RISCVTargetStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {}
emitAttribute(unsigned Attribute,unsigned Value)475ffd83dbSDimitry Andric void RISCVTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {}
finishAttributeSection()485ffd83dbSDimitry Andric void RISCVTargetStreamer::finishAttributeSection() {}
emitTextAttribute(unsigned Attribute,StringRef String)495ffd83dbSDimitry Andric void RISCVTargetStreamer::emitTextAttribute(unsigned Attribute,
505ffd83dbSDimitry Andric StringRef String) {}
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)515ffd83dbSDimitry Andric void RISCVTargetStreamer::emitIntTextAttribute(unsigned Attribute,
525ffd83dbSDimitry Andric unsigned IntValue,
535ffd83dbSDimitry Andric StringRef StringValue) {}
setTargetABI(RISCVABI::ABI ABI)5481ad6265SDimitry Andric void RISCVTargetStreamer::setTargetABI(RISCVABI::ABI ABI) {
5581ad6265SDimitry Andric assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialized target ABI");
5681ad6265SDimitry Andric TargetABI = ABI;
5781ad6265SDimitry Andric }
585ffd83dbSDimitry Andric
setFlagsFromFeatures(const MCSubtargetInfo & STI)593a079333SDimitry Andric void RISCVTargetStreamer::setFlagsFromFeatures(const MCSubtargetInfo &STI) {
60*0fca6ea1SDimitry Andric HasRVC = STI.hasFeature(RISCV::FeatureStdExtC) ||
61*0fca6ea1SDimitry Andric STI.hasFeature(RISCV::FeatureStdExtZca);
623a079333SDimitry Andric HasTSO = STI.hasFeature(RISCV::FeatureStdExtZtso);
633a079333SDimitry Andric }
643a079333SDimitry Andric
emitTargetAttributes(const MCSubtargetInfo & STI,bool EmitStackAlign)6506c3fb27SDimitry Andric void RISCVTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI,
6606c3fb27SDimitry Andric bool EmitStackAlign) {
677a6dacacSDimitry Andric if (EmitStackAlign) {
68*0fca6ea1SDimitry Andric unsigned StackAlign;
697a6dacacSDimitry Andric if (TargetABI == RISCVABI::ABI_ILP32E)
70*0fca6ea1SDimitry Andric StackAlign = 4;
717a6dacacSDimitry Andric else if (TargetABI == RISCVABI::ABI_LP64E)
72*0fca6ea1SDimitry Andric StackAlign = 8;
737a6dacacSDimitry Andric else
74*0fca6ea1SDimitry Andric StackAlign = 16;
75*0fca6ea1SDimitry Andric emitAttribute(RISCVAttrs::STACK_ALIGN, StackAlign);
767a6dacacSDimitry Andric }
775ffd83dbSDimitry Andric
7881ad6265SDimitry Andric auto ParseResult = RISCVFeatures::parseFeatureBits(
7981ad6265SDimitry Andric STI.hasFeature(RISCV::Feature64Bit), STI.getFeatureBits());
80349cc55cSDimitry Andric if (!ParseResult) {
8181ad6265SDimitry Andric report_fatal_error(ParseResult.takeError());
82349cc55cSDimitry Andric } else {
83349cc55cSDimitry Andric auto &ISAInfo = *ParseResult;
84349cc55cSDimitry Andric emitTextAttribute(RISCVAttrs::ARCH, ISAInfo->toString());
85349cc55cSDimitry Andric }
86*0fca6ea1SDimitry Andric
87*0fca6ea1SDimitry Andric if (RiscvAbiAttr && STI.hasFeature(RISCV::FeatureStdExtA)) {
88*0fca6ea1SDimitry Andric unsigned AtomicABITag = static_cast<unsigned>(
89*0fca6ea1SDimitry Andric STI.hasFeature(RISCV::FeatureNoTrailingSeqCstFence)
90*0fca6ea1SDimitry Andric ? RISCVAttrs::RISCVAtomicAbiTag::A6C
91*0fca6ea1SDimitry Andric : RISCVAttrs::RISCVAtomicAbiTag::A6S);
92*0fca6ea1SDimitry Andric emitAttribute(RISCVAttrs::ATOMIC_ABI, AtomicABITag);
93*0fca6ea1SDimitry Andric }
945ffd83dbSDimitry Andric }
955ffd83dbSDimitry Andric
960b57cec5SDimitry Andric // This part is for ascii assembly output
RISCVTargetAsmStreamer(MCStreamer & S,formatted_raw_ostream & OS)970b57cec5SDimitry Andric RISCVTargetAsmStreamer::RISCVTargetAsmStreamer(MCStreamer &S,
980b57cec5SDimitry Andric formatted_raw_ostream &OS)
990b57cec5SDimitry Andric : RISCVTargetStreamer(S), OS(OS) {}
1000b57cec5SDimitry Andric
emitDirectiveOptionPush()1010b57cec5SDimitry Andric void RISCVTargetAsmStreamer::emitDirectiveOptionPush() {
1020b57cec5SDimitry Andric OS << "\t.option\tpush\n";
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric
emitDirectiveOptionPop()1050b57cec5SDimitry Andric void RISCVTargetAsmStreamer::emitDirectiveOptionPop() {
1060b57cec5SDimitry Andric OS << "\t.option\tpop\n";
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric
emitDirectiveOptionPIC()1095ffd83dbSDimitry Andric void RISCVTargetAsmStreamer::emitDirectiveOptionPIC() {
1105ffd83dbSDimitry Andric OS << "\t.option\tpic\n";
1115ffd83dbSDimitry Andric }
1125ffd83dbSDimitry Andric
emitDirectiveOptionNoPIC()1135ffd83dbSDimitry Andric void RISCVTargetAsmStreamer::emitDirectiveOptionNoPIC() {
1145ffd83dbSDimitry Andric OS << "\t.option\tnopic\n";
1155ffd83dbSDimitry Andric }
1165ffd83dbSDimitry Andric
emitDirectiveOptionRVC()1170b57cec5SDimitry Andric void RISCVTargetAsmStreamer::emitDirectiveOptionRVC() {
1180b57cec5SDimitry Andric OS << "\t.option\trvc\n";
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric
emitDirectiveOptionNoRVC()1210b57cec5SDimitry Andric void RISCVTargetAsmStreamer::emitDirectiveOptionNoRVC() {
1220b57cec5SDimitry Andric OS << "\t.option\tnorvc\n";
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric
emitDirectiveOptionRelax()1250b57cec5SDimitry Andric void RISCVTargetAsmStreamer::emitDirectiveOptionRelax() {
1260b57cec5SDimitry Andric OS << "\t.option\trelax\n";
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric
emitDirectiveOptionNoRelax()1290b57cec5SDimitry Andric void RISCVTargetAsmStreamer::emitDirectiveOptionNoRelax() {
1300b57cec5SDimitry Andric OS << "\t.option\tnorelax\n";
1310b57cec5SDimitry Andric }
1325ffd83dbSDimitry Andric
emitDirectiveOptionArch(ArrayRef<RISCVOptionArchArg> Args)13306c3fb27SDimitry Andric void RISCVTargetAsmStreamer::emitDirectiveOptionArch(
13406c3fb27SDimitry Andric ArrayRef<RISCVOptionArchArg> Args) {
13506c3fb27SDimitry Andric OS << "\t.option\tarch";
13606c3fb27SDimitry Andric for (const auto &Arg : Args) {
13706c3fb27SDimitry Andric OS << ", ";
13806c3fb27SDimitry Andric switch (Arg.Type) {
13906c3fb27SDimitry Andric case RISCVOptionArchArgType::Full:
14006c3fb27SDimitry Andric break;
14106c3fb27SDimitry Andric case RISCVOptionArchArgType::Plus:
14206c3fb27SDimitry Andric OS << "+";
14306c3fb27SDimitry Andric break;
14406c3fb27SDimitry Andric case RISCVOptionArchArgType::Minus:
14506c3fb27SDimitry Andric OS << "-";
14606c3fb27SDimitry Andric break;
14706c3fb27SDimitry Andric }
14806c3fb27SDimitry Andric OS << Arg.Value;
14906c3fb27SDimitry Andric }
15006c3fb27SDimitry Andric OS << "\n";
15106c3fb27SDimitry Andric }
15206c3fb27SDimitry Andric
emitDirectiveVariantCC(MCSymbol & Symbol)153bdd1243dSDimitry Andric void RISCVTargetAsmStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {
154bdd1243dSDimitry Andric OS << "\t.variant_cc\t" << Symbol.getName() << "\n";
155bdd1243dSDimitry Andric }
156bdd1243dSDimitry Andric
emitAttribute(unsigned Attribute,unsigned Value)1575ffd83dbSDimitry Andric void RISCVTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
1585ffd83dbSDimitry Andric OS << "\t.attribute\t" << Attribute << ", " << Twine(Value) << "\n";
1595ffd83dbSDimitry Andric }
1605ffd83dbSDimitry Andric
emitTextAttribute(unsigned Attribute,StringRef String)1615ffd83dbSDimitry Andric void RISCVTargetAsmStreamer::emitTextAttribute(unsigned Attribute,
1625ffd83dbSDimitry Andric StringRef String) {
1635ffd83dbSDimitry Andric OS << "\t.attribute\t" << Attribute << ", \"" << String << "\"\n";
1645ffd83dbSDimitry Andric }
1655ffd83dbSDimitry Andric
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)1665ffd83dbSDimitry Andric void RISCVTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute,
1675ffd83dbSDimitry Andric unsigned IntValue,
1685ffd83dbSDimitry Andric StringRef StringValue) {}
1695ffd83dbSDimitry Andric
finishAttributeSection()1705ffd83dbSDimitry Andric void RISCVTargetAsmStreamer::finishAttributeSection() {}
171