diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1460,6 +1460,12 @@ let Documentation = [Undocumented]; } +// For internal use by compiler-rt +def MSP430Builtin : DeclOrTypeAttr, TargetSpecificAttr { + let Spellings = [Clang<"msp430_builtin">]; + let Documentation = [Undocumented]; +} + def Mips16 : InheritableAttr, TargetSpecificAttr { let Spellings = [GCC<"mips16">]; let Subjects = SubjectList<[Function], ErrorDiag>; diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -286,6 +286,7 @@ CC_PreserveMost, // __attribute__((preserve_most)) CC_PreserveAll, // __attribute__((preserve_all)) CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs)) + CC_MSP430Builtin, // __attribute__((msp430_builtin)) }; /// Checks whether the given calling convention supports variadic diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2854,6 +2854,7 @@ case CC_OpenCLKernel: case CC_PreserveMost: case CC_PreserveAll: + case CC_MSP430Builtin: // FIXME: we should be mangling all of the above. return ""; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3115,6 +3115,7 @@ case CC_Swift: return "swiftcall"; case CC_PreserveMost: return "preserve_most"; case CC_PreserveAll: return "preserve_all"; + case CC_MSP430Builtin: return "msp430_builtin"; } llvm_unreachable("Invalid calling convention."); @@ -3529,6 +3530,7 @@ case attr::IntelOclBicc: case attr::PreserveMost: case attr::PreserveAll: + case attr::MSP430Builtin: return true; } llvm_unreachable("invalid attr kind"); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -940,6 +940,9 @@ case CC_PreserveAll: OS << " __attribute__((preserve_all))"; break; + case CC_MSP430Builtin: + OS << " __attribute__((msp430_builtin))"; + break; } } @@ -1635,6 +1638,9 @@ case attr::ArmSveVectorBits: OS << "arm_sve_vector_bits"; break; + case attr::MSP430Builtin: + OS << "msp430_builtin"; + break; } OS << "))"; } diff --git a/clang/lib/Basic/Targets/MSP430.h b/clang/lib/Basic/Targets/MSP430.h --- a/clang/lib/Basic/Targets/MSP430.h +++ b/clang/lib/Basic/Targets/MSP430.h @@ -96,6 +96,16 @@ // FIXME: implement return TargetInfo::CharPtrBuiltinVaList; } + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + switch (CC) { + default: + return CCCR_Warning; + case CC_C: + case CC_MSP430Builtin: + return CCCR_OK; + } + } }; } // namespace targets diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -65,6 +65,7 @@ case CC_PreserveMost: return llvm::CallingConv::PreserveMost; case CC_PreserveAll: return llvm::CallingConv::PreserveAll; case CC_Swift: return llvm::CallingConv::Swift; + case CC_MSP430Builtin: return llvm::CallingConv::MSP430_BUILTIN; } } @@ -239,6 +240,9 @@ if (D->hasAttr()) return CC_PreserveAll; + if (D->hasAttr()) + return CC_MSP430Builtin; + return CC_C; } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1230,6 +1230,7 @@ return llvm::dwarf::DW_CC_LLVM_PreserveAll; case CC_X86RegCall: return llvm::dwarf::DW_CC_LLVM_X86RegCall; + // TODO case CC_MSP430Builtin: } return 0; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4459,6 +4459,9 @@ case ParsedAttr::AT_PreserveAll: D->addAttr(::new (S.Context) PreserveAllAttr(S.Context, AL)); return; + case ParsedAttr::AT_MSP430Builtin: + D->addAttr(::new (S.Context) MSP430BuiltinAttr(S.Context, AL)); + return; default: llvm_unreachable("unexpected attribute kind"); } @@ -4624,6 +4627,9 @@ case ParsedAttr::AT_PreserveAll: CC = CC_PreserveAll; break; + case ParsedAttr::AT_MSP430Builtin: + CC = CC_MSP430Builtin; + break; default: llvm_unreachable("unexpected attribute kind"); } @@ -7252,6 +7258,7 @@ case ParsedAttr::AT_PreserveMost: case ParsedAttr::AT_PreserveAll: case ParsedAttr::AT_AArch64VectorPcs: + case ParsedAttr::AT_MSP430Builtin: handleCallConvAttr(S, D, AL); break; case ParsedAttr::AT_Suppress: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -124,7 +124,8 @@ case ParsedAttr::AT_Pcs: \ case ParsedAttr::AT_IntelOclBicc: \ case ParsedAttr::AT_PreserveMost: \ - case ParsedAttr::AT_PreserveAll + case ParsedAttr::AT_PreserveAll: \ + case ParsedAttr::AT_MSP430Builtin // Function type attributes. #define FUNCTION_TYPE_ATTRS_CASELIST \ @@ -7248,6 +7249,8 @@ return createSimpleAttr(Ctx, Attr); case ParsedAttr::AT_PreserveAll: return createSimpleAttr(Ctx, Attr); + case ParsedAttr::AT_MSP430Builtin: + return createSimpleAttr(Ctx, Attr); } llvm_unreachable("unexpected attribute kind!"); } diff --git a/clang/test/CodeGen/msp430-cc-builtin.c b/clang/test/CodeGen/msp430-cc-builtin.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/msp430-cc-builtin.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple msp430 -emit-llvm < %s | FileCheck %s + +__attribute__((msp430_builtin)) int f(long long x, long long y); + +__attribute__((msp430_builtin)) int g(long long x, long long y) { + return (int)42; +} +// CHECK: define cc94 {{(dso_local )?}}i16 @g(i64 %x, i64 %y) + +int caller() +{ + return f(0, 0); +// CHECK: call cc94 i16 @f +} + +// CHECK: declare cc94 {{(dso_local )?}}i16 @f(i64, i64) diff --git a/clang/test/Sema/attr-msp430.c b/clang/test/Sema/attr-msp430.c --- a/clang/test/Sema/attr-msp430.c +++ b/clang/test/Sema/attr-msp430.c @@ -11,3 +11,7 @@ __attribute__((interrupt(0))) void f6(void); __attribute__((interrupt(63))) void f7(void); + +__attribute__((msp430_builtin)) int t2; // expected-warning {{'msp430_builtin' only applies to function types; type here is 'int'}} +__attribute__((msp430_builtin(1))) void f8(long long a, long long b); // expected-error {{'msp430_builtin' attribute takes no arguments}} +__attribute__((msp430_builtin)) void f9(long long a, long long b); diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -666,6 +666,7 @@ TCALLINGCONV(Swift); TCALLINGCONV(PreserveMost); TCALLINGCONV(PreserveAll); + case CC_MSP430Builtin: return CXCallingConv_Unexposed; case CC_SpirFunction: return CXCallingConv_Unexposed; case CC_OpenCLKernel: return CXCallingConv_Unexposed; break; diff --git a/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp b/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp --- a/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -573,6 +573,7 @@ report_fatal_error("Unsupported calling convention"); case CallingConv::C: case CallingConv::Fast: + case CallingConv::MSP430_BUILTIN: return LowerCCCArguments(Chain, CallConv, isVarArg, Ins, dl, DAG, InVals); case CallingConv::MSP430_INTR: if (Ins.empty())