summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/TargetInfo.cpp
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2016-01-15 04:06:31 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2016-01-15 04:06:31 +0000
commitd51e9933b6aaa6d99efe871bf6a73c0484e317b9 (patch)
tree5ed18426dde4cd81281ed6ea4a00cc1942059cc6 /clang/lib/CodeGen/TargetInfo.cpp
parentbd3a772e9ff81e32c308d05670dc35438e5f93c4 (diff)
downloadbcm5719-llvm-d51e9933b6aaa6d99efe871bf6a73c0484e317b9.tar.gz
bcm5719-llvm-d51e9933b6aaa6d99efe871bf6a73c0484e317b9.zip
[X86] Support 'interrupt' attribute for x86
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 handler. The IRET instruction, instead of the RET instruction, is used to return from interrupt or exception handlers. All registers, except for the EFLAGS register which is restored by the IRET instruction, are preserved by the compiler. Any interruptible-without-stack-switch code must be compiled with -mno-red-zone since interrupt handlers can and will, because of the hardware design, touch the red zone. interrupt handler must be declared with a mandatory pointer argument: struct interrupt_frame; __attribute__ ((interrupt)) void f (struct interrupt_frame *frame) { ... } and user must properly define the structure the pointer pointing to. exception handler: The exception handler is very similar to the interrupt handler with a different mandatory function signature: #ifdef __x86_64__ typedef unsigned long long int uword_t; #else typedef unsigned int uword_t; #endif struct interrupt_frame; __attribute__ ((interrupt)) void f (struct interrupt_frame *frame, uword_t error_code) { ... } and compiler pops the error code off stack before the IRET instruction. The exception handler should only be used for exceptions which push an error code and all other exceptions must use the interrupt handler. The system will crash if the wrong handler is used. Differential Revision: http://reviews.llvm.org/D15709 llvm-svn: 257867
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp21
1 files changed, 21 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index f6f8405b0e0..2e73ee162ff 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -1609,6 +1609,10 @@ void X86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D,
llvm::AttributeSet::FunctionIndex,
B));
}
+ if (FD->hasAttr<AnyX86InterruptAttr>()) {
+ llvm::Function *Fn = cast<llvm::Function>(GV);
+ Fn->setCallingConv(llvm::CallingConv::X86_INTR);
+ }
}
}
@@ -1914,6 +1918,16 @@ public:
('T' << 24);
return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
}
+
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &CGM) const override {
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+ if (FD->hasAttr<AnyX86InterruptAttr>()) {
+ llvm::Function *Fn = cast<llvm::Function>(GV);
+ Fn->setCallingConv(llvm::CallingConv::X86_INTR);
+ }
+ }
+ }
};
class PS4TargetCodeGenInfo : public X86_64TargetCodeGenInfo {
@@ -2031,6 +2045,13 @@ void WinX86_64TargetCodeGenInfo::setTargetAttributes(const Decl *D,
CodeGen::CodeGenModule &CGM) const {
TargetCodeGenInfo::setTargetAttributes(D, GV, CGM);
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+ if (FD->hasAttr<AnyX86InterruptAttr>()) {
+ llvm::Function *Fn = cast<llvm::Function>(GV);
+ Fn->setCallingConv(llvm::CallingConv::X86_INTR);
+ }
+ }
+
addStackProbeSizeTargetAttribute(D, GV, CGM);
}
}
OpenPOWER on IntegriCloud