]> granicus.if.org Git - clang/commitdiff
Generalize target weirdness handling having proper layering in mind:
authorAnton Korobeynikov <asl@math.spbu.ru>
Sun, 10 Jan 2010 12:58:08 +0000 (12:58 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Sun, 10 Jan 2010 12:58:08 +0000 (12:58 +0000)
 1. Add helper class for sema checks for target attributes
 2. Add helper class for codegen of target attributes

As a proof-of-concept - implement msp430's 'interrupt' attribute.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93118 91177308-0d34-0410-b5e6-96231b3b80d8

14 files changed:
include/clang/AST/Attr.h
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/CodeGenTypes.cpp
lib/CodeGen/CodeGenTypes.h
lib/CodeGen/TargetInfo.cpp
lib/CodeGen/TargetInfo.h [new file with mode: 0644]
lib/Frontend/PCHReaderDecl.cpp
lib/Frontend/PCHWriter.cpp
lib/Sema/Sema.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclAttr.cpp
lib/Sema/TargetAttributesSema.cpp [new file with mode: 0644]
lib/Sema/TargetAttributesSema.h [new file with mode: 0644]

index 2c7ab9d67e95392245937d202b6e314e423b2103..f11374b70b792bc7acef1bc0eba7221451e8a7c2 100644 (file)
@@ -55,8 +55,6 @@ public:
     Cleanup,
     Const,
     Constructor,
-    DLLExport,
-    DLLImport,
     Deprecated,
     Destructor,
     FastCall,
@@ -93,7 +91,12 @@ public:
     Visibility,
     WarnUnusedResult,
     Weak,
-    WeakImport
+    WeakImport,
+
+    FIRST_TARGET_ATTRIBUTE,
+    DLLExport,
+    DLLImport,
+    MSP430Interrupt
   };
 
 private:
@@ -456,8 +459,6 @@ public:
   static bool classof(const VisibilityAttr *A) { return true; }
 };
 
-DEF_SIMPLE_ATTR(DLLImport);
-DEF_SIMPLE_ATTR(DLLExport);
 DEF_SIMPLE_ATTR(FastCall);
 DEF_SIMPLE_ATTR(StdCall);
 DEF_SIMPLE_ATTR(CDecl);
@@ -566,6 +567,27 @@ DEF_SIMPLE_ATTR(BaseCheck);
 DEF_SIMPLE_ATTR(Hiding);
 DEF_SIMPLE_ATTR(Override);
 
+// Target-specific attributes
+DEF_SIMPLE_ATTR(DLLImport);
+DEF_SIMPLE_ATTR(DLLExport);
+
+class MSP430InterruptAttr : public Attr {
+  unsigned Number;
+
+public:
+  MSP430InterruptAttr(unsigned n) : Attr(MSP430Interrupt), Number(n) {}
+
+  unsigned getNumber() const { return Number; }
+
+  virtual Attr *clone(ASTContext &C) const {
+    return ::new (C) MSP430InterruptAttr(Number);
+  }
+
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Attr *A) { return A->getKind() == MSP430Interrupt; }
+  static bool classof(const MSP430InterruptAttr *A) { return true; }
+};
+
 #undef DEF_SIMPLE_ATTR
 
 }  // end namespace clang
index eb716b6ab181541860cd26d56968e0581781ee3c..5ecc30eb4ea227cee15eaaf36eed39ef5e0f4911 100644 (file)
@@ -17,6 +17,7 @@
 #include "CGCall.h"
 #include "CGObjCRuntime.h"
 #include "Mangle.h"
+#include "TargetInfo.h"
 #include "clang/CodeGen/CodeGenOptions.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
@@ -42,8 +43,9 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
                              Diagnostic &diags)
   : BlockModule(C, M, TD, Types, *this), Context(C),
     Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M),
