diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 74 |
2 files changed, 94 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 06a2e71f5c0..df081b4fb9f 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -5893,6 +5893,27 @@ public: else if (FD->hasAttr<NoMips16Attr>()) { Fn->addFnAttr("nomips16"); } + + const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>(); + if (!Attr) + return; + + const char *Kind; + switch (Attr->getInterrupt()) { + default: llvm_unreachable("Unknown Mips interrupt attribute type!"); + case MipsInterruptAttr::eic: Kind = "eic"; break; + case MipsInterruptAttr::sw0: Kind = "sw0"; break; + case MipsInterruptAttr::sw1: Kind = "sw1"; break; + case MipsInterruptAttr::hw0: Kind = "hw0"; break; + case MipsInterruptAttr::hw1: Kind = "hw1"; break; + case MipsInterruptAttr::hw2: Kind = "hw2"; break; + case MipsInterruptAttr::hw3: Kind = "hw3"; break; + case MipsInterruptAttr::hw4: Kind = "hw4"; break; + case MipsInterruptAttr::hw5: Kind = "hw5"; break; + } + + Fn->addFnAttr("interrupt", Kind); + } bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 13a11bcac9e..df1641af5f4 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4450,14 +4450,86 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, D->addAttr(UsedAttr::CreateImplicit(S.Context)); } +static void handleMipsInterruptAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + // Only one optional argument permitted. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) + << Attr.getName() << 1; + return; + } + + StringRef Str; + SourceLocation ArgLoc; + + if (Attr.getNumArgs() == 0) + Str = ""; + else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc)) + return; + + // Semantic checks for a function with the 'interrupt' attribute for MIPS: + // a) Must be a function. + // b) Must have no parameters. + // c) Must have the 'void' return type. + // d) Cannot have the 'mips16' attribute, as that instruction set + // lacks the 'eret' instruction. + // e) The attribute itself must either have no argument or one of the + // valid interrupt types, see [MipsInterruptDocs]. + + if (!isFunctionOrMethod(D)) { + S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) + << "'interrupt'" << ExpectedFunctionOrMethod; + return; + } + + if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) { + S.Diag(D->getLocation(), diag::warn_mips_interrupt_attribute) + << 0; + return; + } + + if (!getFunctionOrMethodResultType(D)->isVoidType()) { + S.Diag(D->getLocation(), diag::warn_mips_interrupt_attribute) + << 1; + return; + } + + if (checkAttrMutualExclusion<Mips16Attr>(S, D, Attr.getRange(), + Attr.getName())) + return; + + MipsInterruptAttr::InterruptType Kind; + if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) + << Attr.getName() << "'" + std::string(Str) + "'"; + return; + } + + D->addAttr(::new (S.Context) MipsInterruptAttr( + Attr.getLoc(), S.Context, Kind, Attr.getAttributeSpellingListIndex())); +} + static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Dispatch the interrupt attribute based on the current target. if (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::msp430) handleMSP430InterruptAttr(S, D, Attr); + else if (S.Context.getTargetInfo().getTriple().getArch() == + llvm::Triple::mipsel || + S.Context.getTargetInfo().getTriple().getArch() == + llvm::Triple::mips) + handleMipsInterruptAttr(S, D, Attr); else handleARMInterruptAttr(S, D, Attr); } +static void handleMips16Attribute(Sema &S, Decl *D, const AttributeList &Attr) { + if (checkAttrMutualExclusion<MipsInterruptAttr>(S, D, Attr.getRange(), + Attr.getName())) + return; + + handleSimpleAttribute<Mips16Attr>(S, D, Attr); +} + static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const AttributeList &Attr) { uint32_t NumRegs; @@ -4847,7 +4919,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleDLLAttr(S, D, Attr); break; case AttributeList::AT_Mips16: - handleSimpleAttribute<Mips16Attr>(S, D, Attr); + handleMips16Attribute(S, D, Attr); break; case AttributeList::AT_NoMips16: handleSimpleAttribute<NoMips16Attr>(S, D, Attr); |