Home | History | Annotate | Line # | Download | only in WebAssembly
      1 // WebAssemblyMachineFunctionInfo.h-WebAssembly machine function info-*- 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 /// \file
     10 /// This file declares WebAssembly-specific per-machine-function
     11 /// information.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
     16 #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
     17 
     18 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
     19 #include "llvm/CodeGen/MIRYamlMapping.h"
     20 #include "llvm/CodeGen/MachineRegisterInfo.h"
     21 #include "llvm/MC/MCSymbolWasm.h"
     22 
     23 namespace llvm {
     24 
     25 struct WasmEHFuncInfo;
     26 
     27 namespace yaml {
     28 struct WebAssemblyFunctionInfo;
     29 }
     30 
     31 /// This class is derived from MachineFunctionInfo and contains private
     32 /// WebAssembly-specific information for each MachineFunction.
     33 class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
     34   const MachineFunction &MF;
     35 
     36   std::vector<MVT> Params;
     37   std::vector<MVT> Results;
     38   std::vector<MVT> Locals;
     39 
     40   /// A mapping from CodeGen vreg index to WebAssembly register number.
     41   std::vector<unsigned> WARegs;
     42 
     43   /// A mapping from CodeGen vreg index to a boolean value indicating whether
     44   /// the given register is considered to be "stackified", meaning it has been
     45   /// determined or made to meet the stack requirements:
     46   ///   - single use (per path)
     47   ///   - single def (per path)
     48   ///   - defined and used in LIFO order with other stack registers
     49   BitVector VRegStackified;
     50 
     51   // A virtual register holding the pointer to the vararg buffer for vararg
     52   // functions. It is created and set in TLI::LowerFormalArguments and read by
     53   // TLI::LowerVASTART
     54   unsigned VarargVreg = -1U;
     55 
     56   // A virtual register holding the base pointer for functions that have
     57   // overaligned values on the user stack.
     58   unsigned BasePtrVreg = -1U;
     59   // A virtual register holding the frame base. This is either FP or SP
     60   // after it has been replaced by a vreg
     61   unsigned FrameBaseVreg = -1U;
     62   // The local holding the frame base. This is either FP or SP
     63   // after WebAssemblyExplicitLocals
     64   unsigned FrameBaseLocal = -1U;
     65 
     66   // Function properties.
     67   bool CFGStackified = false;
     68 
     69   // Catchpad unwind destination info for wasm EH.
     70   WasmEHFuncInfo *WasmEHInfo = nullptr;
     71 
     72 public:
     73   explicit WebAssemblyFunctionInfo(MachineFunction &MF)
     74       : MF(MF), WasmEHInfo(MF.getWasmEHFuncInfo()) {}
     75   ~WebAssemblyFunctionInfo() override;
     76 
     77   const MachineFunction &getMachineFunction() const { return MF; }
     78 
     79   void initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo &YamlMFI);
     80 
     81   void addParam(MVT VT) { Params.push_back(VT); }
     82   const std::vector<MVT> &getParams() const { return Params; }
     83 
     84   void addResult(MVT VT) { Results.push_back(VT); }
     85   const std::vector<MVT> &getResults() const { return Results; }
     86 
     87   void clearParamsAndResults() {
     88     Params.clear();
     89     Results.clear();
     90   }
     91 
     92   void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); }
     93   void setLocal(size_t i, MVT VT) { Locals[i] = VT; }
     94   void addLocal(MVT VT) { Locals.push_back(VT); }
     95   const std::vector<MVT> &getLocals() const { return Locals; }
     96 
     97   unsigned getVarargBufferVreg() const {
     98     assert(VarargVreg != -1U && "Vararg vreg hasn't been set");
     99     return VarargVreg;
    100   }
    101   void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; }
    102 
    103   unsigned getBasePointerVreg() const {
    104     assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set");
    105     return BasePtrVreg;
    106   }
    107   void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; }
    108   unsigned getFrameBaseVreg() const {
    109     assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set");
    110     return FrameBaseVreg;
    111   }
    112   void clearFrameBaseVreg() { FrameBaseVreg = -1U; }
    113   // Return true if the frame base physreg has been replaced by a virtual reg.
    114   bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; }
    115   void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; }
    116   unsigned getFrameBaseLocal() const {
    117     assert(FrameBaseLocal != -1U && "Frame base local hasn't been set");
    118     return FrameBaseLocal;
    119   }
    120   void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; }
    121 
    122   static const unsigned UnusedReg = -1u;
    123 
    124   void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) {
    125     assert(MRI.getUniqueVRegDef(VReg));
    126     auto I = Register::virtReg2Index(VReg);
    127     if (I >= VRegStackified.size())
    128       VRegStackified.resize(I + 1);
    129     VRegStackified.set(I);
    130   }
    131   void unstackifyVReg(unsigned VReg) {
    132     auto I = Register::virtReg2Index(VReg);
    133     if (I < VRegStackified.size())
    134       VRegStackified.reset(I);
    135   }
    136   bool isVRegStackified(unsigned VReg) const {
    137     auto I = Register::virtReg2Index(VReg);
    138     if (I >= VRegStackified.size())
    139       return false;
    140     return VRegStackified.test(I);
    141   }
    142 
    143   void initWARegs(MachineRegisterInfo &MRI);
    144   void setWAReg(unsigned VReg, unsigned WAReg) {
    145     assert(WAReg != UnusedReg);
    146     auto I = Register::virtReg2Index(VReg);
    147     assert(I < WARegs.size());
    148     WARegs[I] = WAReg;
    149   }
    150   unsigned getWAReg(unsigned VReg) const {
    151     auto I = Register::virtReg2Index(VReg);
    152     assert(I < WARegs.size());
    153     return WARegs[I];
    154   }
    155 
    156   // For a given stackified WAReg, return the id number to print with push/pop.
    157   static unsigned getWARegStackId(unsigned Reg) {
    158     assert(Reg & INT32_MIN);
    159     return Reg & INT32_MAX;
    160   }
    161 
    162   bool isCFGStackified() const { return CFGStackified; }
    163   void setCFGStackified(bool Value = true) { CFGStackified = Value; }
    164 
    165   WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; }
    166   void setWasmEHFuncInfo(WasmEHFuncInfo *Info) { WasmEHInfo = Info; }
    167 };
    168 
    169 void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
    170                           SmallVectorImpl<MVT> &ValueVTs);
    171 
    172 // Compute the signature for a given FunctionType (Ty). Note that it's not the
    173 // signature for ContextFunc (ContextFunc is just used to get varous context)
    174 void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc,
    175                          const Function &ContextFunc, const TargetMachine &TM,
    176                          SmallVectorImpl<MVT> &Params,
    177                          SmallVectorImpl<MVT> &Results);
    178 
    179 void valTypesFromMVTs(const ArrayRef<MVT> &In,
    180                       SmallVectorImpl<wasm::ValType> &Out);
    181 
    182 std::unique_ptr<wasm::WasmSignature>
    183 signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
    184                   const SmallVectorImpl<MVT> &Params);
    185 
    186 namespace yaml {
    187 
    188 using BBNumberMap = DenseMap<int, int>;
    189 
    190 struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo {
    191   std::vector<FlowStringValue> Params;
    192   std::vector<FlowStringValue> Results;
    193   bool CFGStackified = false;
    194   // The same as WasmEHFuncInfo's SrcToUnwindDest, but stored in the mapping of
    195   // BB numbers
    196   BBNumberMap SrcToUnwindDest;
    197 
    198   WebAssemblyFunctionInfo() = default;
    199   WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo &MFI);
    200 
    201   void mappingImpl(yaml::IO &YamlIO) override;
    202   ~WebAssemblyFunctionInfo() = default;
    203 };
    204 
    205 template <> struct MappingTraits<WebAssemblyFunctionInfo> {
    206   static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) {
    207     YamlIO.mapOptional("params", MFI.Params, std::vector<FlowStringValue>());
    208     YamlIO.mapOptional("results", MFI.Results, std::vector<FlowStringValue>());
    209     YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false);
    210     YamlIO.mapOptional("wasmEHFuncInfo", MFI.SrcToUnwindDest);
    211   }
    212 };
    213 
    214 template <> struct CustomMappingTraits<BBNumberMap> {
    215   static void inputOne(IO &YamlIO, StringRef Key,
    216                        BBNumberMap &SrcToUnwindDest) {
    217     YamlIO.mapRequired(Key.str().c_str(),
    218                        SrcToUnwindDest[std::atoi(Key.str().c_str())]);
    219   }
    220 
    221   static void output(IO &YamlIO, BBNumberMap &SrcToUnwindDest) {
    222     for (auto KV : SrcToUnwindDest)
    223       YamlIO.mapRequired(std::to_string(KV.first).c_str(), KV.second);
    224   }
    225 };
    226 
    227 } // end namespace yaml
    228 
    229 } // end namespace llvm
    230 
    231 #endif
    232