-    TheTargetData(TD), Diags(diags), Types(C, M, TD), MangleCtx(C), 
-    VtableInfo(*this), Runtime(0),
+    TheTargetData(TD), TheTargetCodeGenInfo(0), Diags(diags),
+    Types(C, M, TD, getTargetCodeGenInfo().getABIInfo()),
+    MangleCtx(C), VtableInfo(*this), Runtime(0),
     MemCpyFn(0), MemMoveFn(0), MemSetFn(0), CFConstantStringClassRef(0),
     VMContext(M.getContext()) {
 
@@ -376,6 +378,8 @@ void CodeGenModule::SetCommonAttributes(const Decl *D,
 
   if (const SectionAttr *SA = D->getAttr<SectionAttr>())
     GV->setSection(SA->getName());
+
+  getTargetCodeGenInfo().SetTargetAttributes(D, GV, *this);
 }
 
 void CodeGenModule::SetInternalFunctionAttributes(const Decl *D,
index 47d8c54cd980cde37aa867a3f1b223c37274e03f..c7aa7a47a83644d6125fea8d3f80bdbc342732af 100644 (file)
@@ -43,6 +43,7 @@ namespace llvm {
 }
 
 namespace clang {
+  class TargetCodeGenInfo;
   class ASTContext;
   class FunctionDecl;
   class IdentifierInfo;
@@ -85,6 +86,7 @@ class CodeGenModule : public BlockModule {
   const CodeGenOptions &CodeGenOpts;
   llvm::Module &TheModule;
   const llvm::TargetData &TheTargetData;
+  mutable const TargetCodeGenInfo *TheTargetCodeGenInfo;
   Diagnostic &Diags;
   CodeGenTypes Types;
   MangleContext MangleCtx;
@@ -191,6 +193,7 @@ public:
   Diagnostic &getDiags() const { return Diags; }
   const llvm::TargetData &getTargetData() const { return TheTargetData; }
   llvm::LLVMContext &getLLVMContext() { return VMContext; }
+  const TargetCodeGenInfo &getTargetCodeGenInfo() const;
 
   /// getDeclVisibilityMode - Compute the visibility of the decl \arg D.
   LangOptions::VisibilityMode getDeclVisibilityMode(const Decl *D) const;
index cd34e0c064ef54f08be720c83792c18ff59c1696..bfea2367a92d0cbacda0b948e6603bdc892e795f 100644 (file)
@@ -28,9 +28,9 @@ using namespace clang;
 using namespace CodeGen;
 
 CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M,
-                           const llvm::TargetData &TD)
+                           const llvm::TargetData &TD, const ABIInfo &Info)
   : Context(Ctx), Target(Ctx.Target), TheModule(M), TheTargetData(TD),
-    TheABIInfo(0) {
+    TheABIInfo(Info) {
 }
 
 CodeGenTypes::~CodeGenTypes() {
@@ -44,7 +44,6 @@ CodeGenTypes::~CodeGenTypes() {
     while (I != E)
       delete &*I++;
   }
-  delete TheABIInfo;
 }
 
 /// ConvertType - Convert the specified type to its LLVM form.
index 2ff602f900fa85af506dd68143a6adf77540858a..7e342526e84be478708d0a66a7cbd4fc67d8c655 100644 (file)
@@ -85,7 +85,7 @@ class CodeGenTypes {
   const TargetInfo &Target;
   llvm::Module& TheModule;
   const llvm::TargetData& TheTargetData;
-  mutable const ABIInfo* TheABIInfo;
+  const ABIInfo& TheABIInfo;
 
   llvm::SmallVector<std::pair<QualType,
                               llvm::OpaqueType *>, 8>  PointersToResolve;
@@ -140,13 +140,14 @@ private:
   /// interface to convert type T into a llvm::Type.
   const llvm::Type *ConvertNewType(QualType T);
 public:
-  CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD);
+  CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD,
+               const ABIInfo &Info);
   ~CodeGenTypes();
 
   const llvm::TargetData &getTargetData() const { return TheTargetData; }
   const TargetInfo &getTarget() const { return Target; }
   ASTContext &getContext() const { return Context; }
-  const ABIInfo &getABIInfo() const;
+  const ABIInfo &getABIInfo() const { return TheABIInfo; }
   llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); }
 
   /// ConvertType - Convert type T into a llvm::Type.
index 863a297cc6a5ed1d30ac37e6232e69c0afce9002..e5fd47ec2d168ea7e834382f96059b02d3b6f920 100644 (file)
@@ -1,4 +1,4 @@
-//===---- TargetABIInfo.cpp - Encapsulate target ABI details ----*- C++ -*-===//
+//===---- TargetInfo.cpp - Encapsulate target details -----------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
 //
 //===----------------------------------------------------------------------===//
 
