mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	This adds a safe interface to the machine independent InputArg struct for accessing the index of the original (IR-level) argument. When a non-native return type is lowered, we generate the hidden machine-level sret argument on-the-fly. Before this fix, we were representing this argument as OrigArgIndex == 0, which is an outright lie. In particular this crashed in the AArch64 backend where we actually try to access the type of the original argument. Now we use a sentinel value for machine arguments that have no original argument index. AArch64, ARM, Mips, and PPC now check for this case before accessing the original argument. Fixes <rdar://19792160> Null pointer assertion in AArch64TargetLowering git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229413 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			143 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===---- MipsCCState.cpp - CCState with Mips specific extensions ---------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "MipsCCState.h"
 | |
| #include "MipsSubtarget.h"
 | |
| #include "llvm/IR/Module.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| /// This function returns true if CallSym is a long double emulation routine.
 | |
| static bool isF128SoftLibCall(const char *CallSym) {
 | |
|   const char *const LibCalls[] = {
 | |
|       "__addtf3",      "__divtf3",     "__eqtf2",       "__extenddftf2",
 | |
|       "__extendsftf2", "__fixtfdi",    "__fixtfsi",     "__fixtfti",
 | |
|       "__fixunstfdi",  "__fixunstfsi", "__fixunstfti",  "__floatditf",
 | |
|       "__floatsitf",   "__floattitf",  "__floatunditf", "__floatunsitf",
 | |
|       "__floatuntitf", "__getf2",      "__gttf2",       "__letf2",
 | |
|       "__lttf2",       "__multf3",     "__netf2",       "__powitf2",
 | |
|       "__subtf3",      "__trunctfdf2", "__trunctfsf2",  "__unordtf2",
 | |
|       "ceill",         "copysignl",    "cosl",          "exp2l",
 | |
|       "expl",          "floorl",       "fmal",          "fmodl",
 | |
|       "log10l",        "log2l",        "logl",          "nearbyintl",
 | |
|       "powl",          "rintl",        "sinl",          "sqrtl",
 | |
|       "truncl"};
 | |
| 
 | |
|   const char *const *End = LibCalls + array_lengthof(LibCalls);
 | |
| 
 | |
|   // Check that LibCalls is sorted alphabetically.
 | |
|   MipsTargetLowering::LTStr Comp;
 | |
| 
 | |
| #ifndef NDEBUG
 | |
|   for (const char *const *I = LibCalls; I < End - 1; ++I)
 | |
|     assert(Comp(*I, *(I + 1)));
 | |
| #endif
 | |
| 
 | |
|   return std::binary_search(LibCalls, End, CallSym, Comp);
 | |
| }
 | |
| 
 | |
| /// This function returns true if Ty is fp128, {f128} or i128 which was
 | |
| /// originally a fp128.
 | |
| static bool originalTypeIsF128(const Type *Ty, const SDNode *CallNode) {
 | |
|   if (Ty->isFP128Ty())
 | |
|     return true;
 | |
| 
 | |
|   if (Ty->isStructTy() && Ty->getStructNumElements() == 1 &&
 | |
|       Ty->getStructElementType(0)->isFP128Ty())
 | |
|     return true;
 | |
| 
 | |
|   const ExternalSymbolSDNode *ES =
 | |
|       dyn_cast_or_null<const ExternalSymbolSDNode>(CallNode);
 | |
| 
 | |
|   // If the Ty is i128 and the function being called is a long double emulation
 | |
|   // routine, then the original type is f128.
 | |
|   return (ES && Ty->isIntegerTy(128) && isF128SoftLibCall(ES->getSymbol()));
 | |
| }
 | |
| 
 | |
| MipsCCState::SpecialCallingConvType
 | |
