diff options
author | Anton Korobeynikov <asl@math.spbu.ru> | 2010-01-10 12:58:08 +0000 |
---|---|---|
committer | Anton Korobeynikov <asl@math.spbu.ru> | 2010-01-10 12:58:08 +0000 |
commit | 82d0a418c8699fc6f4a9417457ffe93d43bba1c1 (patch) | |
tree | e0ee69587ef2122adc4528807f5899519b8f40e3 /lib/Sema/TargetAttributesSema.cpp | |
parent | 82bac50fc0ab125ff5b4308ee91a731e3761eb63 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93118 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/TargetAttributesSema.cpp')
-rw-r--r-- | lib/Sema/TargetAttributesSema.cpp | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp new file mode 100644 index 0000000000..7c19bf6e4f --- /dev/null +++ b/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); + } +} + |