diff options
author | Tim Northover <tnorthover@apple.com> | 2013-10-01 14:34:25 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2013-10-01 14:34:25 +0000 |
commit | a484bc00ff592bd2efb9c37c70222994aa6f9508 (patch) | |
tree | 31934e502d5bddc5f1558ed71e16711f08845ce1 /clang/lib/CodeGen/TargetInfo.cpp | |
parent | 6a6b63b464e55ff2bd124fca468a8a800b6cd8cd (diff) | |
download | bcm5719-llvm-a484bc00ff592bd2efb9c37c70222994aa6f9508.tar.gz bcm5719-llvm-a484bc00ff592bd2efb9c37c70222994aa6f9508.zip |
Implement ARM GNU-style interrupt attribute
This attribute allows users to use a modified C or C++ function as an ARM
exception-handling function and, with care, to successfully return control to
user-space after the issue has been dealt with.
rdar://problem/14207019
llvm-svn: 191769
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 0706a289170..01efd119c74 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -3056,9 +3056,9 @@ public: Env == "android" || Env == "androideabi"); } -private: ABIKind getABIKind() const { return Kind; } +private: ABIArgInfo classifyReturnType(QualType RetTy) const; ABIArgInfo classifyArgumentType(QualType RetTy, int *VFPRegs, unsigned &AllocatedVFP, @@ -3105,6 +3105,45 @@ public: if (getABIInfo().isEABI()) return 88; return TargetCodeGenInfo::getSizeOfUnwindException(); } + + void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV, + CodeGen::CodeGenModule &CGM) const { + const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (!FD) + return; + + const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>(); + if (!Attr) + return; + + const char *Kind; + switch (Attr->getInterrupt()) { + case ARMInterruptAttr::Generic: Kind = ""; break; + case ARMInterruptAttr::IRQ: Kind = "IRQ"; break; + case ARMInterruptAttr::FIQ: Kind = "FIQ"; break; + case ARMInterruptAttr::SWI: Kind = "SWI"; break; + case ARMInterruptAttr::ABORT: Kind = "ABORT"; break; + case ARMInterruptAttr::UNDEF: Kind = "UNDEF"; break; + } + + llvm::Function *Fn = cast<llvm::Function>(GV); + + Fn->addFnAttr("interrupt", Kind); + + if (cast<ARMABIInfo>(getABIInfo()).getABIKind() == ARMABIInfo::APCS) + return; + + // AAPCS guarantees that sp will be 8-byte aligned on any public interface, + // however this is not necessarily true on taking any interrupt. Instruct + // the backend to perform a realignment as part of the function prologue. + llvm::AttrBuilder B; + B.addStackAlignmentAttr(8); + Fn->addAttributes(llvm::AttributeSet::FunctionIndex, + llvm::AttributeSet::get(CGM.getLLVMContext(), + llvm::AttributeSet::FunctionIndex, + B)); + } + }; } |