xref: /freebsd/contrib/llvm-project/clang/lib/Sema/SemaMSP430.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===------ SemaMSP430.cpp ----- MSP430 target-specific routines ----------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric //  This file implements semantic analysis functions specific to NVPTX.
10*0fca6ea1SDimitry Andric //
11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
12*0fca6ea1SDimitry Andric 
13*0fca6ea1SDimitry Andric #include "clang/Sema/SemaMSP430.h"
14*0fca6ea1SDimitry Andric #include "clang/AST/ASTContext.h"
15*0fca6ea1SDimitry Andric #include "clang/AST/Attr.h"
16*0fca6ea1SDimitry Andric #include "clang/AST/DeclBase.h"
17*0fca6ea1SDimitry Andric #include "clang/Basic/DiagnosticSema.h"
18*0fca6ea1SDimitry Andric #include "clang/Sema/Attr.h"
19*0fca6ea1SDimitry Andric #include "clang/Sema/ParsedAttr.h"
20*0fca6ea1SDimitry Andric 
21*0fca6ea1SDimitry Andric namespace clang {
22*0fca6ea1SDimitry Andric 
SemaMSP430(Sema & S)23*0fca6ea1SDimitry Andric SemaMSP430::SemaMSP430(Sema &S) : SemaBase(S) {}
24*0fca6ea1SDimitry Andric 
handleInterruptAttr(Decl * D,const ParsedAttr & AL)25*0fca6ea1SDimitry Andric void SemaMSP430::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
26*0fca6ea1SDimitry Andric   // MSP430 'interrupt' attribute is applied to
27*0fca6ea1SDimitry Andric   // a function with no parameters and void return type.
28*0fca6ea1SDimitry Andric   if (!isFuncOrMethodForAttrSubject(D)) {
29*0fca6ea1SDimitry Andric     Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
30*0fca6ea1SDimitry Andric         << AL << AL.isRegularKeywordAttribute() << ExpectedFunctionOrMethod;
31*0fca6ea1SDimitry Andric     return;
32*0fca6ea1SDimitry Andric   }
33*0fca6ea1SDimitry Andric 
34*0fca6ea1SDimitry Andric   if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
35*0fca6ea1SDimitry Andric     Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
36*0fca6ea1SDimitry Andric         << /*MSP430*/ 1 << 0;
37*0fca6ea1SDimitry Andric     return;
38*0fca6ea1SDimitry Andric   }
39*0fca6ea1SDimitry Andric 
40*0fca6ea1SDimitry Andric   if (!getFunctionOrMethodResultType(D)->isVoidType()) {
41*0fca6ea1SDimitry Andric     Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
42*0fca6ea1SDimitry Andric         << /*MSP430*/ 1 << 1;
43*0fca6ea1SDimitry Andric     return;
44*0fca6ea1SDimitry Andric   }
45*0fca6ea1SDimitry Andric 
46*0fca6ea1SDimitry Andric   // The attribute takes one integer argument.
47*0fca6ea1SDimitry Andric   if (!AL.checkExactlyNumArgs(SemaRef, 1))
48*0fca6ea1SDimitry Andric     return;
49*0fca6ea1SDimitry Andric 
50*0fca6ea1SDimitry Andric   if (!AL.isArgExpr(0)) {
51*0fca6ea1SDimitry Andric     Diag(AL.getLoc(), diag::err_attribute_argument_type)
52*0fca6ea1SDimitry Andric         << AL << AANT_ArgumentIntegerConstant;
53*0fca6ea1SDimitry Andric     return;
54*0fca6ea1SDimitry Andric   }
55*0fca6ea1SDimitry Andric 
56*0fca6ea1SDimitry Andric   Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
57*0fca6ea1SDimitry Andric   std::optional<llvm::APSInt> NumParams = llvm::APSInt(32);
58*0fca6ea1SDimitry Andric   if (!(NumParams = NumParamsExpr->getIntegerConstantExpr(getASTContext()))) {
59*0fca6ea1SDimitry Andric     Diag(AL.getLoc(), diag::err_attribute_argument_type)
60*0fca6ea1SDimitry Andric         << AL << AANT_ArgumentIntegerConstant
61*0fca6ea1SDimitry Andric         << NumParamsExpr->getSourceRange();
62*0fca6ea1SDimitry Andric     return;
63*0fca6ea1SDimitry Andric   }
64*0fca6ea1SDimitry Andric   // The argument should be in range 0..63.
65*0fca6ea1SDimitry Andric   unsigned Num = NumParams->getLimitedValue(255);
66*0fca6ea1SDimitry Andric   if (Num > 63) {
67*0fca6ea1SDimitry Andric     Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
68*0fca6ea1SDimitry Andric         << AL << (int)NumParams->getSExtValue()
69*0fca6ea1SDimitry Andric         << NumParamsExpr->getSourceRange();
70*0fca6ea1SDimitry Andric     return;
71*0fca6ea1SDimitry Andric   }
72*0fca6ea1SDimitry Andric 
73*0fca6ea1SDimitry Andric   D->addAttr(::new (getASTContext())
74*0fca6ea1SDimitry Andric                  MSP430InterruptAttr(getASTContext(), AL, Num));
75*0fca6ea1SDimitry Andric   D->addAttr(UsedAttr::CreateImplicit(getASTContext()));
76*0fca6ea1SDimitry Andric }
77*0fca6ea1SDimitry Andric 
78*0fca6ea1SDimitry Andric } // namespace clang
79