clang  19.0.0git
WebAssembly.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "ABIInfoImpl.h"
10 #include "TargetInfo.h"
11 
12 using namespace clang;
13 using namespace clang::CodeGen;
14 
15 //===----------------------------------------------------------------------===//
16 // WebAssembly ABI Implementation
17 //
18 // This is a very simple ABI that relies a lot on DefaultABIInfo.
19 //===----------------------------------------------------------------------===//
20 
21 class WebAssemblyABIInfo final : public ABIInfo {
22  DefaultABIInfo defaultInfo;
24 
25 public:
28  : ABIInfo(CGT), defaultInfo(CGT), Kind(Kind) {}
29 
30 private:
33 
34  // DefaultABIInfo's classifyReturnType and classifyArgumentType are
35  // non-virtual, but computeInfo and EmitVAArg are virtual, so we
36  // overload them.
37  void computeInfo(CGFunctionInfo &FI) const override {
38  if (!getCXXABI().classifyReturnType(FI))
40  for (auto &Arg : FI.arguments())
41  Arg.info = classifyArgumentType(Arg.type);
42  }
43 
44  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
45  QualType Ty) const override;
46 };
47 
49 public:
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 {
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.
99 ABIArgInfo WebAssemblyABIInfo::classifyArgumentType(QualType Ty) const {
101 
102  if (isAggregateTypeForABI(Ty)) {
103  // Records with non-trivial destructors/copy-constructors should not be
104  // passed by value.
105  if (auto RAA = getRecordArgABI(Ty, getCXXABI()))
106  return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
107  // Ignore empty structs/unions.
108  if (isEmptyRecord(getContext(), Ty, true))
109  return ABIArgInfo::getIgnore();
110  // Lower single-element structs to just pass a regular value. TODO: We
111  // could do reasonable-size multiple-element structs too, using getExpand(),
112  // though watch out for things like bitfields.
113  if (const Type *SeltTy = isSingleElementStruct(Ty, getContext()))
114  return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
115  // For the experimental multivalue ABI, fully expand all other aggregates
117  const RecordType *RT = Ty->getAs<RecordType>();
118  assert(RT);
119  bool HasBitField = false;
120  for (auto *Field : RT->getDecl()->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 
135 ABIArgInfo WebAssemblyABIInfo::classifyReturnType(QualType RetTy) const {
136  if (isAggregateTypeForABI(RetTy)) {
137  // Records with non-trivial destructors/copy-constructors should not be
138  // 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: We
144  // could do reasonable-size multiple-element structs too, using
145  // 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 aggregates
150  return ABIArgInfo::getDirect();
151  }
152  }
153 
154  // Otherwise just do the default thing.
155  return defaultInfo.classifyReturnType(RetTy);
156 }
157 
158 Address WebAssemblyABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
159  QualType Ty) 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),
166  /*AllowHigherAlign=*/true);
167 }
168 
169 std::unique_ptr<TargetCodeGenInfo>
171  WebAssemblyABIKind K) {
172  return std::make_unique<WebAssemblyTargetCodeGenInfo>(CGM.getTypes(), K);
173 }
WebAssemblyABIInfo(CodeGen::CodeGenTypes &CGT, WebAssemblyABIKind Kind)
Definition: WebAssembly.cpp:26
virtual llvm::Type * getWasmFuncrefReferenceType() const override
Return the WebAssembly funcref reference type.
Definition: WebAssembly.cpp:93
virtual llvm::Type * getWasmExternrefReferenceType() const override
Return the WebAssembly externref reference type.
Definition: WebAssembly.cpp:89
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const override
setTargetAttributes - Provides a convenient hook to handle extra target-specific attributes for the g...
Definition: WebAssembly.cpp:57
WebAssemblyTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, WebAssemblyABIKind K)
Definition: WebAssembly.cpp:50
Attr - This represents one attribute.
Definition: Attr.h:46
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition: CharUnits.h:63
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
static ABIArgInfo getIgnore()
static ABIArgInfo getExpand()
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
ABIInfo - Target specific hooks for defining how a type should be passed or returned from functions.
Definition: ABIInfo.h:45
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition: Address.h:111
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
Definition: CGCXXABI.h:158
CGFunctionInfo - Class to encapsulate the information about a function definition.
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
This class organizes the cross-function state that is used while generating LLVM code.
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
Definition: CodeGenTypes.h:54
DefaultABIInfo - The default implementation for ABI specific details.
Definition: ABIInfoImpl.h:21
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
Definition: TargetInfo.h:46
virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const
setTargetAttributes - Provides a convenient hook to handle extra target-specific attributes for the g...
Definition: TargetInfo.h:75
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
A (possibly-)qualified type.
Definition: Type.h:940
field_range fields() const
Definition: Decl.h:4377
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5561
RecordDecl * getDecl() const
Definition: Type.h:5571
The base class of the type hierarchy.
Definition: Type.h:1813
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8160
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
std::unique_ptr< TargetCodeGenInfo > createWebAssemblyTargetCodeGenInfo(CodeGenModule &CGM, WebAssemblyABIKind K)
Address emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType ValueTy, bool IsIndirect, TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign, bool AllowHigherAlign, bool ForceRightAdjust=false)
Emit va_arg for a platform using the common void* representation, where arguments are simply emitted ...
bool isAggregateTypeForABI(QualType T)
const Type * isSingleElementStruct(QualType T, ASTContext &Context)
isSingleElementStruct - Determine if a structure is a "single element struct", i.e.
QualType useFirstFieldIfTransparentUnion(QualType Ty)
Pass transparent unions as if they were the type of the first element.
bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool AsIfNoUniqueAddr=false)
isEmptyRecord - Return true iff a structure contains only empty fields.
The JSON file list parser is used to communicate input to InstallAPI.
Definition: Format.h:5433