1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/*
2c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Copyright 2010, The Android Open Source Project
3c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
4c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
5c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * you may not use this file except in compliance with the License.
6c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * You may obtain a copy of the License at
7c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
8c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
9c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
10c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Unless required by applicable law or agreed to in writing, software
11c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
12c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * See the License for the specific language governing permissions and
14c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * limitations under the License.
15c383a500aa59423264811be3874461bf8adbfea0Zonr Chang */
16c383a500aa59423264811be3874461bf8adbfea0Zonr Chang
176315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_pragma_handler.h"
18462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
195e306b944425a952fe744f59d828538137a59375David Gross#include <map>
203fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines#include <sstream>
21e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <string>
22e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
2365f23ed862e1a1e16477ba740f295ff4a83ac822David Gross#include "clang/AST/ASTContext.h"
2465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
259ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Basic/TokenKinds.h"
26462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
279ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Lex/LiteralSupport.h"
289ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Lex/Preprocessor.h"
299ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#include "clang/Lex/Token.h"
30462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
316e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
326315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include "slang_rs_context.h"
3315e44e66adc350adb4fe0533a442092c64333ab5David Gross#include "slang_rs_export_reduce.h"
3415e44e66adc350adb4fe0533a442092c64333ab5David Gross#include "slang_version.h"
356315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr
36e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
37462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
389ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaonamespace {  // Anonymous namespace
39462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
40462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liaoclass RSExportTypePragmaHandler : public RSPragmaHandler {
419ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao private:
426315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr  void handleItem(const std::string &Item) {
433fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    mContext->addPragma(this->getName(), Item);
449ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mContext->addExportType(Item);
459ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
469ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
479ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao public:
486315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr  RSExportTypePragmaHandler(llvm::StringRef Name, RSContext *Context)
49796e7b1400d3f3f7c07496d88bb48129ea925bb9Jean-Luc Brouillet      : RSPragmaHandler(Name, Context) { }
509ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
51df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao  void HandlePragma(clang::Preprocessor &PP,
52df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::PragmaIntroducerKind Introducer,
53df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::Token &FirstToken) {
549ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    this->handleItemListPragma(PP, FirstToken);
559ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
56462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao};
57462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
58537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liaoclass RSJavaPackageNamePragmaHandler : public RSPragmaHandler {
599ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao public:
606315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr  RSJavaPackageNamePragmaHandler(llvm::StringRef Name, RSContext *Context)
61796e7b1400d3f3f7c07496d88bb48129ea925bb9Jean-Luc Brouillet      : RSPragmaHandler(Name, Context) { }
629ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
63df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao  void HandlePragma(clang::Preprocessor &PP,
64df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::PragmaIntroducerKind Introducer,
65df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::Token &FirstToken) {
6635f5b39f0490953f1fe13ef803b43e3ced9a01d9Stephen Hines    // FIXME: Need to validate the extracted package name from pragma.
679ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Currently "all chars" specified in pragma will be treated as package
689ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // name.
699ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
709ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // 18.1 The Grammar of the Java Programming Language
719ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // (http://java.sun.com/docs/books/jls/third_edition/html/syntax.html#18.1)
729ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
739ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // CompilationUnit:
749ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //     [[Annotations] package QualifiedIdentifier   ;  ] {ImportDeclaration}
759ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //     {TypeDeclaration}
769ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
779ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // QualifiedIdentifier:
789ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //     Identifier { . Identifier }
799ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
809ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Identifier:
819ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //     IDENTIFIER
829ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // 3.8 Identifiers
849ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // (http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.8)
859ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    //
879ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    clang::Token &PragmaToken = FirstToken;
899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    std::string PackageName;
909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
919ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Skip first token, "java_package_name"
929ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    PP.LexUnexpandedToken(PragmaToken);
93537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Now, the current token must be clang::tok::lpara
959ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (PragmaToken.isNot(clang::tok::l_paren))
969ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      return;
979ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
98be27482cdeaf08576bc39b72a15d35d13014a636Logan    while (PragmaToken.isNot(clang::tok::eod)) {
999ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      // Lex package name
1009ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      PP.LexUnexpandedToken(PragmaToken);
1019ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1029ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      bool Invalid;
1039ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      std::string Spelling = PP.getSpelling(PragmaToken, &Invalid);
1049ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      if (!Invalid)
1059ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        PackageName.append(Spelling);
1069ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1079ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      // Pre-mature end (syntax error will be triggered by preprocessor later)
108be27482cdeaf08576bc39b72a15d35d13014a636Logan      if (PragmaToken.is(clang::tok::eod) || PragmaToken.is(clang::tok::eof)) {
1099ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
1106315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      } else {
11196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines        // Next token is ')' (end of pragma)
1129ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        const clang::Token &NextTok = PP.LookAhead(0);
1139ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        if (NextTok.is(clang::tok::r_paren)) {
1143fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines          mContext->addPragma(this->getName(), PackageName);
1159ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          mContext->setReflectJavaPackageName(PackageName);
116be27482cdeaf08576bc39b72a15d35d13014a636Logan          // Lex until meets clang::tok::eod
1179ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          do {
1189ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            PP.LexUnexpandedToken(PragmaToken);
119be27482cdeaf08576bc39b72a15d35d13014a636Logan          } while (PragmaToken.isNot(clang::tok::eod));
1209ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao          break;
121537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao        }
1229ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      }
123537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao    }
1249ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
125537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao};
126537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
12715e44e66adc350adb4fe0533a442092c64333ab5David Grossclass RSReducePragmaHandler : public RSPragmaHandler {
12815e44e66adc350adb4fe0533a442092c64333ab5David Gross public:
12915e44e66adc350adb4fe0533a442092c64333ab5David Gross  RSReducePragmaHandler(llvm::StringRef Name, RSContext *Context)
13015e44e66adc350adb4fe0533a442092c64333ab5David Gross      : RSPragmaHandler(Name, Context) { }
13115e44e66adc350adb4fe0533a442092c64333ab5David Gross
13215e44e66adc350adb4fe0533a442092c64333ab5David Gross  void HandlePragma(clang::Preprocessor &PP,
13315e44e66adc350adb4fe0533a442092c64333ab5David Gross                    clang::PragmaIntroducerKind Introducer,
13415e44e66adc350adb4fe0533a442092c64333ab5David Gross                    clang::Token &FirstToken) override {
13515e44e66adc350adb4fe0533a442092c64333ab5David Gross    // #pragma rs reduce(name)
13615e44e66adc350adb4fe0533a442092c64333ab5David Gross    //   initializer(initializename)
13715e44e66adc350adb4fe0533a442092c64333ab5David Gross    //   accumulator(accumulatename)
13815e44e66adc350adb4fe0533a442092c64333ab5David Gross    //   combiner(combinename)
13915e44e66adc350adb4fe0533a442092c64333ab5David Gross    //   outconverter(outconvertname)
14015e44e66adc350adb4fe0533a442092c64333ab5David Gross    //   halter(haltname)
14115e44e66adc350adb4fe0533a442092c64333ab5David Gross
14215e44e66adc350adb4fe0533a442092c64333ab5David Gross    const clang::SourceLocation PragmaLocation = FirstToken.getLocation();
14315e44e66adc350adb4fe0533a442092c64333ab5David Gross
14415e44e66adc350adb4fe0533a442092c64333ab5David Gross    clang::Token &PragmaToken = FirstToken;
14515e44e66adc350adb4fe0533a442092c64333ab5David Gross
14615e44e66adc350adb4fe0533a442092c64333ab5David Gross    // Grab "reduce(name)" ("reduce" is already known to be the first
14715e44e66adc350adb4fe0533a442092c64333ab5David Gross    // token) and all the "keyword(value)" contributions
1488ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    KeywordValueMapType KeywordValueMap({std::make_pair(RSExportReduce::KeyReduce, ""),
1498ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross                                         std::make_pair(RSExportReduce::KeyInitializer, ""),
1508ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross                                         std::make_pair(RSExportReduce::KeyAccumulator, ""),
1518ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross                                         std::make_pair(RSExportReduce::KeyCombiner, ""),
1528ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross                                         std::make_pair(RSExportReduce::KeyOutConverter, "")});
15346a0334d8901576e20db68e15930a19f8f789cb8David Gross    if (mContext->getTargetAPI() >= SLANG_FEATURE_GENERAL_REDUCTION_HALTER_API) {
15446a0334d8901576e20db68e15930a19f8f789cb8David Gross      // Halter functionality has not been released, nor has its
15546a0334d8901576e20db68e15930a19f8f789cb8David Gross      // specification been finalized with partners.  We do not have a
15646a0334d8901576e20db68e15930a19f8f789cb8David Gross      // specification that extends through the full RenderScript
15746a0334d8901576e20db68e15930a19f8f789cb8David Gross      // software stack, either.
1588ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross      KeywordValueMap.insert(std::make_pair(RSExportReduce::KeyHalter, ""));
15946a0334d8901576e20db68e15930a19f8f789cb8David Gross    }
16015e44e66adc350adb4fe0533a442092c64333ab5David Gross    while (PragmaToken.is(clang::tok::identifier)) {
16115e44e66adc350adb4fe0533a442092c64333ab5David Gross      if (!ProcessKeywordAndValue(PP, PragmaToken, KeywordValueMap))
16215e44e66adc350adb4fe0533a442092c64333ab5David Gross        return;
16315e44e66adc350adb4fe0533a442092c64333ab5David Gross    }
16415e44e66adc350adb4fe0533a442092c64333ab5David Gross
16515e44e66adc350adb4fe0533a442092c64333ab5David Gross    // Make sure there's no end-of-line garbage
16615e44e66adc350adb4fe0533a442092c64333ab5David Gross    if (PragmaToken.isNot(clang::tok::eod)) {
16715e44e66adc350adb4fe0533a442092c64333ab5David Gross      PP.Diag(PragmaToken.getLocation(),
16815e44e66adc350adb4fe0533a442092c64333ab5David Gross              PP.getDiagnostics().getCustomDiagID(
16915e44e66adc350adb4fe0533a442092c64333ab5David Gross                clang::DiagnosticsEngine::Error,
17015e44e66adc350adb4fe0533a442092c64333ab5David Gross                "did not expect '%0' here for '#pragma rs %1'"))
17115e44e66adc350adb4fe0533a442092c64333ab5David Gross          << PP.getSpelling(PragmaToken) << getName();
17215e44e66adc350adb4fe0533a442092c64333ab5David Gross      return;
17315e44e66adc350adb4fe0533a442092c64333ab5David Gross    }
17415e44e66adc350adb4fe0533a442092c64333ab5David Gross
17565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    // Make sure we have an accumulator
1768ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    if (KeywordValueMap[RSExportReduce::KeyAccumulator].empty()) {
17715e44e66adc350adb4fe0533a442092c64333ab5David Gross      PP.Diag(PragmaLocation, PP.getDiagnostics().getCustomDiagID(
17815e44e66adc350adb4fe0533a442092c64333ab5David Gross                                clang::DiagnosticsEngine::Error,
17915e44e66adc350adb4fe0533a442092c64333ab5David Gross                                "missing '%0' for '#pragma rs %1'"))
1808ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross          << RSExportReduce::KeyAccumulator << getName();
18115e44e66adc350adb4fe0533a442092c64333ab5David Gross      return;
18215e44e66adc350adb4fe0533a442092c64333ab5David Gross    }
18315e44e66adc350adb4fe0533a442092c64333ab5David Gross
18415e44e66adc350adb4fe0533a442092c64333ab5David Gross    // Make sure the reduction kernel name is unique.  (If we were
18515e44e66adc350adb4fe0533a442092c64333ab5David Gross    // worried there might be a VERY large number of pragmas, then we
18615e44e66adc350adb4fe0533a442092c64333ab5David Gross    // could do something more efficient than walking a list to search
18715e44e66adc350adb4fe0533a442092c64333ab5David Gross    // for duplicates.)
1888ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    for (auto I = mContext->export_reduce_begin(),
1898ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross              E = mContext->export_reduce_end();
19015e44e66adc350adb4fe0533a442092c64333ab5David Gross         I != E; ++I) {
1918ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross      if ((*I)->getNameReduce() == KeywordValueMap[RSExportReduce::KeyReduce]) {
19215e44e66adc350adb4fe0533a442092c64333ab5David Gross        PP.Diag(PragmaLocation, PP.getDiagnostics().getCustomDiagID(
19315e44e66adc350adb4fe0533a442092c64333ab5David Gross                                  clang::DiagnosticsEngine::Error,
19415e44e66adc350adb4fe0533a442092c64333ab5David Gross                                  "reduction kernel '%0' declared multiple "
19515e44e66adc350adb4fe0533a442092c64333ab5David Gross                                  "times (first one is at %1)"))
1968ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross            << KeywordValueMap[RSExportReduce::KeyReduce]
19715e44e66adc350adb4fe0533a442092c64333ab5David Gross            << (*I)->getLocation().printToString(PP.getSourceManager());
19815e44e66adc350adb4fe0533a442092c64333ab5David Gross        return;
19915e44e66adc350adb4fe0533a442092c64333ab5David Gross      }
20015e44e66adc350adb4fe0533a442092c64333ab5David Gross    }
20115e44e66adc350adb4fe0533a442092c64333ab5David Gross
20215e44e66adc350adb4fe0533a442092c64333ab5David Gross    // Check API version.
2031623659165bb24d733a40124e929cfd42aa917e3David Gross    if (mContext->getTargetAPI() < SLANG_FEATURE_GENERAL_REDUCTION_API) {
20415e44e66adc350adb4fe0533a442092c64333ab5David Gross      PP.Diag(PragmaLocation,
20515e44e66adc350adb4fe0533a442092c64333ab5David Gross              PP.getDiagnostics().getCustomDiagID(
20615e44e66adc350adb4fe0533a442092c64333ab5David Gross                clang::DiagnosticsEngine::Error,
2071623659165bb24d733a40124e929cfd42aa917e3David Gross                "reduction kernels are not supported in SDK levels %0-%1"))
2081623659165bb24d733a40124e929cfd42aa917e3David Gross          << SLANG_MINIMUM_TARGET_API
2091623659165bb24d733a40124e929cfd42aa917e3David Gross          << (SLANG_FEATURE_GENERAL_REDUCTION_API - 1);
21015e44e66adc350adb4fe0533a442092c64333ab5David Gross      return;
21115e44e66adc350adb4fe0533a442092c64333ab5David Gross    }
21215e44e66adc350adb4fe0533a442092c64333ab5David Gross
21365f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    // Handle backward reference from pragma (see Backend::HandleTopLevelDecl for forward reference).
2148ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    MarkUsed(PP, KeywordValueMap[RSExportReduce::KeyInitializer]);
2158ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    MarkUsed(PP, KeywordValueMap[RSExportReduce::KeyAccumulator]);
2168ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    MarkUsed(PP, KeywordValueMap[RSExportReduce::KeyCombiner]);
2178ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    MarkUsed(PP, KeywordValueMap[RSExportReduce::KeyOutConverter]);
2188ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    MarkUsed(PP, KeywordValueMap[RSExportReduce::KeyHalter]);
2198ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross
2208ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    mContext->addExportReduce(RSExportReduce::Create(mContext, PragmaLocation,
2218ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross                                                     KeywordValueMap[RSExportReduce::KeyReduce],
2228ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross                                                     KeywordValueMap[RSExportReduce::KeyInitializer],
2238ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross                                                     KeywordValueMap[RSExportReduce::KeyAccumulator],
2248ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross                                                     KeywordValueMap[RSExportReduce::KeyCombiner],
2258ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross                                                     KeywordValueMap[RSExportReduce::KeyOutConverter],
2268ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross                                                     KeywordValueMap[RSExportReduce::KeyHalter]));
22715e44e66adc350adb4fe0533a442092c64333ab5David Gross  }
22815e44e66adc350adb4fe0533a442092c64333ab5David Gross
22915e44e66adc350adb4fe0533a442092c64333ab5David Gross private:
23015e44e66adc350adb4fe0533a442092c64333ab5David Gross  typedef std::map<std::string, std::string> KeywordValueMapType;
23115e44e66adc350adb4fe0533a442092c64333ab5David Gross
23265f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  void MarkUsed(clang::Preprocessor &PP, const std::string &FunctionName) {
23365f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    if (FunctionName.empty())
23465f23ed862e1a1e16477ba740f295ff4a83ac822David Gross      return;
23565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
23665f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    clang::ASTContext &ASTC = mContext->getASTContext();
23765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    clang::TranslationUnitDecl *TUDecl = ASTC.getTranslationUnitDecl();
23865f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    slangAssert(TUDecl);
23965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    if (const clang::IdentifierInfo *II = PP.getIdentifierInfo(FunctionName)) {
24065f23ed862e1a1e16477ba740f295ff4a83ac822David Gross      for (auto Decl : TUDecl->lookup(II)) {
24165f23ed862e1a1e16477ba740f295ff4a83ac822David Gross        clang::FunctionDecl *FDecl = Decl->getAsFunction();
24265f23ed862e1a1e16477ba740f295ff4a83ac822David Gross        if (!FDecl || !FDecl->isThisDeclarationADefinition())
24365f23ed862e1a1e16477ba740f295ff4a83ac822David Gross          continue;
2445e306b944425a952fe744f59d828538137a59375David Gross        // Handle backward reference from pragma (see
2455e306b944425a952fe744f59d828538137a59375David Gross        // Backend::HandleTopLevelDecl for forward reference).
2465e306b944425a952fe744f59d828538137a59375David Gross        mContext->markUsedByReducePragma(FDecl, RSContext::CheckNameNo);
24765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross      }
24865f23ed862e1a1e16477ba740f295ff4a83ac822David Gross    }
24965f23ed862e1a1e16477ba740f295ff4a83ac822David Gross  }
25065f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
25115e44e66adc350adb4fe0533a442092c64333ab5David Gross  // Return comma-separated list of all keys in the map
25215e44e66adc350adb4fe0533a442092c64333ab5David Gross  static std::string ListKeywords(const KeywordValueMapType &KeywordValueMap) {
25315e44e66adc350adb4fe0533a442092c64333ab5David Gross    std::string Ret;
25415e44e66adc350adb4fe0533a442092c64333ab5David Gross    bool First = true;
25515e44e66adc350adb4fe0533a442092c64333ab5David Gross    for (auto const &entry : KeywordValueMap) {
25615e44e66adc350adb4fe0533a442092c64333ab5David Gross      if (First)
25715e44e66adc350adb4fe0533a442092c64333ab5David Gross        First = false;
25815e44e66adc350adb4fe0533a442092c64333ab5David Gross      else
25915e44e66adc350adb4fe0533a442092c64333ab5David Gross        Ret += ", ";
26015e44e66adc350adb4fe0533a442092c64333ab5David Gross      Ret += "'";
26115e44e66adc350adb4fe0533a442092c64333ab5David Gross      Ret += entry.first;
26215e44e66adc350adb4fe0533a442092c64333ab5David Gross      Ret += "'";
26315e44e66adc350adb4fe0533a442092c64333ab5David Gross    }
26415e44e66adc350adb4fe0533a442092c64333ab5David Gross    return Ret;
26515e44e66adc350adb4fe0533a442092c64333ab5David Gross  }
26615e44e66adc350adb4fe0533a442092c64333ab5David Gross
26715e44e66adc350adb4fe0533a442092c64333ab5David Gross  // Parse "keyword(value)" and set KeywordValueMap[keyword] = value.  (Both
26815e44e66adc350adb4fe0533a442092c64333ab5David Gross  // "keyword" and "value" are identifiers.)
26915e44e66adc350adb4fe0533a442092c64333ab5David Gross  // Does both syntactic validation and the following semantic validation:
27015e44e66adc350adb4fe0533a442092c64333ab5David Gross  // - The keyword must be present in the map.
27115e44e66adc350adb4fe0533a442092c64333ab5David Gross  // - The map entry for the keyword must not contain a value.
27215e44e66adc350adb4fe0533a442092c64333ab5David Gross  bool ProcessKeywordAndValue(clang::Preprocessor &PP,
27315e44e66adc350adb4fe0533a442092c64333ab5David Gross                              clang::Token &PragmaToken,
27415e44e66adc350adb4fe0533a442092c64333ab5David Gross                              KeywordValueMapType &KeywordValueMap) {
27515e44e66adc350adb4fe0533a442092c64333ab5David Gross    // The current token must be an identifier in KeywordValueMap
27615e44e66adc350adb4fe0533a442092c64333ab5David Gross    KeywordValueMapType::iterator Entry;
27715e44e66adc350adb4fe0533a442092c64333ab5David Gross    if (PragmaToken.isNot(clang::tok::identifier) ||
27815e44e66adc350adb4fe0533a442092c64333ab5David Gross        ((Entry = KeywordValueMap.find(
27915e44e66adc350adb4fe0533a442092c64333ab5David Gross            PragmaToken.getIdentifierInfo()->getName())) ==
28015e44e66adc350adb4fe0533a442092c64333ab5David Gross         KeywordValueMap.end())) {
28115e44e66adc350adb4fe0533a442092c64333ab5David Gross      // Note that we should never get here for the "reduce" token
28215e44e66adc350adb4fe0533a442092c64333ab5David Gross      // itself, which should already have been recognized.
28315e44e66adc350adb4fe0533a442092c64333ab5David Gross      PP.Diag(PragmaToken.getLocation(),
28415e44e66adc350adb4fe0533a442092c64333ab5David Gross              PP.getDiagnostics().getCustomDiagID(
28515e44e66adc350adb4fe0533a442092c64333ab5David Gross                clang::DiagnosticsEngine::Error,
28615e44e66adc350adb4fe0533a442092c64333ab5David Gross                "did not recognize '%0' for '#pragma %1'; expected one of "
28715e44e66adc350adb4fe0533a442092c64333ab5David Gross                "the following keywords: %2"))
28815e44e66adc350adb4fe0533a442092c64333ab5David Gross          << PragmaToken.getIdentifierInfo()->getName() << getName()
28915e44e66adc350adb4fe0533a442092c64333ab5David Gross          << ListKeywords(KeywordValueMap);
29015e44e66adc350adb4fe0533a442092c64333ab5David Gross      return false;
29115e44e66adc350adb4fe0533a442092c64333ab5David Gross    }
29215e44e66adc350adb4fe0533a442092c64333ab5David Gross    // ... and there must be no value for this keyword yet
29315e44e66adc350adb4fe0533a442092c64333ab5David Gross    if (!Entry->second.empty()) {
29415e44e66adc350adb4fe0533a442092c64333ab5David Gross      PP.Diag(PragmaToken.getLocation(),
29515e44e66adc350adb4fe0533a442092c64333ab5David Gross              PP.getDiagnostics().getCustomDiagID(
29615e44e66adc350adb4fe0533a442092c64333ab5David Gross                clang::DiagnosticsEngine::Error,
29715e44e66adc350adb4fe0533a442092c64333ab5David Gross                "more than one '%0' for '#pragma rs %1'"))
29815e44e66adc350adb4fe0533a442092c64333ab5David Gross          << Entry->first << getName();
29915e44e66adc350adb4fe0533a442092c64333ab5David Gross      return false;
30015e44e66adc350adb4fe0533a442092c64333ab5David Gross    }
30115e44e66adc350adb4fe0533a442092c64333ab5David Gross    PP.LexUnexpandedToken(PragmaToken);
30215e44e66adc350adb4fe0533a442092c64333ab5David Gross
30315e44e66adc350adb4fe0533a442092c64333ab5David Gross    // The current token must be clang::tok::l_paren
30415e44e66adc350adb4fe0533a442092c64333ab5David Gross    if (PragmaToken.isNot(clang::tok::l_paren)) {
30515e44e66adc350adb4fe0533a442092c64333ab5David Gross      PP.Diag(PragmaToken.getLocation(),
30615e44e66adc350adb4fe0533a442092c64333ab5David Gross              PP.getDiagnostics().getCustomDiagID(
30715e44e66adc350adb4fe0533a442092c64333ab5David Gross                clang::DiagnosticsEngine::Error,
30815e44e66adc350adb4fe0533a442092c64333ab5David Gross                "missing '(' after '%0' for '#pragma rs %1'"))
30915e44e66adc350adb4fe0533a442092c64333ab5David Gross          << Entry->first << getName();
31015e44e66adc350adb4fe0533a442092c64333ab5David Gross      return false;
31115e44e66adc350adb4fe0533a442092c64333ab5David Gross    }
31215e44e66adc350adb4fe0533a442092c64333ab5David Gross    PP.LexUnexpandedToken(PragmaToken);
31315e44e66adc350adb4fe0533a442092c64333ab5David Gross
31415e44e66adc350adb4fe0533a442092c64333ab5David Gross    // The current token must be an identifier (a name)
31515e44e66adc350adb4fe0533a442092c64333ab5David Gross    if (PragmaToken.isNot(clang::tok::identifier)) {
31615e44e66adc350adb4fe0533a442092c64333ab5David Gross      PP.Diag(PragmaToken.getLocation(),
31715e44e66adc350adb4fe0533a442092c64333ab5David Gross              PP.getDiagnostics().getCustomDiagID(
31815e44e66adc350adb4fe0533a442092c64333ab5David Gross                clang::DiagnosticsEngine::Error,
31915e44e66adc350adb4fe0533a442092c64333ab5David Gross                "missing name after '%0(' for '#pragma rs %1'"))
32015e44e66adc350adb4fe0533a442092c64333ab5David Gross          << Entry->first << getName();
32115e44e66adc350adb4fe0533a442092c64333ab5David Gross      return false;
32215e44e66adc350adb4fe0533a442092c64333ab5David Gross    }
32315e44e66adc350adb4fe0533a442092c64333ab5David Gross    const std::string Name = PragmaToken.getIdentifierInfo()->getName();
32415e44e66adc350adb4fe0533a442092c64333ab5David Gross    PP.LexUnexpandedToken(PragmaToken);
32515e44e66adc350adb4fe0533a442092c64333ab5David Gross
32615e44e66adc350adb4fe0533a442092c64333ab5David Gross    // The current token must be clang::tok::r_paren
32715e44e66adc350adb4fe0533a442092c64333ab5David Gross    if (PragmaToken.isNot(clang::tok::r_paren)) {
32815e44e66adc350adb4fe0533a442092c64333ab5David Gross      PP.Diag(PragmaToken.getLocation(),
32915e44e66adc350adb4fe0533a442092c64333ab5David Gross              PP.getDiagnostics().getCustomDiagID(
33015e44e66adc350adb4fe0533a442092c64333ab5David Gross                clang::DiagnosticsEngine::Error,
33115e44e66adc350adb4fe0533a442092c64333ab5David Gross                "missing ')' after '%0(%1' for '#pragma rs %2'"))
33215e44e66adc350adb4fe0533a442092c64333ab5David Gross          << Entry->first << Name << getName();
33315e44e66adc350adb4fe0533a442092c64333ab5David Gross      return false;
33415e44e66adc350adb4fe0533a442092c64333ab5David Gross    }
33515e44e66adc350adb4fe0533a442092c64333ab5David Gross    PP.LexUnexpandedToken(PragmaToken);
33615e44e66adc350adb4fe0533a442092c64333ab5David Gross
33715e44e66adc350adb4fe0533a442092c64333ab5David Gross    // Success
33815e44e66adc350adb4fe0533a442092c64333ab5David Gross    Entry->second = Name;
33915e44e66adc350adb4fe0533a442092c64333ab5David Gross    return true;
34015e44e66adc350adb4fe0533a442092c64333ab5David Gross  }
34115e44e66adc350adb4fe0533a442092c64333ab5David Gross};
34215e44e66adc350adb4fe0533a442092c64333ab5David Gross
343d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsiehclass RSReflectLicensePragmaHandler : public RSPragmaHandler {
3449ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao private:
3459ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  void handleItem(const std::string &Item) {
3463fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    mContext->addPragma(this->getName(), Item);
3479ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mContext->setLicenseNote(Item);
3489ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
3499ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
3509ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao public:
3519ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  RSReflectLicensePragmaHandler(llvm::StringRef Name, RSContext *Context)
352796e7b1400d3f3f7c07496d88bb48129ea925bb9Jean-Luc Brouillet      : RSPragmaHandler(Name, Context) { }
3539ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
354df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao  void HandlePragma(clang::Preprocessor &PP,
355df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::PragmaIntroducerKind Introducer,
356df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::Token &FirstToken) {
3579d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines    this->handleOptionalStringLiteralParamPragma(PP, FirstToken);
3589ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
359d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh};
360d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh
36196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hinesclass RSVersionPragmaHandler : public RSPragmaHandler {
36296ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines private:
3637aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines  void handleInt(clang::Preprocessor &PP,
3647aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                 clang::Token &Tok,
3657aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                 const int v) {
3667aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    if (v != 1) {
3677aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      PP.Diag(Tok,
3687aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines              PP.getDiagnostics().getCustomDiagID(
3697aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  clang::DiagnosticsEngine::Error,
3707aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  "pragma for version in source file must be set to 1"));
3717aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      mContext->setVersion(1);
3727aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      return;
3737aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    }
3743fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    std::stringstream ss;
3753fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    ss << v;
3763fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    mContext->addPragma(this->getName(), ss.str());
37796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    mContext->setVersion(v);
37896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  }
37996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
38096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines public:
38196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  RSVersionPragmaHandler(llvm::StringRef Name, RSContext *Context)
382796e7b1400d3f3f7c07496d88bb48129ea925bb9Jean-Luc Brouillet      : RSPragmaHandler(Name, Context) { }
38396ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
384df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao  void HandlePragma(clang::Preprocessor &PP,
385df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::PragmaIntroducerKind Introducer,
386df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao                    clang::Token &FirstToken) {
38796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    this->handleIntegerParamPragma(PP, FirstToken);
38896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  }
38996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines};
39096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
391109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet// Handles the pragmas rs_fp_full, rs_fp_relaxed, and rs_fp_imprecise.
392109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet// There's one instance of this handler for each of the above values.
393109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet// Only getName() differs between the instances.
394109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouilletclass RSPrecisionPragmaHandler : public RSPragmaHandler {
395109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouilletpublic:
396109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  RSPrecisionPragmaHandler(llvm::StringRef Name, RSContext *Context)
397109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      : RSPragmaHandler(Name, Context) {}
398462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
399109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  void HandlePragma(clang::Preprocessor &PP,
400109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                    clang::PragmaIntroducerKind Introducer,
401109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                    clang::Token &Token) {
402109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    std::string Precision = getName();
403109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    // We are deprecating rs_fp_imprecise.
404109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    if (Precision == "rs_fp_imprecise") {
405109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      PP.Diag(Token, PP.getDiagnostics().getCustomDiagID(
406109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                         clang::DiagnosticsEngine::Warning,
407109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                         "rs_fp_imprecise is deprecated.  Assuming "
408109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                         "rs_fp_relaxed instead."));
409109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      Precision = "rs_fp_relaxed";
410109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    }
411109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    // Check if we have already encountered a precision pragma already.
412109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    std::string PreviousPrecision = mContext->getPrecision();
413109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    if (!PreviousPrecision.empty()) {
414109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      // If the previous specified a different value, it's an error.
415109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      if (PreviousPrecision != Precision) {
416109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet        PP.Diag(Token, PP.getDiagnostics().getCustomDiagID(
417109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                           clang::DiagnosticsEngine::Error,
418109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                           "Multiple float precisions specified.  Encountered "
419109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                           "%0 previously."))
420109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet            << PreviousPrecision;
421109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      }
422109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      // Otherwise we ignore redundant entries.
423109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      return;
424109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    }
425537446c9542fdda458920876ed8a020a97ddf7a4Shih-wei Liao
426109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    mContext->addPragma(Precision, "");
427109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet    mContext->setPrecision(Precision);
428109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  }
429109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet};
430d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh
431109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet}  // namespace
43296ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
4339ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liaovoid RSPragmaHandler::handleItemListPragma(clang::Preprocessor &PP,
4349ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao                                           clang::Token &FirstToken) {
4359ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  clang::Token &PragmaToken = FirstToken;
436462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
4379ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Skip first token, like "export_var"
4389ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  PP.LexUnexpandedToken(PragmaToken);
439462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
4409ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Now, the current token must be clang::tok::lpara
4419ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (PragmaToken.isNot(clang::tok::l_paren))
4429ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return;
443462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
444be27482cdeaf08576bc39b72a15d35d13014a636Logan  while (PragmaToken.isNot(clang::tok::eod)) {
4459ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Lex variable name
4469ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    PP.LexUnexpandedToken(PragmaToken);
4479ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (PragmaToken.is(clang::tok::identifier))
4486315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      this->handleItem(PP.getSpelling(PragmaToken));
4499ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    else
4509ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
451462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
452be27482cdeaf08576bc39b72a15d35d13014a636Logan    slangAssert(PragmaToken.isNot(clang::tok::eod));
453462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
4549ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    PP.LexUnexpandedToken(PragmaToken);
455462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
4569ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (PragmaToken.isNot(clang::tok::comma))
4579ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      break;
4589ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
459462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao}
460462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
4616315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonrvoid RSPragmaHandler::handleNonParamPragma(clang::Preprocessor &PP,
4626315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr                                           clang::Token &FirstToken) {
4636315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr  clang::Token &PragmaToken = FirstToken;
464c6718b312b793ea76ac6b61479090c33ba9f2ba6Victor Hsieh
4659ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Skip first token, like "export_var_all"
4669ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  PP.LexUnexpandedToken(PragmaToken);
467c6718b312b793ea76ac6b61479090c33ba9f2ba6Victor Hsieh
4689ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Should be end immediately
469be27482cdeaf08576bc39b72a15d35d13014a636Logan  if (PragmaToken.isNot(clang::tok::eod))
4707aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    if (PragmaToken.isNot(clang::tok::r_paren)) {
4717aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      PP.Diag(PragmaToken,
4727aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines              PP.getDiagnostics().getCustomDiagID(
4737aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  clang::DiagnosticsEngine::Error,
4747aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  "expected a ')'"));
4757aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      return;
4767aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    }
477c6718b312b793ea76ac6b61479090c33ba9f2ba6Victor Hsieh}
478c6718b312b793ea76ac6b61479090c33ba9f2ba6Victor Hsieh
4799d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hinesvoid RSPragmaHandler::handleOptionalStringLiteralParamPragma(
4809ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    clang::Preprocessor &PP, clang::Token &FirstToken) {
4819ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  clang::Token &PragmaToken = FirstToken;
482d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh
4839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Skip first token, like "set_reflect_license"
4849ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  PP.LexUnexpandedToken(PragmaToken);
485d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh
4869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // Now, the current token must be clang::tok::lpara
4879ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (PragmaToken.isNot(clang::tok::l_paren))
4889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return;
489d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh
4909ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  // If not ')', eat the following string literal as the license
4919ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  PP.LexUnexpandedToken(PragmaToken);
4929ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  if (PragmaToken.isNot(clang::tok::r_paren)) {
4939ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Eat the whole string literal
4942eb9a3f7c48fe54eb4e813d80e3363bc79553a1eStephen Hines    clang::StringLiteralParser StringLiteral(PragmaToken, PP);
4957aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    if (StringLiteral.hadError) {
4967aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      // Diagnostics will be generated automatically
4977aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      return;
498e67239de8d94975e7e2216ee6860ae2e6cb8b15aStephen Hines    } else {
4996315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr      this->handleItem(std::string(StringLiteral.GetString()));
5007aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    }
5019ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
5029ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // The current token should be clang::tok::r_para
503d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh    PP.LexUnexpandedToken(PragmaToken);
5047aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    if (PragmaToken.isNot(clang::tok::r_paren)) {
5057aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      PP.Diag(PragmaToken,
5067aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines              PP.getDiagnostics().getCustomDiagID(
5077aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  clang::DiagnosticsEngine::Error,
5087aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                  "expected a ')'"));
5097aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      return;
5107aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    }
5119ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  } else {
5129ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // If no argument, remove the license
5136315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    this->handleItem("");
5149ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao  }
515d8a0d186a362739f385f1a4af35360d5da69e47bVictor Hsieh}
516e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
51796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hinesvoid RSPragmaHandler::handleIntegerParamPragma(
51896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    clang::Preprocessor &PP, clang::Token &FirstToken) {
51996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  clang::Token &PragmaToken = FirstToken;
52096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
52196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  // Skip first token, like "version"
52296ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  PP.LexUnexpandedToken(PragmaToken);
52396ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
52496ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  // Now, the current token must be clang::tok::lpara
5257aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines  if (PragmaToken.isNot(clang::tok::l_paren)) {
5267aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    // If no argument, set the version to 0
5277aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    this->handleInt(PP, PragmaToken, 0);
52896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    return;
5297aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines  }
53096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  PP.LexUnexpandedToken(PragmaToken);
53196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
53296ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  if (PragmaToken.is(clang::tok::numeric_constant)) {
53323c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines    llvm::SmallString<128> SpellingBuffer;
53423c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines    SpellingBuffer.resize(PragmaToken.getLength() + 1);
53523c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines    llvm::StringRef TokSpelling = PP.getSpelling(PragmaToken, SpellingBuffer);
53623c4358f12bd9d0ba7166eceebd683db95a41b3fStephen Hines    clang::NumericLiteralParser NumericLiteral(TokSpelling,
53796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines        PragmaToken.getLocation(), PP);
53896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    if (NumericLiteral.hadError) {
5397aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      // Diagnostics will be generated automatically
5407aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      return;
54196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    } else {
54296ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines      llvm::APInt Val(32, 0);
54396ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines      NumericLiteral.GetIntegerValue(Val);
5447aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines      this->handleInt(PP, PragmaToken, static_cast<int>(Val.getSExtValue()));
54596ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    }
54696ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    PP.LexUnexpandedToken(PragmaToken);
54796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  } else {
54896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    // If no argument, set the version to 0
5497aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    this->handleInt(PP, PragmaToken, 0);
55096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  }
55196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
55296ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  if (PragmaToken.isNot(clang::tok::r_paren)) {
5537aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    PP.Diag(PragmaToken,
5547aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines            PP.getDiagnostics().getCustomDiagID(
5557aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                clang::DiagnosticsEngine::Error,
5567aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines                "expected a ')'"));
5577aff4a0a124209fdf93ecbcd7aed701d39ba094bStephen Hines    return;
55896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  }
55996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
56096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines  do {
56196ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    PP.LexUnexpandedToken(PragmaToken);
562be27482cdeaf08576bc39b72a15d35d13014a636Logan  } while (PragmaToken.isNot(clang::tok::eod));
56396ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines}
56496ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
565109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouilletvoid AddPragmaHandlers(clang::Preprocessor &PP, RSContext *RsContext) {
566109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  // For #pragma rs export_type
567109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler("rs",
568109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet                      new RSExportTypePragmaHandler("export_type", RsContext));
569109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
570109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  // For #pragma rs java_package_name
571109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(
572109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      "rs", new RSJavaPackageNamePragmaHandler("java_package_name", RsContext));
573109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
57415e44e66adc350adb4fe0533a442092c64333ab5David Gross  // For #pragma rs reduce
57515e44e66adc350adb4fe0533a442092c64333ab5David Gross  PP.AddPragmaHandler(
5768ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross      "rs", new RSReducePragmaHandler(RSExportReduce::KeyReduce, RsContext));
57715e44e66adc350adb4fe0533a442092c64333ab5David Gross
578109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  // For #pragma rs set_reflect_license
579109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(
580109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet      "rs", new RSReflectLicensePragmaHandler("set_reflect_license", RsContext));
581109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
582109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  // For #pragma version
583109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(new RSVersionPragmaHandler("version", RsContext));
584109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
585109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  // For #pragma rs_fp*
586109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(new RSPrecisionPragmaHandler("rs_fp_full", RsContext));
587109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(new RSPrecisionPragmaHandler("rs_fp_relaxed", RsContext));
588109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet  PP.AddPragmaHandler(new RSPrecisionPragmaHandler("rs_fp_imprecise", RsContext));
589109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet}
590109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
591109e90a854ac8d8f4df24ef27db636a641ba9913Jean-Luc Brouillet
592e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
593