Path: blob/main/contrib/llvm-project/llvm/lib/Target/Mips/MipsCCState.cpp
35269 views
//===---- MipsCCState.cpp - CCState with Mips specific extensions ---------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "MipsCCState.h"9#include "MipsSubtarget.h"10#include "llvm/IR/Module.h"1112using namespace llvm;1314bool MipsCCState::isF128SoftLibCall(const char *CallSym) {15const char *const LibCalls[] = {16"__addtf3", "__divtf3", "__eqtf2", "__extenddftf2",17"__extendsftf2", "__fixtfdi", "__fixtfsi", "__fixtfti",18"__fixunstfdi", "__fixunstfsi", "__fixunstfti", "__floatditf",19"__floatsitf", "__floattitf", "__floatunditf", "__floatunsitf",20"__floatuntitf", "__getf2", "__gttf2", "__letf2",21"__lttf2", "__multf3", "__netf2", "__powitf2",22"__subtf3", "__trunctfdf2", "__trunctfsf2", "__unordtf2",23"ceill", "copysignl", "cosl", "exp2l",24"expl", "floorl", "fmal", "fmaxl",25"fmodl", "log10l", "log2l", "logl",26"nearbyintl", "powl", "rintl", "roundl",27"sinl", "sqrtl", "truncl"};2829// Check that LibCalls is sorted alphabetically.30auto Comp = [](const char *S1, const char *S2) { return strcmp(S1, S2) < 0; };31assert(llvm::is_sorted(LibCalls, Comp));32return std::binary_search(std::begin(LibCalls), std::end(LibCalls), CallSym,33Comp);34}3536/// This function returns true if Ty is fp128, {f128} or i128 which was37/// originally a fp128.38bool MipsCCState::originalTypeIsF128(const Type *Ty, const char *Func) {39if (Ty->isFP128Ty())40return true;4142if (Ty->isStructTy() && Ty->getStructNumElements() == 1 &&43Ty->getStructElementType(0)->isFP128Ty())44return true;4546// If the Ty is i128 and the function being called is a long double emulation47// routine, then the original type is f128.48// FIXME: This is unsound because these functions could be indirectly called49return (Func && Ty->isIntegerTy(128) && isF128SoftLibCall(Func));50}5152/// Return true if the original type was vXfXX.53bool MipsCCState::originalEVTTypeIsVectorFloat(EVT Ty) {54if (Ty.isVector() && Ty.getVectorElementType().isFloatingPoint())55return true;5657return false;58}5960/// Return true if the original type was vXfXX / vXfXX.61bool MipsCCState::originalTypeIsVectorFloat(const Type *Ty) {62if (Ty->isVectorTy() && Ty->isFPOrFPVectorTy())63return true;6465return false;66}6768MipsCCState::SpecialCallingConvType69MipsCCState::getSpecialCallingConvForCallee(const SDNode *Callee,70const MipsSubtarget &Subtarget) {71MipsCCState::SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv;72if (Subtarget.inMips16HardFloat()) {73if (const GlobalAddressSDNode *G =74dyn_cast<const GlobalAddressSDNode>(Callee)) {75llvm::StringRef Sym = G->getGlobal()->getName();76Function *F = G->getGlobal()->getParent()->getFunction(Sym);77if (F && F->hasFnAttribute("__Mips16RetHelper")) {78SpecialCallingConv = Mips16RetHelperConv;79}80}81}82return SpecialCallingConv;83}8485void MipsCCState::PreAnalyzeCallResultForF128(86const SmallVectorImpl<ISD::InputArg> &Ins,87const Type *RetTy, const char *Call) {88for (unsigned i = 0; i < Ins.size(); ++i) {89OriginalArgWasF128.push_back(90originalTypeIsF128(RetTy, Call));91OriginalArgWasFloat.push_back(RetTy->isFloatingPointTy());92}93}9495/// Identify lowered values that originated from f128 or float arguments and96/// record this for use by RetCC_MipsN.97void MipsCCState::PreAnalyzeReturnForF128(98const SmallVectorImpl<ISD::OutputArg> &Outs) {99const MachineFunction &MF = getMachineFunction();100for (unsigned i = 0; i < Outs.size(); ++i) {101OriginalArgWasF128.push_back(102originalTypeIsF128(MF.getFunction().getReturnType(), nullptr));103OriginalArgWasFloat.push_back(104MF.getFunction().getReturnType()->isFloatingPointTy());105}106}107108/// Identify lower values that originated from vXfXX and record109/// this.110void MipsCCState::PreAnalyzeCallResultForVectorFloat(111const SmallVectorImpl<ISD::InputArg> &Ins, const Type *RetTy) {112for (unsigned i = 0; i < Ins.size(); ++i) {113OriginalRetWasFloatVector.push_back(originalTypeIsVectorFloat(RetTy));114}115}116117/// Identify lowered values that originated from vXfXX arguments and record118/// this.119void MipsCCState::PreAnalyzeReturnForVectorFloat(120const SmallVectorImpl<ISD::OutputArg> &Outs) {121for (unsigned i = 0; i < Outs.size(); ++i) {122ISD::OutputArg Out = Outs[i];123OriginalRetWasFloatVector.push_back(124originalEVTTypeIsVectorFloat(Out.ArgVT));125}126}127128void MipsCCState::PreAnalyzeReturnValue(EVT ArgVT) {129OriginalRetWasFloatVector.push_back(originalEVTTypeIsVectorFloat(ArgVT));130}131132void MipsCCState::PreAnalyzeCallOperand(const Type *ArgTy, bool IsFixed,133const char *Func) {134OriginalArgWasF128.push_back(originalTypeIsF128(ArgTy, Func));135OriginalArgWasFloat.push_back(ArgTy->isFloatingPointTy());136OriginalArgWasFloatVector.push_back(ArgTy->isVectorTy());137CallOperandIsFixed.push_back(IsFixed);138}139140/// Identify lowered values that originated from f128, float and sret to vXfXX141/// arguments and record this.142void MipsCCState::PreAnalyzeCallOperands(143const SmallVectorImpl<ISD::OutputArg> &Outs,144std::vector<TargetLowering::ArgListEntry> &FuncArgs,145const char *Func) {146for (unsigned i = 0; i < Outs.size(); ++i) {147TargetLowering::ArgListEntry FuncArg = FuncArgs[Outs[i].OrigArgIndex];148149OriginalArgWasF128.push_back(originalTypeIsF128(FuncArg.Ty, Func));150OriginalArgWasFloat.push_back(FuncArg.Ty->isFloatingPointTy());151OriginalArgWasFloatVector.push_back(FuncArg.Ty->isVectorTy());152CallOperandIsFixed.push_back(Outs[i].IsFixed);153}154}155156void MipsCCState::PreAnalyzeFormalArgument(const Type *ArgTy,157ISD::ArgFlagsTy Flags) {158// SRet arguments cannot originate from f128 or {f128} returns so we just159// push false. We have to handle this specially since SRet arguments160// aren't mapped to an original argument.161if (Flags.isSRet()) {162OriginalArgWasF128.push_back(false);163OriginalArgWasFloat.push_back(false);164OriginalArgWasFloatVector.push_back(false);165return;166}167168OriginalArgWasF128.push_back(originalTypeIsF128(ArgTy, nullptr));169OriginalArgWasFloat.push_back(ArgTy->isFloatingPointTy());170171// The MIPS vector ABI exhibits a corner case of sorts or quirk; if the172// first argument is actually an SRet pointer to a vector, then the next173// argument slot is $a2.174OriginalArgWasFloatVector.push_back(ArgTy->isVectorTy());175}176177/// Identify lowered values that originated from f128, float and vXfXX arguments178/// and record this.179void MipsCCState::PreAnalyzeFormalArgumentsForF128(180const SmallVectorImpl<ISD::InputArg> &Ins) {181const MachineFunction &MF = getMachineFunction();182for (unsigned i = 0; i < Ins.size(); ++i) {183Function::const_arg_iterator FuncArg = MF.getFunction().arg_begin();184185// SRet arguments cannot originate from f128 or {f128} returns so we just186// push false. We have to handle this specially since SRet arguments187// aren't mapped to an original argument.188if (Ins[i].Flags.isSRet()) {189OriginalArgWasF128.push_back(false);190OriginalArgWasFloat.push_back(false);191OriginalArgWasFloatVector.push_back(false);192continue;193}194195assert(Ins[i].getOrigArgIndex() < MF.getFunction().arg_size());196std::advance(FuncArg, Ins[i].getOrigArgIndex());197198OriginalArgWasF128.push_back(199originalTypeIsF128(FuncArg->getType(), nullptr));200OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy());201202// The MIPS vector ABI exhibits a corner case of sorts or quirk; if the203// first argument is actually an SRet pointer to a vector, then the next204// argument slot is $a2.205OriginalArgWasFloatVector.push_back(FuncArg->getType()->isVectorTy());206}207}208209210