+#include "TargetInfo.h"
 #include "ABIInfo.h"
 #include "CodeGenFunction.h"
 #include "clang/AST/RecordLayout.h"
 #include "llvm/Type.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
@@ -50,6 +52,8 @@ void ABIArgInfo::dump() const {
   OS << ")\n";
 }
 
+TargetCodeGenInfo::~TargetCodeGenInfo() { delete Info; }
+
 static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
 
 /// isEmptyField - Return true iff a the field is "empty", that is it
@@ -251,6 +255,27 @@ class DefaultABIInfo : public ABIInfo {
                                  CodeGenFunction &CGF) const;
 };
 
+class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  DefaultTargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {};
+};
+
+llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+                                       CodeGenFunction &CGF) const {
+  return 0;
+}
+
+ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty,
+                                                ASTContext &Context,
+                                          llvm::LLVMContext &VMContext) const {
+  if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
+    return ABIArgInfo::getIndirect(0);
+  } else {
+    return (Ty->isPromotableIntegerType() ?
+            ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+  }
+}
+
 /// X86_32ABIInfo - The X86-32 ABI information.
 class X86_32ABIInfo : public ABIInfo {
   ASTContext &Context;
@@ -291,8 +316,14 @@ public:
     : ABIInfo(), Context(Context), IsDarwinVectorABI(d),
       IsSmallStructInRegABI(p) {}
 };
-}
 
+class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  X86_32TargetCodeGenInfo(ASTContext &Context, bool d, bool p)
+    :TargetCodeGenInfo(new X86_32ABIInfo(Context, d, p)) {};
+};
+
+}
 
 /// shouldReturnTypeInRegister - Determine if the given type should be
 /// passed in a register (for the Darwin ABI).
@@ -585,6 +616,12 @@ public:
   virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
                                  CodeGenFunction &CGF) const;
 };
+
+class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  X86_64TargetCodeGenInfo():TargetCodeGenInfo(new X86_64ABIInfo()) {};
+};
+
 }
 
 X86_64ABIInfo::Class X86_64ABIInfo::merge(Class Accum,
@@ -1389,6 +1426,11 @@ class PIC16ABIInfo : public ABIInfo {
                                  CodeGenFunction &CGF) const;
 };
 
+class PIC16TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  PIC16TargetCodeGenInfo():TargetCodeGenInfo(new PIC16ABIInfo()) {};
+};
+
 }
 
 ABIArgInfo PIC16ABIInfo::classifyReturnType(QualType RetTy,
@@ -1448,6 +1490,12 @@ private:
                                  CodeGenFunction &CGF) const;
 };
 
+class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ARMTargetCodeGenInfo(ARMABIInfo::ABIKind K)
+    :TargetCodeGenInfo(new ARMABIInfo(K)) {};
+};
+
 }
 
 void ARMABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context,
@@ -1704,6 +1752,11 @@ class SystemZABIInfo : public ABIInfo {
                                  CodeGenFunction &CGF) const;
 };
 
+class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  SystemZTargetCodeGenInfo():TargetCodeGenInfo(new SystemZABIInfo()) {};
+};
+
 }
 
 bool SystemZABIInfo::isPromotableIntegerType(QualType Ty) const {
@@ -1757,51 +1810,79 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty,
   }
 }
 
-ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty,
-                                                ASTContext &Context,
-                                          llvm::LLVMContext &VMContext) const {
-  if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
-    return ABIArgInfo::getIndirect(0);
-  } else {
-    return (Ty->isPromotableIntegerType() ?
-            ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
-  }
+// MSP430 ABI Implementation
+
+namespace {
+
+class MSP430TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  MSP430TargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {};
+  void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+                           CodeGen::CodeGenModule &M) const;
+};
+
 }
 
-llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
-                                       CodeGenFunction &CGF) const {
-  return 0;
+void MSP430TargetCodeGenInfo::SetTargetAttributes(const Decl *D,
+                                                  llvm::GlobalValue *GV,
+                                             CodeGen::CodeGenModule &M) const {
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    if (const MSP430InterruptAttr *attr = FD->getAttr<MSP430InterruptAttr>()) {
+      // Handle 'interrupt' attribute:
+      llvm::Function *F = cast<llvm::Function>(GV);
+
+      // Step 1: Set ISR calling convention.
+      F->setCallingConv(llvm::CallingConv::MSP430_INTR);
+
+      // Step 2: Add attributes goodness.
+      F->addFnAttr(llvm::Attribute::NoInline);
+
+      // Step 3: Emit ISR vector alias.
+      unsigned Num = attr->getNumber() + 0xffe0;
+      new llvm::GlobalAlias(GV->getType(), llvm::Function::ExternalLinkage,
+                            "vector_" +
+                            llvm::LowercaseString(llvm::utohexstr(Num)),
+                            GV, &M.getModule());
+    }
+  }
 }
 
-const ABIInfo &CodeGenTypes::getABIInfo() const {
-  if (TheABIInfo)
-    return *TheABIInfo;
+const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() const {
+  if (TheTargetCodeGenInfo)
+    return *TheTargetCodeGenInfo;
 
-  // For now we just cache the ABIInfo in CodeGenTypes and don't free it.
+  // For now we just cache the TargetCodeGenInfo in CodeGenModule and don't
+  // free it.
 
   const llvm::Triple &Triple(getContext().Target.getTriple());
   switch (Triple.getArch()) {
   default:
-    return *(TheABIInfo = new DefaultABIInfo);
+    return *(TheTargetCodeGenInfo = new DefaultTargetCodeGenInfo);
 
   case llvm::Triple::arm:
   case llvm::Triple::thumb:
     // FIXME: We want to know the float calling convention as well.
     if (strcmp(getContext().Target.getABI(), "apcs-gnu") == 0)
-      return *(TheABIInfo = new ARMABIInfo(ARMABIInfo::APCS));
+      return *(TheTargetCodeGenInfo =
+               new ARMTargetCodeGenInfo(ARMABIInfo::APCS));
 
-    return *(TheABIInfo = new ARMABIInfo(ARMABIInfo::AAPCS));
+    return *(TheTargetCodeGenInfo =
+             new ARMTargetCodeGenInfo(ARMABIInfo::AAPCS));
 
   case llvm::Triple::pic16:
-    return *(TheABIInfo = new PIC16ABIInfo());
+    return *(TheTargetCodeGenInfo = new PIC16TargetCodeGenInfo());
 
   case llvm::Triple::systemz:
-    return *(TheABIInfo = new SystemZABIInfo());
+    return *(TheTargetCodeGenInfo = new SystemZTargetCodeGenInfo());
+
+  case llvm::Triple::msp430:
+    return *(TheTargetCodeGenInfo = new MSP430TargetCodeGenInfo());
 
   case llvm::Triple::x86:
     switch (Triple.getOS()) {
     case llvm::Triple::Darwin:
-      return *(TheABIInfo = new X86_32ABIInfo(Context, true, true));
+      return *(TheTargetCodeGenInfo =
+               new X86_32TargetCodeGenInfo(Context, true, true));
     case llvm::Triple::Cygwin:
     case llvm::Triple::MinGW32:
     case llvm::Triple::MinGW64:
@@ -1809,13 +1890,15 @@ const ABIInfo &CodeGenTypes::getABIInfo() const {
     case llvm::Triple::DragonFly:
     case llvm::Triple::FreeBSD:
     case llvm::Triple::OpenBSD:
-      return *(TheABIInfo = new X86_32ABIInfo(Context, false, true));
+      return *(TheTargetCodeGenInfo =
+               new X86_32TargetCodeGenInfo(Context, false, true));
 
     default:
-      return *(TheABIInfo = new X86_32ABIInfo(Context, false, false));
+      return *(TheTargetCodeGenInfo =
+               new X86_32TargetCodeGenInfo(Context, false, false));
     }
 
   case llvm::Triple::x86_64:
-    return *(TheABIInfo = new X86_64ABIInfo());
+    return *(TheTargetCodeGenInfo = new X86_64TargetCodeGenInfo());
   }
 }
diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h
new file mode 100644 (file)
index 0000000..495b22f
--- /dev/null
@@ -0,0 +1,50 @@
+//===---- TargetInfo.h - Encapsulate target details -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes wrap the information about a call or function
+// definition used to handle ABI compliancy.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_TARGETINFO_H
+#define CLANG_CODEGEN_TARGETINFO_H
+
+namespace llvm {
+  class GlobalValue;
+}
+
+namespace clang {
+  class ABIInfo;
+  class Decl;
+
+  namespace CodeGen {
+    class CodeGenModule;
+  }
+
+  /// TargetCodeGenInfo - This class organizes various target-specific
+  /// codegeneration issues, like target-specific attributes, builtins and so
+  /// on.
+  class TargetCodeGenInfo {
+    ABIInfo *Info;
+  public:
+    // WARNING: Acquires the ownership of ABIInfo.
+    TargetCodeGenInfo(ABIInfo *info = 0):Info(info) { };
+    virtual ~TargetCodeGenInfo();
+
+    /// getABIInfo() - Returns ABI info helper for the target.
+    const ABIInfo& getABIInfo() const { return *Info; }
+
+    /// SetTargetAttributes - Provides a convenient hook to handle extra
+    /// target-specific attributes for the given global.
+    virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+                                     CodeGen::CodeGenModule &M) const { };
+  };
+}
+
+#endif // CLANG_CODEGEN_TARGETINFO_H
index 91568f182da60747f93d27aa0a666f17783e0033..69343ed48c4b812cc1ddfe76a4a051f8d6cd5dd9 100644 (file)
@@ -438,6 +438,9 @@ Attr *PCHReader::ReadAttributes() {
     bool IsInherited = Record[Idx++];
 
     switch (Kind) {
+    default:
+      assert(0 && "Unknown attribute!");
+      break;
     STRING_ATTR(Alias);
     UNSIGNED_ATTR(Aligned);
     SIMPLE_ATTR(AlwaysInline);
index 39e5d6f46bf3157f64769e60977a6193c5540894..84a8a450b0c238bb514b5d1745072ae95c1717db 100644 (file)
@@ -1739,9 +1739,12 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) {
 void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
   RecordData Record;
   for (; Attr; Attr = Attr->getNext()) {
-    Record.push_back(Attr->getKind()); // FIXME: stable encoding
+    Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs
     Record.push_back(Attr->isInherited());
     switch (Attr->getKind()) {
+    default:
+      assert(0 && "Does not support PCH writing for this attribute yet!");
+      break;
     case Attr::Alias:
       AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
       break;
index b32ddfd2093ac71c03872d9264cc6801503849e8..fefe924bc46f7ccfb917807aa636dceaa771d4bb 100644 (file)
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Sema.h"
+#include "TargetAttributesSema.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/APFloat.h"
 #include "clang/AST/ASTConsumer.h"
@@ -347,7 +348,8 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
 Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
            bool CompleteTranslationUnit,
            CodeCompleteConsumer *CodeCompleter)
-  : LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
+  : TheTargetAttributesSema(0),
+    LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
     Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
     ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), 
     CurBlock(0), PackContext(0), ParsingDeclDepth(0),
@@ -368,6 +370,11 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
                   ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
 }
 
+Sema::~Sema() {
+  if (PackContext) FreePackedContext();
+  delete TheTargetAttributesSema;
+}
+
 /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
 /// If there is already an implicit cast, merge into the existing one.
 /// If isLvalue, the result of the cast is an lvalue.
index 54dd060fcee729513139d0ba83b153dc20a18b1c..f487fbeb5b49e94b9a35561eecf25a90761ff284 100644 (file)
@@ -101,6 +101,7 @@ namespace clang {
   class InitializationKind;
   class InitializationSequence;
   class VisibleDeclConsumer;
+  class TargetAttributesSema;
 
 /// BlockSemaInfo - When a block is being parsed, this contains information
 /// about the block.  It is pointed to from Sema::CurBlock.
@@ -176,6 +177,7 @@ public:
 class Sema : public Action {
   Sema(const Sema&);           // DO NOT IMPLEMENT
   void operator=(const Sema&); // DO NOT IMPLEMENT
+  mutable const TargetAttributesSema* TheTargetAttributesSema;
 public:
   const LangOptions &LangOpts;
   Preprocessor &PP;
@@ -426,13 +428,12 @@ public:
   Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
        bool CompleteTranslationUnit = true,
        CodeCompleteConsumer *CompletionConsumer = 0);
-  ~Sema() {
-    if (PackContext) FreePackedContext();
-  }
+  ~Sema();
 
   const LangOptions &getLangOptions() const { return LangOpts; }
   Diagnostic &getDiagnostics() const { return Diags; }
   SourceManager &getSourceManager() const { return SourceMgr; }
+  const TargetAttributesSema &getTargetAttributesSema() const;
 
   /// \brief Helper class that creates diagnostics with optional
   /// template instantiation stacks.
index 094e5b56e558ef09dc3655f8c5b008010455cfd3..ceab525db128c2f0819b6dd538989ea44a060bb3 100644 (file)
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Sema.h"
+#include "TargetAttributesSema.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/Expr.h"
@@ -1959,7 +1960,10 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
     // Just ignore
     break;
   default:
-    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+    // Ask target about the attribute.
+    const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
+    if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
+      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
     break;
   }
 }
diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp
new file mode 100644 (file)
index 0000000..7c19bf6
--- /dev/null
@@ -0,0 +1,86 @@
+//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains semantic analysis implementation for target-specific
+// attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "TargetAttributesSema.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace clang;
+
+TargetAttributesSema::~TargetAttributesSema() {}
+bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
+                                    const AttributeList &Attr, Sema &S) const {
+  return false;
+}
+
+static void HandleMSP430InterruptAttr(Decl *d,
+                                      const AttributeList &Attr, Sema &S) {
+    // Check the attribute arguments.
+    if (Attr.getNumArgs() != 1) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+      return;
+    }
+
+    // FIXME: Check for decl - it should be void ()(void).
+
+    Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
+    llvm::APSInt NumParams(32);
+    if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+        << "interrupt" << NumParamsExpr->getSourceRange();
+      return;
+    }
+
+    unsigned Num = NumParams.getLimitedValue(255);
+    if ((Num & 1) || Num > 30) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+        << "interrupt" << (int)NumParams.getSExtValue()
+        << NumParamsExpr->getSourceRange();
+      return;
+    }
+
+    d->addAttr(::new (S.Context) MSP430InterruptAttr(Num));
+    d->addAttr(::new (S.Context) UsedAttr());
+  }
+
+namespace {
+  class MSP430AttributesSema : public TargetAttributesSema {
+  public:
+    MSP430AttributesSema() { }
+    bool ProcessDeclAttribute(Scope *scope, Decl *D,
+                              const AttributeList &Attr, Sema &S) const {
+      if (Attr.getName()->getName() == "interrupt") {
+        HandleMSP430InterruptAttr(D, Attr, S);
+        return true;
+      }
+      return false;
+    }
+  };
+}
+
+const TargetAttributesSema &Sema::getTargetAttributesSema() const {
+  if (TheTargetAttributesSema)
+    return *TheTargetAttributesSema;
+
+  const llvm::Triple &Triple(Context.Target.getTriple());
+  switch (Triple.getArch()) {
+  default:
+    return *(TheTargetAttributesSema = new TargetAttributesSema);
+
+  case llvm::Triple::msp430:
+    return *(TheTargetAttributesSema = new MSP430AttributesSema);
+  }
+}
+
diff --git a/lib/Sema/TargetAttributesSema.h b/lib/Sema/TargetAttributesSema.h
new file mode 100644 (file)
index 0000000..8794e40
--- /dev/null
@@ -0,0 +1,27 @@
+//===--- TargetAttributesSema.h - Semantic Analysis For Target Attributes -===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_SEMA_TARGETSEMA_H
+#define CLANG_SEMA_TARGETSEMA_H
+
+namespace clang {
+  class Scope;
+  class Decl;
+  class Attr;
+  class Sema;
+
+  class TargetAttributesSema {
+  public:
+    virtual ~TargetAttributesSema();
+    virtual bool ProcessDeclAttribute(Scope *scope, Decl *D,
+                                      const AttributeList &Attr, Sema &S) const;
+  };
+}
+
+#endif