summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/TargetAttributesSema.cpp
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2010-01-10 12:58:08 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2010-01-10 12:58:08 +0000
commit55bcea1e65ea97efb782314605f01e3bca9706d0 (patch)
treebe67c9ed2f95facf346be289e231b9b2dba78c52 /clang/lib/Sema/TargetAttributesSema.cpp
parent89b14a4309ec7c59a0dbb748aef088a661edbfe4 (diff)
downloadbcm5719-llvm-55bcea1e65ea97efb782314605f01e3bca9706d0.tar.gz
bcm5719-llvm-55bcea1e65ea97efb782314605f01e3bca9706d0.zip
Generalize target weirdness handling having proper layering in mind:
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. llvm-svn: 93118
Diffstat (limited to 'clang/lib/Sema/TargetAttributesSema.cpp')
-rw-r--r--clang/lib/Sema/TargetAttributesSema.cpp86
1 files changed, 86 insertions, 0 deletions
diff --git a/clang/lib/Sema/TargetAttributesSema.cpp b/clang/lib/Sema/TargetAttributesSema.cpp
new file mode 100644
index 00000000000..7c19bf6e4fd
--- /dev/null
+++ b/clang/lib/Sema/TargetAttributesSema.cpp
@@ -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);
+ }
+}
+
OpenPOWER on IntegriCloud