TargetAttributesSema.cpp revision 5a0164d6ab843ca61437ec59a504365cb1c98f43
182d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===//
282d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov//
382d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov//                     The LLVM Compiler Infrastructure
482d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov//
582d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov// This file is distributed under the University of Illinois Open Source
682d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov// License. See LICENSE.TXT for details.
782d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov//
882d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov//===----------------------------------------------------------------------===//
982d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov//
1082d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov// This file contains semantic analysis implementation for target-specific
1182d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov// attributes.
1282d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov//
1382d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov//===----------------------------------------------------------------------===//
1482d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
1582d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov#include "Sema.h"
1682d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov#include "TargetAttributesSema.h"
1782d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov#include "clang/Basic/TargetInfo.h"
1882d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov#include "llvm/ADT/Triple.h"
1982d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
2082d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikovusing namespace clang;
2182d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
2282d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton KorobeynikovTargetAttributesSema::~TargetAttributesSema() {}
2382d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikovbool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
2482d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov                                    const AttributeList &Attr, Sema &S) const {
2582d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov  return false;
2682d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov}
2782d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
2882d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikovstatic void HandleMSP430InterruptAttr(Decl *d,
2982d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov                                      const AttributeList &Attr, Sema &S) {
3082d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    // Check the attribute arguments.
3182d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    if (Attr.getNumArgs() != 1) {
3282d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
3382d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov      return;
3482d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    }
3582d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
3682d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    // FIXME: Check for decl - it should be void ()(void).
3782d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
3882d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
3982d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    llvm::APSInt NumParams(32);
4082d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
4182d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
4282d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov        << "interrupt" << NumParamsExpr->getSourceRange();
4382d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov      return;
4482d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    }
4582d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
4682d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    unsigned Num = NumParams.getLimitedValue(255);
4782d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    if ((Num & 1) || Num > 30) {
4882d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov      S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
4982d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov        << "interrupt" << (int)NumParams.getSExtValue()
5082d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov        << NumParamsExpr->getSourceRange();
5182d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov      return;
5282d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    }
5382d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
5482d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    d->addAttr(::new (S.Context) MSP430InterruptAttr(Num));
5582d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    d->addAttr(::new (S.Context) UsedAttr());
5682d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov  }
5782d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
5882d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikovnamespace {
5982d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov  class MSP430AttributesSema : public TargetAttributesSema {
6082d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov  public:
6182d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    MSP430AttributesSema() { }
6282d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    bool ProcessDeclAttribute(Scope *scope, Decl *D,
6382d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov                              const AttributeList &Attr, Sema &S) const {
6482d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov      if (Attr.getName()->getName() == "interrupt") {
6582d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov        HandleMSP430InterruptAttr(D, Attr, S);
6682d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov        return true;
6782d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov      }
6882d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov      return false;
6982d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    }
7082d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov  };
7182d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov}
7282d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
735a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davisstatic void HandleX86ForceAlignArgPointerAttr(Decl *D,
745a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis                                              const AttributeList& Attr,
755a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis                                              Sema &S) {
765a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  // Check the attribute arguments.
775a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  if (Attr.getNumArgs() != 0) {
785a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
795a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis    return;
805a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  }
815a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis
825a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  // If we try to apply it to a function pointer, don't warn, but don't
835a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  // do anything, either. It doesn't matter anyway, because there's nothing
845a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  // special about calling a force_align_arg_pointer function.
855a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  ValueDecl* VD = dyn_cast<ValueDecl>(D);
865a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  if(VD->getType()->isFunctionPointerType())
875a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis    return;
885a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  // Attribute can only be applied to function types.
895a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  if(!isa<FunctionDecl>(D)) {
905a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
915a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis      << Attr.getName() << /* function */0;
925a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis    return;
935a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  }
945a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis
955a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr());
965a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis}
975a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis
985a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davisnamespace {
995a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  class X86AttributesSema : public TargetAttributesSema {
1005a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  public:
1015a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis    X86AttributesSema() { }
1025a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis    bool ProcessDeclAttribute(Scope *scope, Decl *D,
1035a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis                              const AttributeList &Attr, Sema &S) const {
1045a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis      if (Attr.getName()->getName() == "force_align_arg_pointer") {
1055a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis        HandleX86ForceAlignArgPointerAttr(D, Attr, S);
1065a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis        return true;
1075a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis      }
1085a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis      return false;
1095a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis    }
1105a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  };
1115a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis}
1125a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis
11382d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikovconst TargetAttributesSema &Sema::getTargetAttributesSema() const {
11482d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov  if (TheTargetAttributesSema)
11582d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    return *TheTargetAttributesSema;
11682d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
11782d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov  const llvm::Triple &Triple(Context.Target.getTriple());
11882d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov  switch (Triple.getArch()) {
11982d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov  default:
12082d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    return *(TheTargetAttributesSema = new TargetAttributesSema);
12182d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
12282d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov  case llvm::Triple::msp430:
12382d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov    return *(TheTargetAttributesSema = new MSP430AttributesSema);
1245a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis  case llvm::Triple::x86:
1255a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis    return *(TheTargetAttributesSema = new X86AttributesSema);
12682d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov  }
12782d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov}
12882d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
129