r191769 - Implement ARM GNU-style interrupt attribute

Timur Iskhodzhanov timurrrr at google.com
Tue Oct 1 07:47:05 PDT 2013


FYI this fails on Windows

FAILED: cmd.exe /c cd . && "C:\Program Files (x86)\CMake
2.8\bin\cmake.exe" -E vs_link_exe C:\PROGRA~2\MICROS~2.0\VC\bin\cl.exe
 /nologo  /DWIN32 /D_WINDOWS /W3 /Zm1000 /GR- /EHs-c-  /MD /O2 /Ob2
/Febin\diagtool.exe /Fdbin\diagtool.pdb
tools\clang\tools\diagtool\CMakeFiles\diagtool.dir\diagtool_main.cpp.obj
tools\clang\tools\diagtool\CMakeFiles\diagtool.dir\DiagTool.cpp.obj
tools\clang\tools\diagtool\CMakeFiles\diagtool.dir\DiagnosticNames.cpp.obj
tools\clang\tools\diagtool\CMakeFiles\diagtool.dir\ListWarnings.cpp.obj
tools\clang\tools\diagtool\CMakeFiles\diagtool.dir\ShowEnabledWarnings.cpp.obj
tools\clang\tools\diagtool\CMakeFiles\diagtool.dir\TreeView.cpp.obj
/link /implib:lib\diagtool.lib /version:0.0  /STACK:10000000
/machine:X86  /INCREMENTAL:NO /subsystem:console
lib\LLVMX86CodeGen.lib lib\LLVMX86AsmParser.lib
lib\LLVMX86Disassembler.lib lib\LLVMAsmParser.lib
lib\LLVMBitReader.lib lib\LLVMAsmPrinter.lib lib\LLVMSelectionDAG.lib
lib\LLVMX86Desc.lib lib\LLVMMCParser.lib lib\LLVMCodeGen.lib
lib\LLVMX86AsmPrinter.lib lib\LLVMX86Info.lib lib\LLVMObjCARCOpts.lib
lib\LLVMScalarOpts.lib lib\LLVMX86Utils.lib lib\LLVMInstCombine.lib
lib\LLVMTransformUtils.lib lib\LLVMipa.lib lib\LLVMAnalysis.lib
lib\LLVMTarget.lib lib\LLVMCore.lib lib\LLVMMC.lib lib\LLVMObject.lib
lib\LLVMSupport.lib lib\clangBasic.lib lib\clangLex.lib
lib\clangSema.lib lib\clangFrontend.lib lib\clangDriver.lib
lib\LLVMOption.lib lib\clangParse.lib lib\clangSerialization.lib
lib\LLVMBitReader.lib lib\clangSema.lib lib\LLVMX86CodeGen.lib
lib\LLVMX86AsmParser.lib lib\LLVMX86Disassembler.lib
lib\LLVMAsmParser.lib lib\LLVMAsmPrinter.lib lib\LLVMSelectionDAG.lib
lib\LLVMX86Desc.lib lib\LLVMMCParser.lib lib\LLVMCodeGen.lib
lib\LLVMX86AsmPrinter.lib lib\LLVMX86Info.lib lib\LLVMObjCARCOpts.lib
lib\LLVMScalarOpts.lib lib\LLVMX86Utils.lib lib\LLVMInstCombine.lib
lib\LLVMTransformUtils.lib lib\LLVMipa.lib lib\LLVMAnalysis.lib
lib\LLVMTarget.lib lib\LLVMCore.lib lib\clangAnalysis.lib
lib\clangEdit.lib lib\clangAST.lib lib\clangLex.lib lib\clangBasic.lib
lib\LLVMMC.lib lib\LLVMObject.lib lib\LLVMSupport.lib kernel32.lib
user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib
uuid.lib comdlg32.lib advapi32.lib && cd .
   Creating library lib\diagtool.lib and object lib\diagtool.exp


clangSerialization.lib(ASTReaderDecl.cpp.obj) : error LNK2001:
unresolved external symbol "public: virtual class
clang::ARMInterruptAttr * __thiscall
clang::ARMInterruptAttr::clone(class clang::ASTContext &)const "
(?clone at ARMInterruptAttr@clang@@UBEPAV12 at AAVASTContext@2@@Z)


