mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2026-01-31 01:35:20 +01:00
Summary: Swift ABI is based on basic C ABI described here https://github.com/WebAssembly/tool-conventions/blob/master/BasicCABI.md Swift Calling Convention on WebAssembly is a little deffer from swiftcc on another architectures. On non WebAssembly arch, swiftcc accepts extra parameters that are attributed with swifterror or swiftself by caller. Even if callee doesn't have these parameters, the invocation succeed ignoring extra parameters. But WebAssembly strictly checks that callee and caller signatures are same. https://github.com/WebAssembly/design/blob/master/Semantics.md#calls So at WebAssembly level, all swiftcc functions end up extra arguments and all function definitions and invocations explicitly have additional parameters to fill swifterror and swiftself. This patch support signature difference for swiftself and swifterror cc is swiftcc. e.g. ``` declare swiftcc void @foo(i32, i32) @data = global i8* bitcast (void (i32, i32)* @foo to i8*) define swiftcc void @bar() { %1 = load i8*, i8** @data %2 = bitcast i8* %1 to void (i32, i32, i32)* call swiftcc void %2(i32 1, i32 2, i32 swiftself 3) ret void } ``` For swiftcc, emit additional swiftself and swifterror parameters if there aren't while lowering. These additional parameters are added for both callee and caller. They are necessary to match callee and caller signature for direct and indirect function call. Differential Revision: https://reviews.llvm.org/D76049
116 lines
4.2 KiB
C++
116 lines
4.2 KiB
C++
//=- WebAssemblyMachineFunctionInfo.cpp - WebAssembly Machine Function Info -=//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// This file implements WebAssembly-specific per-machine-function
|
|
/// information.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "WebAssemblyMachineFunctionInfo.h"
|
|
#include "WebAssemblyISelLowering.h"
|
|
#include "WebAssemblySubtarget.h"
|
|
#include "llvm/CodeGen/Analysis.h"
|
|
using namespace llvm;
|
|
|
|
WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() = default; // anchor.
|
|
|
|
void WebAssemblyFunctionInfo::initWARegs() {
|
|
assert(WARegs.empty());
|
|
unsigned Reg = UnusedReg;
|
|
WARegs.resize(MF.getRegInfo().getNumVirtRegs(), Reg);
|
|
}
|
|
|
|
void llvm::computeLegalValueVTs(const Function &F, const TargetMachine &TM,
|
|
Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
|
|
const DataLayout &DL(F.getParent()->getDataLayout());
|
|
const WebAssemblyTargetLowering &TLI =
|
|
*TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering();
|
|
SmallVector<EVT, 4> VTs;
|
|
ComputeValueVTs(TLI, DL, Ty, VTs);
|
|
|
|
for (EVT VT : VTs) {
|
|
unsigned NumRegs = TLI.getNumRegisters(F.getContext(), VT);
|
|
MVT RegisterVT = TLI.getRegisterType(F.getContext(), VT);
|
|
for (unsigned I = 0; I != NumRegs; ++I)
|
|
ValueVTs.push_back(RegisterVT);
|
|
}
|
|
}
|
|
|
|
void llvm::computeSignatureVTs(const FunctionType *Ty,
|
|
const Function *TargetFunc,
|
|
const Function &ContextFunc,
|
|
const TargetMachine &TM,
|
|
SmallVectorImpl<MVT> &Params,
|
|
SmallVectorImpl<MVT> &Results) {
|
|
computeLegalValueVTs(ContextFunc, TM, Ty->getReturnType(), Results);
|
|
|
|
MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
|
|
if (Results.size() > 1 &&
|
|
!TM.getSubtarget<WebAssemblySubtarget>(ContextFunc).hasMultivalue()) {
|
|
// WebAssembly can't lower returns of multiple values without demoting to
|
|
// sret unless multivalue is enabled (see
|
|
// WebAssemblyTargetLowering::CanLowerReturn). So replace multiple return
|
|
// values with a poitner parameter.
|
|
Results.clear();
|
|
Params.push_back(PtrVT);
|
|
}
|
|
|
|
for (auto *Param : Ty->params())
|
|
computeLegalValueVTs(ContextFunc, TM, Param, Params);
|
|
if (Ty->isVarArg())
|
|
Params.push_back(PtrVT);
|
|
|
|
// For swiftcc, emit additional swiftself and swifterror parameters
|
|
// if there aren't. These additional parameters are also passed for caller.
|
|
// They are necessary to match callee and caller signature for indirect
|
|
// call.
|
|
|
|
if (TargetFunc && TargetFunc->getCallingConv() == CallingConv::Swift) {
|
|
MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
|
|
bool HasSwiftErrorArg = false;
|
|
bool HasSwiftSelfArg = false;
|
|
for (const auto &Arg : TargetFunc->args()) {
|
|
HasSwiftErrorArg |= Arg.hasAttribute(Attribute::SwiftError);
|
|
HasSwiftSelfArg |= Arg.hasAttribute(Attribute::SwiftSelf);
|
|
}
|
|
if (!HasSwiftErrorArg)
|
|
Params.push_back(PtrVT);
|
|
if (!HasSwiftSelfArg)
|
|
Params.push_back(PtrVT);
|
|
}
|
|
}
|
|
|
|
void llvm::valTypesFromMVTs(const ArrayRef<MVT> &In,
|
|
SmallVectorImpl<wasm::ValType> &Out) {
|
|
for (MVT Ty : In)
|
|
Out.push_back(WebAssembly::toValType(Ty));
|
|
}
|
|
|
|
std::unique_ptr<wasm::WasmSignature>
|
|
llvm::signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
|
|
const SmallVectorImpl<MVT> &Params) {
|
|
auto Sig = std::make_unique<wasm::WasmSignature>();
|
|
valTypesFromMVTs(Results, Sig->Returns);
|
|
valTypesFromMVTs(Params, Sig->Params);
|
|
return Sig;
|
|
}
|
|
|
|
yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
|
|
const llvm::WebAssemblyFunctionInfo &MFI)
|
|
: CFGStackified(MFI.isCFGStackified()) {}
|
|
|
|
void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
|
|
MappingTraits<WebAssemblyFunctionInfo>::mapping(YamlIO, *this);
|
|
}
|
|
|
|
void WebAssemblyFunctionInfo::initializeBaseYamlFields(
|
|
const yaml::WebAssemblyFunctionInfo &YamlMFI) {
|
|
CFGStackified = YamlMFI.CFGStackified;
|
|
}
|