| MipsCCState::getSpecialCallingConvForCallee(const SDNode *Callee,
 | |
|                                             const MipsSubtarget &Subtarget) {
 | |
|   MipsCCState::SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv;
 | |
|   if (Subtarget.inMips16HardFloat()) {
 | |
|     if (const GlobalAddressSDNode *G =
 | |
|             dyn_cast<const GlobalAddressSDNode>(Callee)) {
 | |
|       llvm::StringRef Sym = G->getGlobal()->getName();
 | |
|       Function *F = G->getGlobal()->getParent()->getFunction(Sym);
 | |
|       if (F && F->hasFnAttribute("__Mips16RetHelper")) {
 | |
|         SpecialCallingConv = Mips16RetHelperConv;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return SpecialCallingConv;
 | |
| }
 | |
| 
 | |
| void MipsCCState::PreAnalyzeCallResultForF128(
 | |
|     const SmallVectorImpl<ISD::InputArg> &Ins,
 | |
|     const TargetLowering::CallLoweringInfo &CLI) {
 | |
|   for (unsigned i = 0; i < Ins.size(); ++i) {
 | |
|     OriginalArgWasF128.push_back(
 | |
|         originalTypeIsF128(CLI.RetTy, CLI.Callee.getNode()));
 | |
|     OriginalArgWasFloat.push_back(CLI.RetTy->isFloatingPointTy());
 | |
|   }
 | |
| }
 | |
| 
 | |
| /// Identify lowered values that originated from f128 arguments and record
 | |
| /// this for use by RetCC_MipsN.
 | |
| void MipsCCState::PreAnalyzeReturnForF128(
 | |
|     const SmallVectorImpl<ISD::OutputArg> &Outs) {
 | |
|   const MachineFunction &MF = getMachineFunction();
 | |
|   for (unsigned i = 0; i < Outs.size(); ++i) {
 | |
|     OriginalArgWasF128.push_back(
 | |
|         originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr));
 | |
|     OriginalArgWasFloat.push_back(
 | |
|         MF.getFunction()->getReturnType()->isFloatingPointTy());
 | |
|   }
 | |
| }
 | |
| 
 | |
| /// Identify lowered values that originated from f128 arguments and record
 | |
| /// this.
 | |
| void MipsCCState::PreAnalyzeCallOperands(
 | |
|     const SmallVectorImpl<ISD::OutputArg> &Outs,
 | |
|     std::vector<TargetLowering::ArgListEntry> &FuncArgs,
 | |
|     const SDNode *CallNode) {
 | |
|   for (unsigned i = 0; i < Outs.size(); ++i) {
 | |
|     OriginalArgWasF128.push_back(
 | |
|         originalTypeIsF128(FuncArgs[Outs[i].OrigArgIndex].Ty, CallNode));
 | |
|     OriginalArgWasFloat.push_back(
 | |
|         FuncArgs[Outs[i].OrigArgIndex].Ty->isFloatingPointTy());
 | |
|     CallOperandIsFixed.push_back(Outs[i].IsFixed);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /// Identify lowered values that originated from f128 arguments and record
 | |
| /// this.
 | |
| void MipsCCState::PreAnalyzeFormalArgumentsForF128(
 | |
|     const SmallVectorImpl<ISD::InputArg> &Ins) {
 | |
|   const MachineFunction &MF = getMachineFunction();
 | |
|   for (unsigned i = 0; i < Ins.size(); ++i) {
 | |
|     Function::const_arg_iterator FuncArg = MF.getFunction()->arg_begin();
 | |
| 
 | |
|     // SRet arguments cannot originate from f128 or {f128} returns so we just
 | |
|     // push false. We have to handle this specially since SRet arguments
 | |
|     // aren't mapped to an original argument.
 | |
|     if (Ins[i].Flags.isSRet()) {
 | |
|       OriginalArgWasF128.push_back(false);
 | |
|       OriginalArgWasFloat.push_back(false);
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     assert(Ins[i].getOrigArgIndex() < MF.getFunction()->arg_size());
 | |
|     std::advance(FuncArg, Ins[i].getOrigArgIndex());
 | |
| 
 | |
|     OriginalArgWasF128.push_back(
 | |
|         originalTypeIsF128(FuncArg->getType(), nullptr));
 | |
|     OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy());
 | |
|   }
 | |
| }
 |