1 //= LoongArchBaseInfo.cpp - Top level definitions for LoongArch MC -*- C++ -*-//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements helper functions for the LoongArch target useful for the
10 // compiler back-end and the MC libraries.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "LoongArchBaseInfo.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/MC/MCSubtargetInfo.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/TargetParser/Triple.h"
19 
20 namespace llvm {
21 
22 namespace LoongArchABI {
23 
24 ABI computeTargetABI(const Triple &TT, StringRef ABIName) {
25   ABI ArgProvidedABI = getTargetABI(ABIName);
26   bool Is64Bit = TT.isArch64Bit();
27   ABI TripleABI;
28 
29   // Figure out the ABI explicitly requested via the triple's environment type.
30   switch (TT.getEnvironment()) {
31   case llvm::Triple::EnvironmentType::GNUSF:
32     TripleABI = Is64Bit ? LoongArchABI::ABI_LP64S : LoongArchABI::ABI_ILP32S;
33     break;
34   case llvm::Triple::EnvironmentType::GNUF32:
35     TripleABI = Is64Bit ? LoongArchABI::ABI_LP64F : LoongArchABI::ABI_ILP32F;
36     break;
37 
38   // Let the fallback case behave like {ILP32,LP64}D.
39   case llvm::Triple::EnvironmentType::GNUF64:
40   default:
41     TripleABI = Is64Bit ? LoongArchABI::ABI_LP64D : LoongArchABI::ABI_ILP32D;
42     break;
43   }
44 
45   switch (ArgProvidedABI) {
46   case LoongArchABI::ABI_Unknown:
47     // Fallback to the triple-implied ABI if ABI name is not specified or
48     // invalid.
49     if (!ABIName.empty())
50       errs() << "'" << ABIName
51              << "' is not a recognized ABI for this target, ignoring and using "
52                 "triple-implied ABI\n";
53     return TripleABI;
54 
55   case LoongArchABI::ABI_ILP32S:
56   case LoongArchABI::ABI_ILP32F:
57   case LoongArchABI::ABI_ILP32D:
58     if (Is64Bit) {
59       errs() << "32-bit ABIs are not supported for 64-bit targets, ignoring "
60                 "target-abi and using triple-implied ABI\n";
61       return TripleABI;
62     }
63     break;
64 
65   case LoongArchABI::ABI_LP64S:
66   case LoongArchABI::ABI_LP64F:
67   case LoongArchABI::ABI_LP64D:
68     if (!Is64Bit) {
69       errs() << "64-bit ABIs are not supported for 32-bit targets, ignoring "
70                 "target-abi and using triple-implied ABI\n";
71       return TripleABI;
72     }
73     break;
74   }
75 
76   if (!ABIName.empty() && TT.hasEnvironment() && ArgProvidedABI != TripleABI)
77     errs() << "warning: triple-implied ABI conflicts with provided target-abi '"
78            << ABIName << "', using target-abi\n";
79 
80   return ArgProvidedABI;
81 }
82 
83 ABI getTargetABI(StringRef ABIName) {
84   auto TargetABI = StringSwitch<ABI>(ABIName)
85                        .Case("ilp32s", ABI_ILP32S)
86                        .Case("ilp32f", ABI_ILP32F)
87                        .Case("ilp32d", ABI_ILP32D)
88                        .Case("lp64s", ABI_LP64S)
89                        .Case("lp64f", ABI_LP64F)
90                        .Case("lp64d", ABI_LP64D)
91                        .Default(ABI_Unknown);
92   return TargetABI;
93 }
94 
95 // To avoid the BP value clobbered by a function call, we need to choose a
96 // callee saved register to save the value. The `last` `S` register (s9) is
97 // used for FP. So we choose the previous (s8) as BP.
98 MCRegister getBPReg() { return LoongArch::R31; }
99 
100 } // end namespace LoongArchABI
101 
102 } // end namespace llvm
103