brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · ebe996a Raw
174 lines · cpp
1//===- WebAssembly.cpp ----------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "ABIInfoImpl.h"10#include "TargetInfo.h"11 12using namespace clang;13using namespace clang::CodeGen;14 15//===----------------------------------------------------------------------===//16// WebAssembly ABI Implementation17//18// This is a very simple ABI that relies a lot on DefaultABIInfo.19//===----------------------------------------------------------------------===//20 21class WebAssemblyABIInfo final : public ABIInfo {22  DefaultABIInfo defaultInfo;23  WebAssemblyABIKind Kind;24 25public:26  explicit WebAssemblyABIInfo(CodeGen::CodeGenTypes &CGT,27                              WebAssemblyABIKind Kind)28      : ABIInfo(CGT), defaultInfo(CGT), Kind(Kind) {}29 30private:31  ABIArgInfo classifyReturnType(QualType RetTy) const;32  ABIArgInfo classifyArgumentType(QualType Ty) const;33 34  // DefaultABIInfo's classifyReturnType and classifyArgumentType are35  // non-virtual, but computeInfo and EmitVAArg are virtual, so we36  // overload them.37  void computeInfo(CGFunctionInfo &FI) const override {38    if (!getCXXABI().classifyReturnType(FI))39      FI.getReturnInfo() = classifyReturnType(FI.getReturnType());40    for (auto &Arg : FI.arguments())41      Arg.info = classifyArgumentType(Arg.type);42  }43 44  RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,45                   AggValueSlot Slot) const override;46};47 48class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo {49public:50  explicit WebAssemblyTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,51                                        WebAssemblyABIKind K)52      : TargetCodeGenInfo(std::make_unique<WebAssemblyABIInfo>(CGT, K)) {53    SwiftInfo =54        std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);55  }56 57  void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,58                           CodeGen::CodeGenModule &CGM) const override {59    TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);60    if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {61      if (const auto *Attr = FD->getAttr<WebAssemblyImportModuleAttr>()) {62        llvm::Function *Fn = cast<llvm::Function>(GV);63        llvm::AttrBuilder B(GV->getContext());64        B.addAttribute("wasm-import-module", Attr->getImportModule());65        Fn->addFnAttrs(B);66      }67      if (const auto *Attr = FD->getAttr<WebAssemblyImportNameAttr>()) {68        llvm::Function *Fn = cast<llvm::Function>(GV);69        llvm::AttrBuilder B(GV->getContext());70        B.addAttribute("wasm-import-name", Attr->getImportName());71        Fn->addFnAttrs(B);72      }73      if (const auto *Attr = FD->getAttr<WebAssemblyExportNameAttr>()) {74        llvm::Function *Fn = cast<llvm::Function>(GV);75        llvm::AttrBuilder B(GV->getContext());76        B.addAttribute("wasm-export-name", Attr->getExportName());77        Fn->addFnAttrs(B);78      }79    }80 81    if (auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {82      llvm::Function *Fn = cast<llvm::Function>(GV);83      if (!FD->doesThisDeclarationHaveABody() && !FD->hasPrototype())84        Fn->addFnAttr("no-prototype");85    }86  }87 88  /// Return the WebAssembly externref reference type.89  virtual llvm::Type *getWasmExternrefReferenceType() const override {90    return llvm::Type::getWasm_ExternrefTy(getABIInfo().getVMContext());91  }92  /// Return the WebAssembly funcref reference type.93  virtual llvm::Type *getWasmFuncrefReferenceType() const override {94    return llvm::Type::getWasm_FuncrefTy(getABIInfo().getVMContext());95  }96};97 98/// Classify argument of given type \p Ty.99ABIArgInfo WebAssemblyABIInfo::classifyArgumentType(QualType Ty) const {100  Ty = useFirstFieldIfTransparentUnion(Ty);101 102  if (isAggregateTypeForABI(Ty)) {103    // Records with non-trivial destructors/copy-constructors should not be104    // passed by value.105    if (auto RAA = getRecordArgABI(Ty, getCXXABI()))106      return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),107                                     RAA == CGCXXABI::RAA_DirectInMemory);108    // Ignore empty structs/unions.109    if (isEmptyRecord(getContext(), Ty, true))110      return ABIArgInfo::getIgnore();111    // Lower single-element structs to just pass a regular value. TODO: We112    // could do reasonable-size multiple-element structs too, using getExpand(),113    // though watch out for things like bitfields.114    if (const Type *SeltTy = isSingleElementStruct(Ty, getContext()))115      return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));116    // For the experimental multivalue ABI, fully expand all other aggregates117    if (Kind == WebAssemblyABIKind::ExperimentalMV) {118      const auto *RD = Ty->castAsRecordDecl();119      bool HasBitField = false;120      for (auto *Field : RD->fields()) {121        if (Field->isBitField()) {122          HasBitField = true;123          break;124        }125      }126      if (!HasBitField)127        return ABIArgInfo::getExpand();128    }129  }130 131  // Otherwise just do the default thing.132  return defaultInfo.classifyArgumentType(Ty);133}134 135ABIArgInfo WebAssemblyABIInfo::classifyReturnType(QualType RetTy) const {136  if (isAggregateTypeForABI(RetTy)) {137    // Records with non-trivial destructors/copy-constructors should not be138    // returned by value.139    if (!getRecordArgABI(RetTy, getCXXABI())) {140      // Ignore empty structs/unions.141      if (isEmptyRecord(getContext(), RetTy, true))142        return ABIArgInfo::getIgnore();143      // Lower single-element structs to just return a regular value. TODO: We144      // could do reasonable-size multiple-element structs too, using145      // ABIArgInfo::getDirect().146      if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext()))147        return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));148      // For the experimental multivalue ABI, return all other aggregates149      if (Kind == WebAssemblyABIKind::ExperimentalMV)150        return ABIArgInfo::getDirect();151    }152  }153 154  // Otherwise just do the default thing.155  return defaultInfo.classifyReturnType(RetTy);156}157 158RValue WebAssemblyABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,159                                     QualType Ty, AggValueSlot Slot) const {160  bool IsIndirect = isAggregateTypeForABI(Ty) &&161                    !isEmptyRecord(getContext(), Ty, true) &&162                    !isSingleElementStruct(Ty, getContext());163  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,164                          getContext().getTypeInfoInChars(Ty),165                          CharUnits::fromQuantity(4),166                          /*AllowHigherAlign=*/true, Slot);167}168 169std::unique_ptr<TargetCodeGenInfo>170CodeGen::createWebAssemblyTargetCodeGenInfo(CodeGenModule &CGM,171                                            WebAssemblyABIKind K) {172  return std::make_unique<WebAssemblyTargetCodeGenInfo>(CGM.getTypes(), K);173}174