mirror of https://github.com/microsoft/clang.git
[AVR] Add support for the 'interrupt' and 'naked' attributes
Summary: This teaches clang how to parse and lower the 'interrupt' and 'naked' attributes. This allows interrupt signal handlers to be written. Reviewers: aaron.ballman Subscribers: malcolm.parsons, cfe-commits Differential Revision: https://reviews.llvm.org/D28451 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@294402 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
52f027dd71
commit
8a58cc33d0
|
@ -258,6 +258,7 @@ class TargetArch<list<string> arches> {
|
|||
list<string> CXXABIs;
|
||||
}
|
||||
def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>;
|
||||
def TargetAVR : TargetArch<["avr"]>;
|
||||
def TargetMips : TargetArch<["mips", "mipsel"]>;
|
||||
def TargetMSP430 : TargetArch<["msp430"]>;
|
||||
def TargetX86 : TargetArch<["x86"]>;
|
||||
|
@ -480,6 +481,19 @@ def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
|
|||
let Documentation = [ARMInterruptDocs];
|
||||
}
|
||||
|
||||
def AVRInterrupt : InheritableAttr, TargetSpecificAttr<TargetAVR> {
|
||||
let Spellings = [GNU<"interrupt">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let ParseKind = "Interrupt";
|
||||
let Documentation = [AVRInterruptDocs];
|
||||
}
|
||||
|
||||
def AVRSignal : InheritableAttr, TargetSpecificAttr<TargetAVR> {
|
||||
let Spellings = [GNU<"signal">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let Documentation = [AVRSignalDocs];
|
||||
}
|
||||
|
||||
def AsmLabel : InheritableAttr {
|
||||
let Spellings = [Keyword<"asm">, Keyword<"__asm__">];
|
||||
let Args = [StringArgument<"Label">];
|
||||
|
|
|
@ -1182,6 +1182,33 @@ The semantics are as follows:
|
|||
}];
|
||||
}
|
||||
|
||||
def AVRInterruptDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Clang supports the GNU style ``__attribute__((interrupt))`` attribute on
|
||||
AVR targets. This attribute may be attached to 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.
|
||||
|
||||
On the AVR, the hardware globally disables interrupts when an interrupt is executed.
|
||||
The first instruction of an interrupt handler declared with this attribute is a SEI
|
||||
instruction to re-enable interrupts. See also the signal attribute that
|
||||
does not insert a SEI instruction.
|
||||
}];
|
||||
}
|
||||
|
||||
def AVRSignalDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Clang supports the GNU style ``__attribute__((signal))`` attribute on
|
||||
AVR targets. This attribute may be attached to 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.
|
||||
|
||||
Interrupt handler functions defined with the signal attribute do not re-enable interrupts.
|
||||
}];
|
||||
}
|
||||
|
||||
def TargetDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
|
|
|
@ -6899,6 +6899,31 @@ MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
|
|||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AVR ABI Implementation.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
class AVRTargetCodeGenInfo : public TargetCodeGenInfo {
|
||||
public:
|
||||
AVRTargetCodeGenInfo(CodeGenTypes &CGT)
|
||||
: TargetCodeGenInfo(new DefaultABIInfo(CGT)) { }
|
||||
|
||||
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
|
||||
CodeGen::CodeGenModule &CGM) const override {
|
||||
const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
|
||||
if (!FD) return;
|
||||
auto *Fn = cast<llvm::Function>(GV);
|
||||
|
||||
if (FD->getAttr<AVRInterruptAttr>())
|
||||
Fn->addFnAttr("interrupt");
|
||||
|
||||
if (FD->getAttr<AVRSignalAttr>())
|
||||
Fn->addFnAttr("signal");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TCE ABI Implementation (see http://tce.cs.tut.fi). Uses mostly the defaults.
|
||||
// Currently subclassed only to implement custom OpenCL C function attribute
|
||||
|
@ -8402,6 +8427,9 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
|
|||
case llvm::Triple::mips64el:
|
||||
return SetCGInfo(new MIPSTargetCodeGenInfo(Types, false));
|
||||
|
||||
case llvm::Triple::avr:
|
||||
return SetCGInfo(new AVRTargetCodeGenInfo(Types));
|
||||
|
||||
case llvm::Triple::aarch64:
|
||||
case llvm::Triple::aarch64_be: {
|
||||
AArch64ABIInfo::ABIKind Kind = AArch64ABIInfo::AAPCS;
|
||||
|
|
|
@ -5126,6 +5126,32 @@ static void handleAnyX86InterruptAttr(Sema &S, Decl *D,
|
|||
D->addAttr(UsedAttr::CreateImplicit(S.Context));
|
||||
}
|
||||
|
||||
static void handleAVRInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||
if (!isFunctionOrMethod(D)) {
|
||||
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
|
||||
<< "'interrupt'" << ExpectedFunction;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkAttributeNumArgs(S, Attr, 0))
|
||||
return;
|
||||
|
||||
handleSimpleAttribute<AVRInterruptAttr>(S, D, Attr);
|
||||
}
|
||||
|
||||
static void handleAVRSignalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||
if (!isFunctionOrMethod(D)) {
|
||||
S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
|
||||
<< "'signal'" << ExpectedFunction;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkAttributeNumArgs(S, Attr, 0))
|
||||
return;
|
||||
|
||||
handleSimpleAttribute<AVRSignalAttr>(S, D, Attr);
|
||||
}
|
||||
|
||||
static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||
// Dispatch the interrupt attribute based on the current target.
|
||||
switch (S.Context.getTargetInfo().getTriple().getArch()) {
|
||||
|
@ -5140,6 +5166,9 @@ static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|||
case llvm::Triple::x86_64:
|
||||
handleAnyX86InterruptAttr(S, D, Attr);
|
||||
break;
|
||||
case llvm::Triple::avr:
|
||||
handleAVRInterruptAttr(S, D, Attr);
|
||||
break;
|
||||
default:
|
||||
handleARMInterruptAttr(S, D, Attr);
|
||||
break;
|
||||
|
@ -5700,6 +5729,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
|||
case AttributeList::AT_AMDGPUNumVGPR:
|
||||
handleAMDGPUNumVGPRAttr(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_AVRSignal:
|
||||
handleAVRSignalAttr(S, D, Attr);
|
||||
break;
|
||||
case AttributeList::AT_IBAction:
|
||||
handleSimpleAttribute<IBActionAttr>(S, D, Attr);
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// RUN: %clang_cc1 -triple avr-unknown-unknown -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
// CHECK: define void @foo() #0
|
||||
__attribute__((interrupt)) void foo(void) { }
|
||||
|
||||
// CHECK: attributes #0 = {{{.*interrupt.*}}}
|
|
@ -0,0 +1,6 @@
|
|||
// RUN: %clang_cc1 -triple avr-unknown-unknown -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
// CHECK: define void @foo() #0
|
||||
__attribute__((signal)) void foo(void) { }
|
||||
|
||||
// CHECK: attributes #0 = {{{.*signal.*}}}
|
|
@ -0,0 +1,8 @@
|
|||
// RUN: %clang_cc1 %s -triple avr-unknown-unknown -verify -fsyntax-only
|
||||
struct a { int b; };
|
||||
|
||||
struct a test __attribute__((interrupt)); // expected-warning {{'interrupt' attribute only applies to functions}}
|
||||
|
||||
__attribute__((interrupt(12))) void foo(void) { } // expected-error {{'interrupt' attribute takes no arguments}}
|
||||
|
||||
__attribute__((interrupt)) void food() {}
|
|
@ -0,0 +1,8 @@
|
|||
// RUN: %clang_cc1 %s -triple avr-unknown-unknown -verify -fsyntax-only
|
||||
struct a { int b; };
|
||||
|
||||
struct a test __attribute__((signal)); // expected-warning {{'signal' attribute only applies to functions}}
|
||||
|
||||
__attribute__((signal(12))) void foo(void) { } // expected-error {{'signal' attribute takes no arguments}}
|
||||
|
||||
__attribute__((signal)) void food() {}
|
Loading…
Reference in New Issue