clangSema.lib(TargetAttributesSema.cpp.obj) : error LNK2001:
unresolved external symbol "public: virtual class
clang::ARMInterruptAttr * __thiscall
clang::ARMInterruptAttr::clone(class clang::ASTContext &)const "
(?clone at ARMInterruptAttr@clang@@UBEPAV12 at AAVASTContext@2@@Z)


clangSerialization.lib(ASTReaderDecl.cpp.obj) : error LNK2001:
unresolved external symbol "public: virtual void __thiscall
clang::ARMInterruptAttr::printPretty(class llvm::raw_ostream &,struct
clang::PrintingPolicy const &)const "
(?printPretty at ARMInterruptAttr@clang@@UBEXAAVraw_ostream at llvm@@ABUPrintingPolicy at 2@@Z)


clangSema.lib(TargetAttributesSema.cpp.obj) : error LNK2019:
unresolved external symbol "public: virtual void __thiscall
clang::ARMInterruptAttr::printPretty(class llvm::raw_ostream &,struct
clang::PrintingPolicy const &)const "
(?printPretty at ARMInterruptAttr@clang@@UBEXAAVraw_ostream at llvm@@ABUPrintingPolicy at 2@@Z)
referenced in function "private: class clang::ExtQualsTypeCommonBase
const * __thiscall clang::QualType::getCommonPtr(void)const "
(?getCommonPtr at QualType@clang@@ABEPBVExtQualsTypeCommonBase at 2@XZ)

