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