| //===-- 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); |
| } |
| } |
| |