2013/10/1 Tim Northover <tnorthover at apple.com>:
> Author: tnorthover
> Date: Tue Oct  1 09:34:25 2013
> New Revision: 191769
>
> URL: http://llvm.org/viewvc/llvm-project?rev=191769&view=rev
> Log:
> 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
>
> Added:
>     cfe/trunk/test/CodeGen/arm-interrupt-attr.c
>     cfe/trunk/test/Sema/arm-interrupt-attr.c
> Modified:
>     cfe/trunk/docs/LanguageExtensions.rst
>     cfe/trunk/include/clang/Basic/Attr.td
>     cfe/trunk/lib/CodeGen/TargetInfo.cpp
>     cfe/trunk/lib/Sema/SemaDeclAttr.cpp
>     cfe/trunk/lib/Sema/TargetAttributesSema.cpp
>
> Modified: cfe/trunk/docs/LanguageExtensions.rst
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=191769&r1=191768&r2=191769&view=diff
> ==============================================================================
> --- cfe/trunk/docs/LanguageExtensions.rst (original)
> +++ cfe/trunk/docs/LanguageExtensions.rst Tue Oct  1 09:34:25 2013
> @@ -1843,6 +1843,48 @@ Which compiles to (on X86-32):
>            movl    %gs:(%eax), %eax
>            ret
>
> +ARM Language Extensions
> +-----------------------
> +
> +Interrupt attribute
> +^^^^^^^^^^^^^^^^^^^
> +
> +Clang supports the GNU style ``__attribite__((interrupt("TYPE")))`` attribute on
> +ARM targets. This attribute may be attached to a function definiton 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: "IRQ",
> +"FIQ", "SWI", "ABORT", "UNDEF".
> +
> +The semantics are as follows:
> +
> +- If the function is AAPCS, Clang instructs the backend to realign the stack to
> +  8 bytes on entry. This is a general requirement of the AAPCS at public
> +  interfaces, but may not hold when an exception is taken. Doing this allows
> +  other AAPCS functions to be called.
> +- If the CPU is M-class this is all that needs to be done since the architecture
> +  itself is designed in such a way that functions obeying the normal AAPCS ABI
> +  constraints are valid exception handlers.
> +- If the CPU is not M-class, the prologue and epilogue are modified to save all
> +  non-banked registers that are used, so that upon return the user-mode state
> +  will not be corrupted. Note that to avoid unnecessary overhead, only
> +  general-purpose (integer) registers are saved in this way. If VFP operations
> +  are needed, that state must be saved manually.
> +
> +  Specifically, interrupt kinds other than "FIQ" will save all core registers
> +  except "lr" and "sp". "FIQ" interrupts will save r0-r7.
> +- If the CPU is not M-class, the return instruction is changed to one of the
> +  canonical sequences permitted by the architecture for exception return. Where
> +  possible the function itself will make the necessary "lr" adjustments so that
> +  the "preferred return address" is selected.
> +
> +  Unfortunately the compiler is unable to make this guarantee for nn "UNDEF"
> +  handler, where the offset from "lr" to the preferred return address depends on
> +  the execution state of the code which generated the exception. In this case
> +  a sequence equivalent to "movs pc, lr" will be used.
> +
>  Extensions for Static Analysis
>  ==============================
>
>
> Modified: cfe/trunk/include/clang/Basic/Attr.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=191769&r1=191768&r2=191769&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Attr.td (original)
> +++ cfe/trunk/include/clang/Basic/Attr.td Tue Oct  1 09:34:25 2013
> @@ -210,6 +210,14 @@ def Annotate : InheritableParamAttr {
>    let Args = [StringArgument<"Annotation">];
>  }
>
> +def ARMInterrupt : InheritableAttr, TargetSpecificAttr {
> +  let Spellings = [GNU<"interrupt">];
> +  let Args = [EnumArgument<"Interrupt", "InterruptType",
> +                           ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", ""],
> +                           ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", "Generic"],
> +                           1>];
> +}
> +
>  def AsmLabel : InheritableAttr {
>    let Spellings = [];
>    let Args = [StringArgument<"Label">];
>
> Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=191769&r1=191768&r2=191769&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
> +++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Tue Oct  1 09:34:25 2013
> @@ -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));
> +  }
> +
>  };
>
>  }
>
> Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=191769&r1=191768&r2=191769&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Oct  1 09:34:25 2013
> @@ -289,7 +289,7 @@ static bool checkFunctionOrMethodArgumen
>  /// literal.
>  bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
>                                            unsigned ArgNum, StringRef &Str,
> -                                          SourceLocation *ArgLocation = 0) {
> +                                          SourceLocation *ArgLocation) {
>    // Look for identifiers. If we have one emit a hint to fix it to a literal.
>    if (Attr.isArgIdent(ArgNum)) {
>      IdentifierLoc *Loc = Attr.getArgAsIdent(ArgNum);
>
> Modified: cfe/trunk/lib/Sema/TargetAttributesSema.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TargetAttributesSema.cpp?rev=191769&r1=191768&r2=191769&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/TargetAttributesSema.cpp (original)
> +++ cfe/trunk/lib/Sema/TargetAttributesSema.cpp Tue Oct  1 09:34:25 2013
> @@ -26,6 +26,50 @@ bool TargetAttributesSema::ProcessDeclAt
>    return false;
>  }
>
> +static void HandleARMInterruptAttr(Decl *d,
> +                                   const AttributeList &Attr, Sema &S) {
> +  // Check the attribute arguments.
> +  if (Attr.getNumArgs() > 1) {
> +    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments)
> +        << 1;
> +    return;
> +  }
> +
> +  StringRef Str;
> +  SourceLocation ArgLoc;
> +
> +  if (Attr.getNumArgs() == 0)
> +    Str = "";
> +  else if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &ArgLoc))
> +    return;
> +
> +  ARMInterruptAttr::InterruptType Kind;
> +  if (!ARMInterruptAttr::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)
> +             ARMInterruptAttr(Attr.getLoc(), S.Context, Kind, Index));
> +}
> +
> +namespace {
> +  class ARMAttributesSema : public TargetAttributesSema {
> +  public:
> +    ARMAttributesSema() { }
> +    bool ProcessDeclAttribute(Scope *scope, Decl *D,
> +                              const AttributeList &Attr, Sema &S) const {
> +      if (Attr.getName()->getName() == "interrupt") {
> +        HandleARMInterruptAttr(D, Attr, S);
> +        return true;
> +      }
> +      return false;
> +    }
> +  };
> +}
> +
>  static void HandleMSP430InterruptAttr(Decl *d,
>                                        const AttributeList &Attr, Sema &S) {
>      // Check the attribute arguments.
> @@ -292,6 +336,9 @@ const TargetAttributesSema &Sema::getTar
>
>    const llvm::Triple &Triple(Context.getTargetInfo().getTriple());
>    switch (Triple.getArch()) {
> +  case llvm::Triple::arm:
> +  case llvm::Triple::thumb:
> +    return *(TheTargetAttributesSema = new ARMAttributesSema);
>    case llvm::Triple::msp430:
>      return *(TheTargetAttributesSema = new MSP430AttributesSema);
>    case llvm::Triple::x86:
>
> Added: cfe/trunk/test/CodeGen/arm-interrupt-attr.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm-interrupt-attr.c?rev=191769&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGen/arm-interrupt-attr.c (added)
> +++ cfe/trunk/test/CodeGen/arm-interrupt-attr.c Tue Oct  1 09:34:25 2013
> @@ -0,0 +1,38 @@
> +// RUN: %clang_cc1 -triple thumb-apple-darwin -target-abi aapcs -target-cpu cortex-m3 -emit-llvm -o - %s | FileCheck %s
> +// RUN: %clang_cc1 -triple arm-apple-darwin -target-abi apcs-gnu -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-APCS
> +
> +__attribute__((interrupt)) void test_generic_interrupt() {
> +  // CHECK: define arm_aapcscc void @test_generic_interrupt() [[GENERIC_ATTR:#[0-9]+]]
> +
> +  // CHECK-APCS: define void @test_generic_interrupt() [[GENERIC_ATTR:#[0-9]+]]
> +}
> +
> +__attribute__((interrupt("IRQ"))) void test_irq_interrupt() {
> +  // CHECK: define arm_aapcscc void @test_irq_interrupt() [[IRQ_ATTR:#[0-9]+]]
> +}
> +
> +__attribute__((interrupt("FIQ"))) void test_fiq_interrupt() {
> +  // CHECK: define arm_aapcscc void @test_fiq_interrupt() [[FIQ_ATTR:#[0-9]+]]
> +}
> +
> +__attribute__((interrupt("SWI"))) void test_swi_interrupt() {
> +  // CHECK: define arm_aapcscc void @test_swi_interrupt() [[SWI_ATTR:#[0-9]+]]
> +}
> +
> +__attribute__((interrupt("ABORT"))) void test_abort_interrupt() {
> +  // CHECK: define arm_aapcscc void @test_abort_interrupt() [[ABORT_ATTR:#[0-9]+]]
> +}
> +
> +
> +__attribute__((interrupt("UNDEF"))) void test_undef_interrupt() {
> +  // CHECK: define arm_aapcscc void @test_undef_interrupt() [[UNDEF_ATTR:#[0-9]+]]
> +}
> +
> +// CHECK: attributes [[GENERIC_ATTR]] = { nounwind alignstack=8 {{"interrupt"[^=]}}
> +// CHECK: attributes [[IRQ_ATTR]] = { nounwind alignstack=8 "interrupt"="IRQ"
> +// CHECK: attributes [[FIQ_ATTR]] = { nounwind alignstack=8 "interrupt"="FIQ"
> +// CHECK: attributes [[SWI_ATTR]] = { nounwind alignstack=8 "interrupt"="SWI"
> +// CHECK: attributes [[ABORT_ATTR]] = { nounwind alignstack=8 "interrupt"="ABORT"
> +// CHECK: attributes [[UNDEF_ATTR]] = { nounwind alignstack=8 "interrupt"="UNDEF"
> +
> +// CHECK-APCS: attributes [[GENERIC_ATTR]] = { nounwind "interrupt"
>
> Added: cfe/trunk/test/Sema/arm-interrupt-attr.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/arm-interrupt-attr.c?rev=191769&view=auto
> ==============================================================================
> --- cfe/trunk/test/Sema/arm-interrupt-attr.c (added)
> +++ cfe/trunk/test/Sema/arm-interrupt-attr.c Tue Oct  1 09:34:25 2013
> @@ -0,0 +1,16 @@
> +// RUN: %clang_cc1 %s -triple arm-apple-darwin -verify -fsyntax-only
> +
> +__attribute__((interrupt(IRQ))) void foo() {} // expected-error {{'interrupt' attribute requires a string}}
> +__attribute__((interrupt("irq"))) void foo1() {} // expected-warning {{'interrupt' attribute argument not supported: irq}}
> +
> +__attribute__((interrupt("IRQ", 1))) void foo2() {} // expected-error {{attribute takes no more than 1 argument}}
> +
> +__attribute__((interrupt("IRQ"))) void foo3() {}
> +__attribute__((interrupt("FIQ"))) void foo4() {}
> +__attribute__((interrupt("SWI"))) void foo5() {}
> +__attribute__((interrupt("ABORT"))) void foo6() {}
> +__attribute__((interrupt("UNDEF"))) void foo7() {}
> +
> +__attribute__((interrupt)) void foo8() {}
> +__attribute__((interrupt())) void foo9() {}
> +__attribute__((interrupt(""))) void foo10() {}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list