diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 3777f956cf2..2dd66bac6ea 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -558,7 +558,8 @@ enum AttributeKindCodes { ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY = 50, ATTR_KIND_ALLOC_SIZE = 51, ATTR_KIND_WRITEONLY = 52, - ATTR_KIND_SPECULATABLE = 53 + ATTR_KIND_SPECULATABLE = 53, + ATTR_KIND_SWIFT_ISA = 54, }; enum ComdatSelectionKindCodes { diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index 497dca44547..183e4f22df7 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -69,6 +69,9 @@ class Argument final : public Value { /// Return true if this argument has the swiftself attribute. bool hasSwiftSelfAttr() const; + /// Return true if this argument has the swiftisa attribute. + bool hasSwiftIsaAttr() const; + /// Return true if this argument has the swifterror attribute. bool hasSwiftErrorAttr() const; diff --git a/include/llvm/IR/Attributes.td b/include/llvm/IR/Attributes.td index 616387816bf..7306f3ba102 100644 --- a/include/llvm/IR/Attributes.td +++ b/include/llvm/IR/Attributes.td @@ -167,6 +167,9 @@ def SwiftError : EnumAttr<"swifterror">; /// Argument is swift self/context. def SwiftSelf : EnumAttr<"swiftself">; +/// Argument is swift isa pointer. +def SwiftIsa : EnumAttr<"swiftisa">; + /// Function must be in a unwind table. def UWTable : EnumAttr<"uwtable">; diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h index 4f750b8a289..eb1c24ca7be 100644 --- a/include/llvm/Target/TargetCallingConv.h +++ b/include/llvm/Target/TargetCallingConv.h @@ -38,6 +38,7 @@ namespace ISD { unsigned IsSplitEnd : 1; ///< Last part of a split unsigned IsSwiftSelf : 1; ///< Swift self parameter unsigned IsSwiftError : 1; ///< Swift error parameter + unsigned IsSwiftIsa : 1; ///< Swift isa parameter unsigned IsHva : 1; ///< HVA field for unsigned IsHvaStart : 1; ///< HVA structure start unsigned IsSecArgPass : 1; ///< Second argument @@ -53,7 +54,7 @@ namespace ISD { ArgFlagsTy() : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0), IsSplitEnd(0), - IsSwiftSelf(0), IsSwiftError(0), IsHva(0), IsHvaStart(0), + IsSwiftSelf(0), IsSwiftError(0), IsSwiftIsa(0), IsHva(0), IsHvaStart(0), IsSecArgPass(0), ByValAlign(0), OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), IsCopyElisionCandidate(0), ByValSize(0) { @@ -84,6 +85,9 @@ namespace ISD { bool isSwiftError() const { return IsSwiftError; } void setSwiftError() { IsSwiftError = 1; } + bool isSwiftIsa() const { return IsSwiftIsa; } + void setSwiftIsa() { IsSwiftIsa = 1; } + bool isHva() const { return IsHva; } void setHva() { IsHva = 1; } diff --git a/include/llvm/Target/TargetCallingConv.td b/include/llvm/Target/TargetCallingConv.td index 3d8639dfe1d..c8750b40225 100644 --- a/include/llvm/Target/TargetCallingConv.td +++ b/include/llvm/Target/TargetCallingConv.td @@ -47,6 +47,11 @@ class CCIfByVal : CCIf<"ArgFlags.isByVal()", A> { class CCIfSwiftSelf : CCIf<"ArgFlags.isSwiftSelf()", A> { } +/// CCIfSwiftIsa - If the current argument has swiftisa parameter attribute, +/// apply Action A. +class CCIfSwiftIsa : CCIf<"ArgFlags.isSwiftIsa()", A> { +} + /// CCIfSwiftError - If the current argument has swifterror parameter attribute, /// apply Action A. class CCIfSwiftError : CCIf<"ArgFlags.isSwiftError()", A> { diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 23711d636c9..3c1b5dcca33 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -186,12 +186,13 @@ class TargetLoweringBase { bool IsReturned : 1; bool IsSwiftSelf : 1; bool IsSwiftError : 1; + bool IsSwiftIsa : 1; uint16_t Alignment = 0; ArgListEntry() : IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false), IsInAlloca(false), IsReturned(false), - IsSwiftSelf(false), IsSwiftError(false) {} + IsSwiftSelf(false), IsSwiftError(false), IsSwiftIsa(false) {} void setAttributes(ImmutableCallSite *CS, unsigned ArgIdx); }; diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 90e0d6a216e..85682aa388e 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -660,6 +660,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(sanitize_memory); KEYWORD(swifterror); KEYWORD(swiftself); + KEYWORD(swiftisa); KEYWORD(uwtable); KEYWORD(writeonly); KEYWORD(zeroext); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index aee2a9ae993..e5607e24ae1 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -1152,6 +1152,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, case lltok::kw_sret: case lltok::kw_swifterror: case lltok::kw_swiftself: + case lltok::kw_swiftisa: HaveError |= Error(Lex.getLoc(), "invalid use of parameter-only attribute on a function"); @@ -1425,6 +1426,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { case lltok::kw_sret: B.addAttribute(Attribute::StructRet); break; case lltok::kw_swifterror: B.addAttribute(Attribute::SwiftError); break; case lltok::kw_swiftself: B.addAttribute(Attribute::SwiftSelf); break; + case lltok::kw_swiftisa: B.addAttribute(Attribute::SwiftIsa); break; case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break; case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; @@ -1515,6 +1517,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { case lltok::kw_sret: case lltok::kw_swifterror: case lltok::kw_swiftself: + case lltok::kw_swiftisa: HaveError |= Error(Lex.getLoc(), "invalid use of parameter-only attribute"); break; diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 0f3707ba0d1..294a5324f60 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -209,6 +209,7 @@ enum Kind { kw_sanitize_memory, kw_swifterror, kw_swiftself, + kw_swiftisa, kw_uwtable, kw_writeonly, kw_zeroext, diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 2b4970a80cd..d90c43ae56c 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1128,6 +1128,7 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) { case Attribute::SwiftError: return 1ULL << 52; case Attribute::WriteOnly: return 1ULL << 53; case Attribute::Speculatable: return 1ULL << 54; + case Attribute::SwiftIsa: return 1ULL << 55; case Attribute::Dereferenceable: llvm_unreachable("dereferenceable attribute not supported in raw format"); break; @@ -1348,6 +1349,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::SwiftError; case bitc::ATTR_KIND_SWIFT_SELF: return Attribute::SwiftSelf; + case bitc::ATTR_KIND_SWIFT_ISA: + return Attribute::SwiftIsa; case bitc::ATTR_KIND_UW_TABLE: return Attribute::UWTable; case bitc::ATTR_KIND_WRITEONLY: diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index dcffde1742c..2cb73864315 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -607,6 +607,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_SWIFT_ERROR; case Attribute::SwiftSelf: return bitc::ATTR_KIND_SWIFT_SELF; + case Attribute::SwiftIsa: + return bitc::ATTR_KIND_SWIFT_ISA; case Attribute::UWTable: return bitc::ATTR_KIND_UW_TABLE; case Attribute::WriteOnly: diff --git a/lib/CodeGen/GlobalISel/CallLowering.cpp b/lib/CodeGen/GlobalISel/CallLowering.cpp index be0c5c2bb70..f8106e52de4 100644 --- a/lib/CodeGen/GlobalISel/CallLowering.cpp +++ b/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -72,6 +72,8 @@ void CallLowering::setArgFlags(CallLowering::ArgInfo &Arg, unsigned OpIdx, Arg.Flags.setSwiftSelf(); if (Attrs.hasAttribute(OpIdx, Attribute::SwiftError)) Arg.Flags.setSwiftError(); + if (Attrs.hasAttribute(OpIdx, Attribute::SwiftIsa)) + Arg.Flags.setSwiftIsa(); if (Attrs.hasAttribute(OpIdx, Attribute::ByVal)) Arg.Flags.setByVal(); if (Attrs.hasAttribute(OpIdx, Attribute::InAlloca)) diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 959735d66c4..f1299b0bd81 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -992,6 +992,8 @@ bool FastISel::lowerCallTo(CallLoweringInfo &CLI) { Flags.setSwiftSelf(); if (Arg.IsSwiftError) Flags.setSwiftError(); + if (Arg.IsSwiftIsa) + Flags.setSwiftIsa(); if (Arg.IsByVal) Flags.setByVal(); if (Arg.IsInAlloca) { diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index b912eb3e2d3..be72728d776 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -8021,6 +8021,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const { Entry.IsReturned = false; Entry.IsSwiftSelf = false; Entry.IsSwiftError = false; + Entry.IsSwiftIsa = false; Entry.Alignment = Align; CLI.getArgs().insert(CLI.getArgs().begin(), Entry); CLI.RetTy = Type::getVoidTy(CLI.RetTy->getContext()); @@ -8113,6 +8114,8 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const { Flags.setSwiftSelf(); if (Args[i].IsSwiftError) Flags.setSwiftError(); + if (Args[i].IsSwiftIsa) + Flags.setSwiftIsa(); if (Args[i].IsByVal) Flags.setByVal(); if (Args[i].IsInAlloca) { @@ -8595,6 +8598,8 @@ void SelectionDAGISel::LowerArguments(const Function &F) { Flags.setSwiftSelf(); if (Arg.hasAttribute(Attribute::SwiftError)) Flags.setSwiftError(); + if (Arg.hasAttribute(Attribute::SwiftIsa)) + Flags.setSwiftIsa(); if (Arg.hasAttribute(Attribute::ByVal)) Flags.setByVal(); if (Arg.hasAttribute(Attribute::InAlloca)) { diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 8652df7bbd7..3d9d63b8040 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -110,6 +110,7 @@ void TargetLoweringBase::ArgListEntry::setAttributes(ImmutableCallSite *CS, IsReturned = CS->paramHasAttr(ArgIdx, Attribute::Returned); IsSwiftSelf = CS->paramHasAttr(ArgIdx, Attribute::SwiftSelf); IsSwiftError = CS->paramHasAttr(ArgIdx, Attribute::SwiftError); + IsSwiftIsa = CS->paramHasAttr(ArgIdx, Attribute::SwiftIsa); Alignment = CS->getParamAlignment(ArgIdx); } diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 8f2e641d64b..c8e2d6e8c2b 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -259,6 +259,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "swifterror"; if (hasAttribute(Attribute::SwiftSelf)) return "swiftself"; + if (hasAttribute(Attribute::SwiftIsa)) + return "swiftisa"; if (hasAttribute(Attribute::InaccessibleMemOnly)) return "inaccessiblememonly"; if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly)) diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 9c59fdd5f3a..a2169477d65 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -1529,6 +1529,7 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, bool SawReturned = false; bool SawSRet = false; bool SawSwiftSelf = false; + bool SawSwiftIsa = false; bool SawSwiftError = false; // Verify return value attributes. @@ -1540,10 +1541,11 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, !RetAttrs.hasAttribute(Attribute::Returned) && !RetAttrs.hasAttribute(Attribute::InAlloca) && !RetAttrs.hasAttribute(Attribute::SwiftSelf) && + !RetAttrs.hasAttribute(Attribute::SwiftIsa) && !RetAttrs.hasAttribute(Attribute::SwiftError)), "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', " - "'returned', 'swiftself', and 'swifterror' do not apply to return " - "values!", + "'returned', 'swiftself', 'swiftisa' and 'swifterror' do not " + "apply to return values!", V); Assert((!RetAttrs.hasAttribute(Attribute::ReadOnly) && !RetAttrs.hasAttribute(Attribute::WriteOnly) && @@ -1586,6 +1588,11 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, SawSwiftSelf = true; } + if (ArgAttrs.hasAttribute(Attribute::SwiftIsa)) { + Assert(!SawSwiftIsa, "Cannot have multiple 'swiftisa' parameters!", V); + SawSwiftIsa = true; + } + if (ArgAttrs.hasAttribute(Attribute::SwiftError)) { Assert(!SawSwiftError, "Cannot have multiple 'swifterror' parameters!", V); diff --git a/lib/Target/AArch64/AArch64CallingConvention.td b/lib/Target/AArch64/AArch64CallingConvention.td index 93a68449de8..169b0fae9f5 100644 --- a/lib/Target/AArch64/AArch64CallingConvention.td +++ b/lib/Target/AArch64/AArch64CallingConvention.td @@ -52,6 +52,9 @@ def CC_AArch64_AAPCS : CallingConv<[ // A SwiftError is passed in X21. CCIfSwiftError>>, + // A SwiftIsa is passed in X22. + CCIfSwiftIsa>>, + CCIfConsecutiveRegs>, // Handle i1, i8, i16, i32, i64, f32, f64 and v2f64 by passing in registers, diff --git a/lib/Target/AArch64/AArch64FastISel.cpp b/lib/Target/AArch64/AArch64FastISel.cpp index 97396057dce..b51a9159788 100644 --- a/lib/Target/AArch64/AArch64FastISel.cpp +++ b/lib/Target/AArch64/AArch64FastISel.cpp @@ -3177,7 +3177,7 @@ bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) { for (auto Flag : CLI.OutFlags) if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal() || - Flag.isSwiftSelf() || Flag.isSwiftError()) + Flag.isSwiftSelf() || Flag.isSwiftError() || Flag.isSwiftIsa()) return false; // Set up the argument vectors. diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp index 9d879886d39..23fe475f65e 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3333,7 +3333,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, if (VA.isRegLoc()) { if (realArgIdx == 0 && Flags.isReturned() && !Flags.isSwiftSelf() && - Outs[0].VT == MVT::i64) { + !Flags.isSwiftIsa() && Outs[0].VT == MVT::i64) { assert(VA.getLocVT() == MVT::i64 && "unexpected calling convention register assignment"); assert(!Ins.empty() && Ins[0].VT == MVT::i64 && diff --git a/lib/Target/ARM/ARMCallingConv.td b/lib/Target/ARM/ARMCallingConv.td index dcfd6518a84..b4d15b01c5e 100644 --- a/lib/Target/ARM/ARMCallingConv.td +++ b/lib/Target/ARM/ARMCallingConv.td @@ -23,6 +23,9 @@ def CC_ARM_APCS : CallingConv<[ CCIfType<[i1, i8, i16], CCPromoteToType>, + // Pass SwiftIsa in a callee saved register. + CCIfSwiftIsa>>, + // Pass SwiftSelf in a callee saved register. CCIfSwiftSelf>>, diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 27dda93387b..b7415e6b863 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -1875,7 +1875,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, } } else if (VA.isRegLoc()) { if (realArgIdx == 0 && Flags.isReturned() && !Flags.isSwiftSelf() && - Outs[0].VT == MVT::i32) { + !Flags.isSwiftIsa() && Outs[0].VT == MVT::i32) { assert(VA.getLocVT() == MVT::i32 && "unexpected calling convention register assignment"); assert(!Ins.empty() && Ins[0].VT == MVT::i32 && diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index 2e624871ea4..6c7ccccb6d8 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1130,7 +1130,8 @@ static bool canUseSiblingCall(const CCState &ArgCCInfo, unsigned Reg = VA.getLocReg(); if (Reg == SystemZ::R6H || Reg == SystemZ::R6L || Reg == SystemZ::R6D) return false; - if (Outs[I].Flags.isSwiftSelf() || Outs[I].Flags.isSwiftError()) + if (Outs[I].Flags.isSwiftSelf() || Outs[I].Flags.isSwiftError() || + Outs[I].Flags.isSwiftIsa()) return false; } return true; diff --git a/lib/Target/X86/X86CallLowering.cpp b/lib/Target/X86/X86CallLowering.cpp index 9d1d24f3349..244c837e4b9 100644 --- a/lib/Target/X86/X86CallLowering.cpp +++ b/lib/Target/X86/X86CallLowering.cpp @@ -267,6 +267,7 @@ bool X86CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, Arg.hasAttribute(Attribute::StructRet) || Arg.hasAttribute(Attribute::SwiftSelf) || Arg.hasAttribute(Attribute::SwiftError) || + Arg.hasAttribute(Attribute::SwiftIsa) || Arg.hasAttribute(Attribute::Nest)) return false; diff --git a/lib/Target/X86/X86CallingConv.td b/lib/Target/X86/X86CallingConv.td index 2de9a5fbfe9..1743bc55c47 100644 --- a/lib/Target/X86/X86CallingConv.td +++ b/lib/Target/X86/X86CallingConv.td @@ -494,6 +494,9 @@ def CC_X86_64_C : CallingConv<[ CCIfNest>>, CCIfNest>, + // Pass SwiftIsa in a callee saved register. + CCIfSwiftIsa>>, + // Pass SwiftSelf in a callee saved register. CCIfSwiftSelf>>, diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 527e5d568ac..4e7b20b2ade 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -3051,6 +3051,7 @@ bool X86FastISel::fastLowerArguments() { Arg.hasAttribute(Attribute::StructRet) || Arg.hasAttribute(Attribute::SwiftSelf) || Arg.hasAttribute(Attribute::SwiftError) || + Arg.hasAttribute(Attribute::SwiftIsa) || Arg.hasAttribute(Attribute::Nest)) return false; diff --git a/test/Bitcode/attributes.ll b/test/Bitcode/attributes.ll index 18aa12c7af9..7342650c18d 100644 --- a/test/Bitcode/attributes.ll +++ b/test/Bitcode/attributes.ll @@ -305,6 +305,12 @@ define i32 @f52(i32, i8** swifterror) ret i32 0 } +; CHECK: define void @f52a(i8* swiftisa) +define void @f52a(i8* swiftisa) +{ + ret void; +} + %swift_error = type {i64, i8} declare float @foo(%swift_error** swifterror %error_ptr_ref) diff --git a/test/CodeGen/X86/swiftisa.ll b/test/CodeGen/X86/swiftisa.ll new file mode 100644 index 00000000000..cb8ae1e11e4 --- /dev/null +++ b/test/CodeGen/X86/swiftisa.ll @@ -0,0 +1,41 @@ +; RUN: llc -verify-machineinstrs -mtriple=x86_64-unknown-unknown -o - %s | FileCheck --check-prefix=CHECK --check-prefix=OPT %s +; RUN: llc -O0 -verify-machineinstrs -mtriple=x86_64-unknown-unknown -o - %s | FileCheck %s + +; Parameter with swiftisa should be allocated to r14. +; CHECK-LABEL: swiftisa_param: +; CHECK: movq %r14, %rax +define i8 *@swiftisa_param(i8* swiftisa %addr0) { + ret i8 *%addr0 +} + +; Check that r14 is used to pass a swiftisa argument. +; CHECK-LABEL: call_swiftisa: +; CHECK: movq %rdi, %r14 +; CHECK: callq {{_?}}swiftisa_param +define i8 *@call_swiftisa(i8* %arg) { + %res = call i8 *@swiftisa_param(i8* swiftisa %arg) + ret i8 *%res +} + +; r14 should be saved by the callee even if used for swiftisa +; CHECK-LABEL: swiftisa_clobber: +; CHECK: pushq %r14 +; ... +; CHECK: popq %r14 +define i8 *@swiftisa_clobber(i8* swiftisa %addr0) { + call void asm sideeffect "nop", "~{r14}"() + ret i8 *%addr0 +} + +; Demonstrate that we do not need any movs when calling multiple functions +; with swiftisa argument. +; CHECK-LABEL: swiftisa_passthrough: +; OPT-NOT: mov{{.*}}r14 +; OPT: callq {{_?}}swiftisa_param +; OPT-NOT: mov{{.*}}r14 +; OPT-NEXT: callq {{_?}}swiftisa_param +define void @swiftisa_passthrough(i8* swiftisa %addr0) { + call i8 *@swiftisa_param(i8* swiftisa %addr0) + call i8 *@swiftisa_param(i8* swiftisa %addr0) + ret void +} diff --git a/test/Verifier/swiftisa.ll b/test/Verifier/swiftisa.ll new file mode 100644 index 00000000000..4c5f8b1387c --- /dev/null +++ b/test/Verifier/swiftisa.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +declare void @a(i32* swiftisa %a, i32* swiftisa %b) +; CHECK: Cannot have multiple 'swiftisa' parameters!