Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/docs/LangRef.rst @@ -1058,6 +1058,11 @@ ``dereferenceable()``). This attribute may only be applied to pointer typed parameters. +``swiftself`` + This indicates that the parameter is the self/context parameter. This is not + a valid attribute for return values and can only be applied to one + parameter. + .. _gc: Garbage Collector Strategy Names Index: llvm/trunk/include/llvm-c/Core.h =================================================================== --- llvm/trunk/include/llvm-c/Core.h +++ llvm/trunk/include/llvm-c/Core.h @@ -94,6 +94,7 @@ LLVMJumpTableAttribute = 1ULL << 45, LLVMConvergentAttribute = 1ULL << 46, LLVMSafeStackAttribute = 1ULL << 47, + LLVMSwiftSelfAttribute = 1ULL << 48, */ } LLVMAttribute; Index: llvm/trunk/include/llvm/CodeGen/FastISel.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/FastISel.h +++ llvm/trunk/include/llvm/CodeGen/FastISel.h @@ -40,12 +40,14 @@ bool IsByVal : 1; bool IsInAlloca : 1; bool IsReturned : 1; + bool IsSwiftSelf : 1; uint16_t Alignment; ArgListEntry() : Val(nullptr), Ty(nullptr), IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false), - IsInAlloca(false), IsReturned(false), Alignment(0) {} + IsInAlloca(false), IsReturned(false), IsSwiftSelf(false), + Alignment(0) {} /// \brief Set CallLoweringInfo attribute flags based on a call instruction /// and called function attributes. Index: llvm/trunk/include/llvm/IR/Argument.h =================================================================== --- llvm/trunk/include/llvm/IR/Argument.h +++ llvm/trunk/include/llvm/IR/Argument.h @@ -73,6 +73,9 @@ /// containing function. bool hasByValAttr() const; + /// \brief Return true if this argument has the swiftself attribute. + bool hasSwiftSelfAttr() const; + /// \brief Return true if this argument has the byval attribute or inalloca /// attribute on it in its containing function. These attributes both /// represent arguments being passed by value. Index: llvm/trunk/include/llvm/IR/Attributes.td =================================================================== --- llvm/trunk/include/llvm/IR/Attributes.td +++ llvm/trunk/include/llvm/IR/Attributes.td @@ -154,6 +154,9 @@ /// MemorySanitizer is on. def SanitizeMemory : EnumAttr<"sanitize_memory">; +/// Argument is swift self/context. +def SwiftSelf : EnumAttr<"swiftself">; + /// Function must be in a unwind table. def UWTable : EnumAttr<"uwtable">; Index: llvm/trunk/include/llvm/Target/TargetCallingConv.h =================================================================== --- llvm/trunk/include/llvm/Target/TargetCallingConv.h +++ llvm/trunk/include/llvm/Target/TargetCallingConv.h @@ -48,6 +48,8 @@ static const uint64_t InAllocaOffs = 12; static const uint64_t SplitEnd = 1ULL<<13; ///< Last part of a split static const uint64_t SplitEndOffs = 13; + static const uint64_t SwiftSelf = 1ULL<<14; ///< Swift self parameter + static const uint64_t SwiftSelfOffs = 14; static const uint64_t OrigAlign = 0x1FULL<<27; static const uint64_t OrigAlignOffs = 27; static const uint64_t ByValSize = 0x3fffffffULL<<32; ///< Struct size @@ -82,6 +84,9 @@ bool isInAlloca() const { return Flags & InAlloca; } void setInAlloca() { Flags |= One << InAllocaOffs; } + bool isSwiftSelf() const { return Flags & SwiftSelf; } + void setSwiftSelf() { Flags |= One << SwiftSelfOffs; } + bool isNest() const { return Flags & Nest; } void setNest() { Flags |= One << NestOffs; } Index: llvm/trunk/include/llvm/Target/TargetCallingConv.td =================================================================== --- llvm/trunk/include/llvm/Target/TargetCallingConv.td +++ llvm/trunk/include/llvm/Target/TargetCallingConv.td @@ -42,6 +42,11 @@ class CCIfByVal : CCIf<"ArgFlags.isByVal()", A> { } +/// CCIfSwiftSelf - If the current argument has swiftself parameter attribute, +/// apply Action A. +class CCIfSwiftSelf : CCIf<"ArgFlags.isSwiftSelf()", A> { +} + /// CCIfConsecutiveRegs - If the current argument has InConsecutiveRegs /// parameter attribute, apply Action A. class CCIfConsecutiveRegs : CCIf<"ArgFlags.isInConsecutiveRegs()", A> { Index: llvm/trunk/include/llvm/Target/TargetLowering.h =================================================================== --- llvm/trunk/include/llvm/Target/TargetLowering.h +++ llvm/trunk/include/llvm/Target/TargetLowering.h @@ -2326,11 +2326,12 @@ bool isByVal : 1; bool isInAlloca : 1; bool isReturned : 1; + bool isSwiftSelf : 1; uint16_t Alignment; ArgListEntry() : isSExt(false), isZExt(false), isInReg(false), isSRet(false), isNest(false), isByVal(false), isInAlloca(false), - isReturned(false), Alignment(0) { } + isReturned(false), isSwiftSelf(false), Alignment(0) { } void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx); }; Index: llvm/trunk/lib/AsmParser/LLLexer.cpp =================================================================== --- llvm/trunk/lib/AsmParser/LLLexer.cpp +++ llvm/trunk/lib/AsmParser/LLLexer.cpp @@ -647,6 +647,7 @@ KEYWORD(sanitize_address); KEYWORD(sanitize_thread); KEYWORD(sanitize_memory); + KEYWORD(swiftself); KEYWORD(uwtable); KEYWORD(zeroext); Index: llvm/trunk/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.cpp +++ llvm/trunk/lib/AsmParser/LLParser.cpp @@ -1071,6 +1071,7 @@ case lltok::kw_nonnull: case lltok::kw_returned: case lltok::kw_sret: + case lltok::kw_swiftself: HaveError |= Error(Lex.getLoc(), "invalid use of parameter-only attribute on a function"); @@ -1344,6 +1345,7 @@ case lltok::kw_returned: B.addAttribute(Attribute::Returned); break; case lltok::kw_signext: B.addAttribute(Attribute::SExt); break; case lltok::kw_sret: B.addAttribute(Attribute::StructRet); break; + case lltok::kw_swiftself: B.addAttribute(Attribute::SwiftSelf); break; case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; case lltok::kw_alignstack: @@ -1431,6 +1433,7 @@ case lltok::kw_nocapture: case lltok::kw_returned: case lltok::kw_sret: + case lltok::kw_swiftself: HaveError |= Error(Lex.getLoc(), "invalid use of parameter-only attribute"); break; Index: llvm/trunk/lib/AsmParser/LLToken.h =================================================================== --- llvm/trunk/lib/AsmParser/LLToken.h +++ llvm/trunk/lib/AsmParser/LLToken.h @@ -151,6 +151,7 @@ kw_sret, kw_sanitize_thread, kw_sanitize_memory, + kw_swiftself, kw_uwtable, kw_zeroext, Index: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1325,6 +1325,8 @@ return Attribute::SanitizeThread; case bitc::ATTR_KIND_SANITIZE_MEMORY: return Attribute::SanitizeMemory; + case bitc::ATTR_KIND_SWIFT_SELF: + return Attribute::SwiftSelf; case bitc::ATTR_KIND_UW_TABLE: return Attribute::UWTable; case bitc::ATTR_KIND_Z_EXT: Index: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -259,6 +259,8 @@ return bitc::ATTR_KIND_SANITIZE_THREAD; case Attribute::SanitizeMemory: return bitc::ATTR_KIND_SANITIZE_MEMORY; + case Attribute::SwiftSelf: + return bitc::ATTR_KIND_SWIFT_SELF; case Attribute::UWTable: return bitc::ATTR_KIND_UW_TABLE; case Attribute::ZExt: Index: llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -89,6 +89,7 @@ IsByVal = CS->paramHasAttr(AttrIdx, Attribute::ByVal); IsInAlloca = CS->paramHasAttr(AttrIdx, Attribute::InAlloca); IsReturned = CS->paramHasAttr(AttrIdx, Attribute::Returned); + IsSwiftSelf = CS->paramHasAttr(AttrIdx, Attribute::SwiftSelf); Alignment = CS->getParamAlignment(AttrIdx); } @@ -957,6 +958,8 @@ Flags.setInReg(); if (Arg.IsSRet) Flags.setSRet(); + if (Arg.IsSwiftSelf) + Flags.setSwiftSelf(); if (Arg.IsByVal) Flags.setByVal(); if (Arg.IsInAlloca) { Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7281,6 +7281,7 @@ Entry.isNest = false; Entry.isByVal = false; Entry.isReturned = false; + Entry.isSwiftSelf = false; Entry.Alignment = Align; CLI.getArgs().insert(CLI.getArgs().begin(), Entry); CLI.RetTy = Type::getVoidTy(CLI.RetTy->getContext()); @@ -7338,6 +7339,8 @@ Flags.setInReg(); if (Args[i].isSRet) Flags.setSRet(); + if (Args[i].isSwiftSelf) + Flags.setSwiftSelf(); if (Args[i].isByVal) Flags.setByVal(); if (Args[i].isInAlloca) { @@ -7617,6 +7620,8 @@ Flags.setInReg(); if (F.getAttributes().hasAttribute(Idx, Attribute::StructRet)) Flags.setSRet(); + if (F.getAttributes().hasAttribute(Idx, Attribute::SwiftSelf)) + Flags.setSwiftSelf(); if (F.getAttributes().hasAttribute(Idx, Attribute::ByVal)) Flags.setByVal(); if (F.getAttributes().hasAttribute(Idx, Attribute::InAlloca)) { Index: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -77,6 +77,7 @@ isByVal = CS->paramHasAttr(AttrIdx, Attribute::ByVal); isInAlloca = CS->paramHasAttr(AttrIdx, Attribute::InAlloca); isReturned = CS->paramHasAttr(AttrIdx, Attribute::Returned); + isSwiftSelf = CS->paramHasAttr(AttrIdx, Attribute::SwiftSelf); Alignment = CS->getParamAlignment(AttrIdx); } Index: llvm/trunk/lib/IR/Attributes.cpp =================================================================== --- llvm/trunk/lib/IR/Attributes.cpp +++ llvm/trunk/lib/IR/Attributes.cpp @@ -195,6 +195,8 @@ return "byval"; if (hasAttribute(Attribute::Convergent)) return "convergent"; + if (hasAttribute(Attribute::SwiftSelf)) + return "swiftself"; if (hasAttribute(Attribute::InaccessibleMemOnly)) return "inaccessiblememonly"; if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly)) @@ -448,6 +450,7 @@ case Attribute::NoRecurse: return 1ULL << 48; case Attribute::InaccessibleMemOnly: return 1ULL << 49; case Attribute::InaccessibleMemOrArgMemOnly: return 1ULL << 50; + case Attribute::SwiftSelf: return 1ULL << 51; case Attribute::Dereferenceable: llvm_unreachable("dereferenceable attribute not supported in raw format"); break; Index: llvm/trunk/lib/IR/Function.cpp =================================================================== --- llvm/trunk/lib/IR/Function.cpp +++ llvm/trunk/lib/IR/Function.cpp @@ -92,6 +92,11 @@ return hasAttribute(Attribute::ByVal); } +bool Argument::hasSwiftSelfAttr() const { + return getParent()->getAttributes(). + hasAttribute(getArgNo()+1, Attribute::SwiftSelf); +} + /// \brief Return true if this argument has the inalloca attribute on it in /// its containing function. bool Argument::hasInAllocaAttr() const { Index: llvm/trunk/lib/IR/Verifier.cpp =================================================================== --- llvm/trunk/lib/IR/Verifier.cpp +++ llvm/trunk/lib/IR/Verifier.cpp @@ -1344,9 +1344,11 @@ !Attrs.hasAttribute(Idx, Attribute::StructRet) && !Attrs.hasAttribute(Idx, Attribute::NoCapture) && !Attrs.hasAttribute(Idx, Attribute::Returned) && - !Attrs.hasAttribute(Idx, Attribute::InAlloca), - "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', and " - "'returned' do not apply to return values!", + !Attrs.hasAttribute(Idx, Attribute::InAlloca) && + !Attrs.hasAttribute(Idx, Attribute::SwiftSelf), + "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', " + "'returned', and 'swiftself' do not apply to return " + "values!", V); // Check for mutually incompatible attributes. Only inreg is compatible with @@ -1423,6 +1425,7 @@ bool SawNest = false; bool SawReturned = false; bool SawSRet = false; + bool SawSwiftSelf = false; for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) { unsigned Idx = Attrs.getSlotIndex(i); @@ -1462,6 +1465,11 @@ SawSRet = true; } + if (Attrs.hasAttribute(Idx, Attribute::SwiftSelf)) { + Assert(!SawSwiftSelf, "Cannot have multiple 'swiftself' parameters!", V); + SawSwiftSelf = true; + } + if (Attrs.hasAttribute(Idx, Attribute::InAlloca)) { Assert(Idx == FT->getNumParams(), "inalloca isn't on the last parameter!", V); @@ -2554,7 +2562,7 @@ static AttrBuilder getParameterABIAttributes(int I, AttributeSet Attrs) { static const Attribute::AttrKind ABIAttrs[] = { Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca, - Attribute::InReg, Attribute::Returned}; + Attribute::InReg, Attribute::Returned, Attribute::SwiftSelf}; AttrBuilder Copy; for (auto AK : ABIAttrs) { if (Attrs.hasAttribute(I + 1, AK)) Index: llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td +++ llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td @@ -126,6 +126,9 @@ // slot is 64-bit. CCIfByVal>, + // A SwiftSelf is passed in X9. + CCIfSwiftSelf>>, + CCIfConsecutiveRegs>, // Handle i1, i8, i16, i32, i64, f32, f64 and v2f64 by passing in registers, Index: llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp @@ -2809,6 +2809,7 @@ if (F->getAttributes().hasAttribute(Idx, Attribute::ByVal) || F->getAttributes().hasAttribute(Idx, Attribute::InReg) || F->getAttributes().hasAttribute(Idx, Attribute::StructRet) || + F->getAttributes().hasAttribute(Idx, Attribute::SwiftSelf) || F->getAttributes().hasAttribute(Idx, Attribute::Nest)) return false; @@ -3060,7 +3061,8 @@ return false; for (auto Flag : CLI.OutFlags) - if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal()) + if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal() || + Flag.isSwiftSelf()) return false; // Set up the argument vectors. Index: llvm/trunk/lib/Target/ARM/ARMCallingConv.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMCallingConv.td +++ llvm/trunk/lib/Target/ARM/ARMCallingConv.td @@ -23,6 +23,9 @@ CCIfType<[i1, i8, i16], CCPromoteToType>, + // A SwiftSelf is passed in R9. + CCIfSwiftSelf>>, + // Handle all vector types as either f64 or v2f64. CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, @@ -151,6 +154,9 @@ CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + // A SwiftSelf is passed in R9. + CCIfSwiftSelf>>, + CCIfType<[f64, v2f64], CCCustom<"CC_ARM_AAPCS_Custom_f64">>, CCIfType<[f32], CCBitConvertToType>, CCDelegateTo @@ -179,6 +185,9 @@ CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + // A SwiftSelf is passed in R9. + CCIfSwiftSelf>>, + // HFAs are passed in a contiguous block of registers, or on the stack CCIfConsecutiveRegs>, Index: llvm/trunk/lib/Target/ARM/ARMFastISel.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMFastISel.cpp +++ llvm/trunk/lib/Target/ARM/ARMFastISel.cpp @@ -2345,6 +2345,7 @@ // FIXME: Only handle *easy* calls for now. if (CS.paramHasAttr(AttrInd, Attribute::InReg) || CS.paramHasAttr(AttrInd, Attribute::StructRet) || + CS.paramHasAttr(AttrInd, Attribute::SwiftSelf) || CS.paramHasAttr(AttrInd, Attribute::Nest) || CS.paramHasAttr(AttrInd, Attribute::ByVal)) return false; @@ -3019,6 +3020,7 @@ if (F->getAttributes().hasAttribute(Idx, Attribute::InReg) || F->getAttributes().hasAttribute(Idx, Attribute::StructRet) || + F->getAttributes().hasAttribute(Idx, Attribute::SwiftSelf) || F->getAttributes().hasAttribute(Idx, Attribute::ByVal)) return false; Index: llvm/trunk/lib/Target/X86/X86CallingConv.td =================================================================== --- llvm/trunk/lib/Target/X86/X86CallingConv.td +++ llvm/trunk/lib/Target/X86/X86CallingConv.td @@ -273,6 +273,9 @@ CCIfNest>>, CCIfNest>, + // A SwiftSelf is passed in R10. + CCIfSwiftSelf>>, + // The first 6 integer arguments are passed in integer registers. CCIfType<[i32], CCAssignToReg<[EDI, ESI, EDX, ECX, R8D, R9D]>>, CCIfType<[i64], CCAssignToReg<[RDI, RSI, RDX, RCX, R8 , R9 ]>>, Index: llvm/trunk/lib/Target/X86/X86FastISel.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86FastISel.cpp +++ llvm/trunk/lib/Target/X86/X86FastISel.cpp @@ -2744,6 +2744,7 @@ if (F->getAttributes().hasAttribute(Idx, Attribute::ByVal) || F->getAttributes().hasAttribute(Idx, Attribute::InReg) || F->getAttributes().hasAttribute(Idx, Attribute::StructRet) || + F->getAttributes().hasAttribute(Idx, Attribute::SwiftSelf) || F->getAttributes().hasAttribute(Idx, Attribute::Nest)) return false; Index: llvm/trunk/test/Bitcode/attributes.ll =================================================================== --- llvm/trunk/test/Bitcode/attributes.ll +++ llvm/trunk/test/Bitcode/attributes.ll @@ -287,6 +287,12 @@ ret void } +; CHECK: define void @f50(i8* swiftself) +define void @f50(i8* swiftself) +{ + ret void; +} + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { readnone } Index: llvm/trunk/test/CodeGen/AArch64/swiftself.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/swiftself.ll +++ llvm/trunk/test/CodeGen/AArch64/swiftself.ll @@ -0,0 +1,29 @@ +; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-apple-ios | FileCheck --check-prefix=CHECK-APPLE %s +; RUN: llc -O0 -verify-machineinstrs < %s -mtriple=aarch64-apple-ios | FileCheck --check-prefix=CHECK-O0 %s + +; Parameter with swiftself should be allocated to x9. +define void @check_swiftself(i32* swiftself %addr0) { +; CHECK-APPLE-LABEL: check_swiftself: +; CHECK-O0-LABEL: check_swiftself: + + %val0 = load volatile i32, i32* %addr0 +; CHECK-APPLE: ldr w{{.*}}, [x9] +; CHECK-O0: ldr w{{.*}}, [x9] + ret void +} + +@var8_3 = global i8 0 +declare void @take_swiftself(i8* swiftself %addr0) + +define void @simple_args() { +; CHECK-APPLE-LABEL: simple_args: +; CHECK-O0-LABEL: simple_args: + + call void @take_swiftself(i8* @var8_3) +; CHECK-APPLE: add x9, +; CHECK-APPLE: bl {{_?}}take_swiftself +; CHECK-O0: add x9, +; CHECK-O0: bl {{_?}}take_swiftself + + ret void +} Index: llvm/trunk/test/CodeGen/ARM/swiftself.ll =================================================================== --- llvm/trunk/test/CodeGen/ARM/swiftself.ll +++ llvm/trunk/test/CodeGen/ARM/swiftself.ll @@ -0,0 +1,32 @@ +; RUN: llc -verify-machineinstrs < %s -mtriple=armv7k-apple-ios8.0 -mcpu=cortex-a7 | FileCheck --check-prefix=CHECK-APPLE %s +; RUN: llc -O0 -verify-machineinstrs < %s -mtriple=armv7k-apple-ios8.0 -mcpu=cortex-a7 | FileCheck --check-prefix=CHECK-O0 %s + +; RUN: llc -verify-machineinstrs < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-APPLE %s +; RUN: llc -O0 -verify-machineinstrs < %s -mtriple=armv7-apple-ios | FileCheck --check-prefix=CHECK-O0 %s + +; Parameter with swiftself should be allocated to r9. +define void @check_swiftself(i32* swiftself %addr0) { +; CHECK-APPLE-LABEL: check_swiftself: +; CHECK-O0-LABEL: check_swiftself: + + %val0 = load volatile i32, i32* %addr0 +; CHECK-APPLE: ldr r{{.*}}, [r9] +; CHECK-O0: ldr r{{.*}}, [r9] + ret void +} + +@var8_3 = global i8 0 +declare void @take_swiftself(i8* swiftself %addr0) + +define void @simple_args() { +; CHECK-APPLE-LABEL: simple_args: +; CHECK-O0-LABEL: simple_args: + + call void @take_swiftself(i8* @var8_3) +; CHECK-APPLE: add r9, pc +; CHECK-APPLE: bl {{_?}}take_swiftself +; CHECK-O0: add r9, pc +; CHECK-O0: bl {{_?}}take_swiftself + + ret void +} Index: llvm/trunk/test/CodeGen/X86/swiftself.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/swiftself.ll +++ llvm/trunk/test/CodeGen/X86/swiftself.ll @@ -0,0 +1,41 @@ +; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-unknown-unknown | FileCheck %s +; RUN: llc -O0 -verify-machineinstrs < %s -mtriple=x86_64-unknown-unknown | FileCheck --check-prefix=CHECK-O0 %s +; RUN: llc -verify-machineinstrs < %s -march=x86 -mcpu=yonah -mtriple=i386-apple-darwin | FileCheck --check-prefix=CHECK-i386 %s +; RUN: llc -O0 -verify-machineinstrs < %s -march=x86 -mcpu=yonah -mtriple=i386-apple-darwin | FileCheck --check-prefix=CHECK-i386-O0 %s + +; Parameter with swiftself should be allocated to r10. +define void @check_swiftself(i32* swiftself %addr0) { +; CHECK-LABEL: check_swiftself: +; CHECK-O0-LABEL: check_swiftself: +; CHECK-i386-LABEL: check_swiftself: +; CHECK-i386-O0-LABEL: check_swiftself: + + %val0 = load volatile i32, i32* %addr0 +; CHECK: movl (%r10), +; CHECK-O0: movl (%r10), +; CHECK-i386: movl {{[0-9a-f]+}}(%esp) +; CHECK-i386-O0: movl {{[0-9a-f]+}}(%esp) + ret void +} + +@var8_3 = global i8 0 +declare void @take_swiftself(i8* swiftself %addr0) + +define void @simple_args() { +; CHECK-LABEL: simple_args: +; CHECK-O0-LABEL: simple_args: +; CHECK-i386-LABEL: simple_args: +; CHECK-i386-O0-LABEL: simple_args: + + call void @take_swiftself(i8* @var8_3) +; CHECK: movl {{.*}}, %r10d +; CHECK: callq {{_?}}take_swiftself +; CHECK-O0: movabsq {{.*}}, %r10 +; CHECK-O0: callq {{_?}}take_swiftself +; CHECK-i386: movl {{.*}}, (%esp) +; CHECK-i386: calll {{.*}}take_swiftself +; CHECK-i386-O0: movl {{.*}}, (%esp) +; CHECK-i386-O0: calll {{.*}}take_swiftself + + ret void +} Index: llvm/trunk/test/Verifier/swiftself.ll =================================================================== --- llvm/trunk/test/Verifier/swiftself.ll +++ llvm/trunk/test/Verifier/swiftself.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +declare void @a(i32* swiftself %a, i32* swiftself %b) +; CHECK: Cannot have multiple 'swiftself' parameters!