Hi dsanders,
This patch adds support for the interrupt attribute for mips
http://reviews.llvm.org/D10802
Files:
include/clang/Basic/Attr.td
include/clang/Basic/AttrDocs.td
lib/CodeGen/TargetInfo.cpp
lib/Sema/SemaDeclAttr.cpp
test/CodeGen/mips-interrupt-attr.c
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -837,6 +837,22 @@
let Documentation = [Undocumented];
}
+def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips> {
+ // NOTE: if you add any additional spellings, ARMInterrupts's &
+ // MSP430Interrupt must match.
+ let Spellings = [GNU<"interrupt">];
+ let Args = [EnumArgument<"Interrupt", "InterruptType",
+ ["vector=sw0", "vector=sw1", "vector=hw0",
+ "vector=hw1", "vector=hw2", "vector=hw3",
+ "vector=hw4", "vector=hw5", "eic", ""],
+ ["sw0", "sw1", "hw0", "hw1", "hw2", "hw3",
+ "hw4", "hw5", "eic", "eic"]
+ >];
+ let ParseKind = "Interrupt";
+ let HasCustomParsing = 1;
+ let Documentation = [MipsInterruptDocs];
+}
+
def Mode : Attr {
let Spellings = [GCC<"mode">];
let Args = [IdentifierArgument<"Mode">];
Index: include/clang/Basic/AttrDocs.td
===================================================================
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -678,6 +678,32 @@
}];
}
+def MipsInterruptDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Clang supports the GNU style ``__attribute__((interrupt("LEVEL")))`` attribute on
+MIPS targets. This attribute may be attached ot a function definition and instructs
+the backend to generate appropriate function entry/exit code so that it can be used
+directly as an interrupt service routine.
+
+The parameter passed to the interrupt attribute is optional, but if
+provided it must be a string literal with one of the following values: "sw0",
+"sw1", "hw0", "hw1", "hw2", "hw3", "hw4", "hw5" or "eic".
+
+The semantics are as follows:
+
+- The prologue and epilogue are modified to save all non-kernel registers.
+
+- The FPU is disabled in the prologue as the floating pointer registers are not
+ spilled to the stack.
+
+- Function return is changed to an exception return instruction.
+
+- The parameter sets the interrupt mask for the function. If no parameter is specified
+ the interrupt mask defaults to "eic".
+ }];
+}
+
def DocCatAMDGPURegisterAttributes :
DocumentationCategory<"AMD GPU Register Attributes"> {
let Content = [{
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -5629,6 +5629,27 @@
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,
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -4186,12 +4186,46 @@
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;
+
+ MipsInterruptAttr::InterruptType Kind;
+ if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
+ << Attr.getName() << Str << ArgLoc;
+ return;
+ }
+
+ unsigned Index = Attr.getAttributeSpellingListIndex();
+ D->addAttr(::new (S.Context)
+ MipsInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
+}
+
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
+ else if (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::arm)
handleARMInterruptAttr(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);
}
static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D,
Index: test/CodeGen/mips-interrupt-attr.c
===================================================================
--- /dev/null
+++ test/CodeGen/mips-interrupt-attr.c
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -triple mipsel-unknown-linux -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK
+
+void __attribute__ ((interrupt("vector=sw0")))
+isr_sw0 (void)
+{
+ // CHECK: define void @isr_sw0() [[SW0:#[0-9]+]]
+}
+
+void __attribute__ ((interrupt("vector=sw1")))
+isr_sw1 (void)
+{
+ // CHECK: define void @isr_sw1() [[SW1:#[0-9]+]]
+}
+
+void __attribute__ ((interrupt("vector=hw0")))
+isr_hw0 (void)
+{
+ // CHECK: define void @isr_hw0() [[HW0:#[0-9]+]]
+}
+
+void __attribute__ ((interrupt("vector=hw1")))
+isr_hw1 (void)
+{
+ // CHECK: define void @isr_hw1() [[HW1:#[0-9]+]]
+}
+
+void __attribute__ ((interrupt("vector=hw2")))
+isr_hw2 (void)
+{
+ // CHECK: define void @isr_hw2() [[HW2:#[0-9]+]]
+}
+
+void __attribute__ ((interrupt("vector=hw3")))
+isr_hw3 (void)
+{
+ // CHECK: define void @isr_hw3() [[HW3:#[0-9]+]]
+}
+
+void __attribute__ ((interrupt("vector=hw4")))
+isr_hw4 (void)
+{
+ // CHECK: define void @isr_hw4() [[HW4:#[0-9]+]]
+}
+
+void __attribute__ ((interrupt("vector=hw5")))
+isr_hw5 (void)
+{
+ // CHECK: define void @isr_hw5() [[HW5:#[0-9]+]]
+}
+
+void __attribute__ ((interrupt))
+isr_eic (void)
+{
+ // CHECK: define void @isr_eic() [[EIC:#[0-9]+]]
+}
+// CHECK: attributes [[SW0]] = { {{.*}} "interrupt"="sw0" {{.*}} }
+// CHECK: attributes [[SW1]] = { {{.*}} "interrupt"="sw1" {{.*}} }
+// CHECK: attributes [[HW0]] = { {{.*}} "interrupt"="hw0" {{.*}} }
+// CHECK: attributes [[HW1]] = { {{.*}} "interrupt"="hw1" {{.*}} }
+// CHECK: attributes [[HW2]] = { {{.*}} "interrupt"="hw2" {{.*}} }
+// CHECK: attributes [[HW3]] = { {{.*}} "interrupt"="hw3" {{.*}} }
+// CHECK: attributes [[HW4]] = { {{.*}} "interrupt"="hw4" {{.*}} }
+// CHECK: attributes [[HW5]] = { {{.*}} "interrupt"="hw5" {{.*}} }
+// CHECK: attributes [[EIC]] = { {{.*}} "interrupt"="eic" {{.*}} }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits