1bdd1243dSDimitry Andric //===-- LoongArchELFStreamer.cpp - LoongArch ELF Target Streamer Methods --===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric //
9bdd1243dSDimitry Andric // This file provides LoongArch specific target streamer methods.
10bdd1243dSDimitry Andric //
11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
12bdd1243dSDimitry Andric 
13bdd1243dSDimitry Andric #include "LoongArchELFStreamer.h"
14bdd1243dSDimitry Andric #include "LoongArchAsmBackend.h"
15*06c3fb27SDimitry Andric #include "LoongArchBaseInfo.h"
16bdd1243dSDimitry Andric #include "llvm/BinaryFormat/ELF.h"
17bdd1243dSDimitry Andric #include "llvm/MC/MCAssembler.h"
18bdd1243dSDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
19bdd1243dSDimitry Andric #include "llvm/MC/MCObjectWriter.h"
20bdd1243dSDimitry Andric 
21bdd1243dSDimitry Andric using namespace llvm;
22bdd1243dSDimitry Andric 
23bdd1243dSDimitry Andric // This part is for ELF object output.
LoongArchTargetELFStreamer(MCStreamer & S,const MCSubtargetInfo & STI)24bdd1243dSDimitry Andric LoongArchTargetELFStreamer::LoongArchTargetELFStreamer(
25bdd1243dSDimitry Andric     MCStreamer &S, const MCSubtargetInfo &STI)
26bdd1243dSDimitry Andric     : LoongArchTargetStreamer(S) {
27*06c3fb27SDimitry Andric   auto &MAB = static_cast<LoongArchAsmBackend &>(
28*06c3fb27SDimitry Andric       getStreamer().getAssembler().getBackend());
29*06c3fb27SDimitry Andric   setTargetABI(LoongArchABI::computeTargetABI(
30*06c3fb27SDimitry Andric       STI.getTargetTriple(), MAB.getTargetOptions().getABIName()));
31bdd1243dSDimitry Andric }
32bdd1243dSDimitry Andric 
getStreamer()33bdd1243dSDimitry Andric MCELFStreamer &LoongArchTargetELFStreamer::getStreamer() {
34bdd1243dSDimitry Andric   return static_cast<MCELFStreamer &>(Streamer);
35bdd1243dSDimitry Andric }
36bdd1243dSDimitry Andric 
finish()37bdd1243dSDimitry Andric void LoongArchTargetELFStreamer::finish() {
38bdd1243dSDimitry Andric   LoongArchTargetStreamer::finish();
39bdd1243dSDimitry Andric   MCAssembler &MCA = getStreamer().getAssembler();
40bdd1243dSDimitry Andric   LoongArchABI::ABI ABI = getTargetABI();
41bdd1243dSDimitry Andric 
42bdd1243dSDimitry Andric   // Figure out the e_flags.
43bdd1243dSDimitry Andric   //
44bdd1243dSDimitry Andric   // Bitness is already represented with the EI_CLASS byte in the current spec,
45bdd1243dSDimitry Andric   // so here we only record the base ABI modifier. Also set the object file ABI
46bdd1243dSDimitry Andric   // version to v1, as upstream LLVM cannot handle the previous stack-machine-
47bdd1243dSDimitry Andric   // based relocs from day one.
48bdd1243dSDimitry Andric   //
49bdd1243dSDimitry Andric   // Refer to LoongArch ELF psABI v2.01 for details.
50bdd1243dSDimitry Andric   unsigned EFlags = MCA.getELFHeaderEFlags();
51bdd1243dSDimitry Andric   EFlags |= ELF::EF_LOONGARCH_OBJABI_V1;
52bdd1243dSDimitry Andric   switch (ABI) {
53bdd1243dSDimitry Andric   case LoongArchABI::ABI_ILP32S:
54bdd1243dSDimitry Andric   case LoongArchABI::ABI_LP64S:
55bdd1243dSDimitry Andric     EFlags |= ELF::EF_LOONGARCH_ABI_SOFT_FLOAT;
56bdd1243dSDimitry Andric     break;
57bdd1243dSDimitry Andric   case LoongArchABI::ABI_ILP32F:
58bdd1243dSDimitry Andric   case LoongArchABI::ABI_LP64F:
59bdd1243dSDimitry Andric     EFlags |= ELF::EF_LOONGARCH_ABI_SINGLE_FLOAT;
60bdd1243dSDimitry Andric     break;
61bdd1243dSDimitry Andric   case LoongArchABI::ABI_ILP32D:
62bdd1243dSDimitry Andric   case LoongArchABI::ABI_LP64D:
63bdd1243dSDimitry Andric     EFlags |= ELF::EF_LOONGARCH_ABI_DOUBLE_FLOAT;
64bdd1243dSDimitry Andric     break;
65bdd1243dSDimitry Andric   case LoongArchABI::ABI_Unknown:
66bdd1243dSDimitry Andric     llvm_unreachable("Improperly initialized target ABI");
67bdd1243dSDimitry Andric   }
68bdd1243dSDimitry Andric   MCA.setELFHeaderEFlags(EFlags);
69bdd1243dSDimitry Andric }
70bdd1243dSDimitry Andric 
71bdd1243dSDimitry Andric namespace {
72bdd1243dSDimitry Andric class LoongArchELFStreamer : public MCELFStreamer {
73bdd1243dSDimitry Andric public:
LoongArchELFStreamer(MCContext & C,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> MOW,std::unique_ptr<MCCodeEmitter> MCE)74bdd1243dSDimitry Andric   LoongArchELFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> MAB,
75bdd1243dSDimitry Andric                        std::unique_ptr<MCObjectWriter> MOW,
76bdd1243dSDimitry Andric                        std::unique_ptr<MCCodeEmitter> MCE)
77bdd1243dSDimitry Andric       : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {}
78bdd1243dSDimitry Andric };
79bdd1243dSDimitry Andric } // end namespace
80bdd1243dSDimitry Andric 
81bdd1243dSDimitry Andric namespace llvm {
createLoongArchELFStreamer(MCContext & C,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> MOW,std::unique_ptr<MCCodeEmitter> MCE,bool RelaxAll)82bdd1243dSDimitry Andric MCELFStreamer *createLoongArchELFStreamer(MCContext &C,
83bdd1243dSDimitry Andric                                           std::unique_ptr<MCAsmBackend> MAB,
84bdd1243dSDimitry Andric                                           std::unique_ptr<MCObjectWriter> MOW,
85bdd1243dSDimitry Andric                                           std::unique_ptr<MCCodeEmitter> MCE,
86bdd1243dSDimitry Andric                                           bool RelaxAll) {
87bdd1243dSDimitry Andric   LoongArchELFStreamer *S = new LoongArchELFStreamer(
88bdd1243dSDimitry Andric       C, std::move(MAB), std::move(MOW), std::move(MCE));
89bdd1243dSDimitry Andric   S->getAssembler().setRelaxAll(RelaxAll);
90bdd1243dSDimitry Andric   return S;
91bdd1243dSDimitry Andric }
92bdd1243dSDimitry Andric } // end namespace llvm
93