brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · fb0999b Raw
238 lines · cpp
1//===- LocationParser.cpp - MLIR Location Parser  -------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Parser.h"10#include "Token.h"11#include "mlir/IR/Attributes.h"12#include "mlir/IR/BuiltinAttributes.h"13#include "mlir/IR/Location.h"14#include "mlir/Support/LLVM.h"15#include <optional>16 17using namespace mlir;18using namespace mlir::detail;19 20/// Specific location instances.21///22/// location-inst ::= filelinecol-location |23///                   name-location |24///                   callsite-location |25///                   fused-location |26///                   unknown-location27/// filelinecol-location ::= string-literal ':' integer-literal28///                                         ':' integer-literal29/// name-location ::= string-literal30/// callsite-location ::= 'callsite' '(' location-inst 'at' location-inst ')'31/// fused-location ::= fused ('<' attribute-value '>')?32///                    '[' location-inst (location-inst ',')* ']'33/// unknown-location ::= 'unknown'34///35ParseResult Parser::parseCallSiteLocation(LocationAttr &loc) {36  consumeToken(Token::bare_identifier);37 38  // Parse the '('.39  if (parseToken(Token::l_paren, "expected '(' in callsite location"))40    return failure();41 42  // Parse the callee location.43  LocationAttr calleeLoc;44  if (parseLocationInstance(calleeLoc))45    return failure();46 47  // Parse the 'at'.48  if (getToken().isNot(Token::bare_identifier) ||49      getToken().getSpelling() != "at")50    return emitWrongTokenError("expected 'at' in callsite location");51  consumeToken(Token::bare_identifier);52 53  // Parse the caller location.54  LocationAttr callerLoc;55  if (parseLocationInstance(callerLoc))56    return failure();57 58  // Parse the ')'.59  if (parseToken(Token::r_paren, "expected ')' in callsite location"))60    return failure();61 62  // Return the callsite location.63  loc = CallSiteLoc::get(calleeLoc, callerLoc);64  return success();65}66 67ParseResult Parser::parseFusedLocation(LocationAttr &loc) {68  consumeToken(Token::bare_identifier);69 70  // Try to parse the optional metadata.71  Attribute metadata;72  if (consumeIf(Token::less)) {73    metadata = parseAttribute();74    if (!metadata)75      return failure();76 77    // Parse the '>' token.78    if (parseToken(Token::greater,79                   "expected '>' after fused location metadata"))80      return failure();81  }82 83  SmallVector<Location, 4> locations;84  auto parseElt = [&] {85    LocationAttr newLoc;86    if (parseLocationInstance(newLoc))87      return failure();88    locations.push_back(newLoc);89    return success();90  };91 92  if (parseCommaSeparatedList(Delimiter::Square, parseElt,93                              " in fused location"))94    return failure();95 96  // Return the fused location.97  loc = FusedLoc::get(locations, metadata, getContext());98  return success();99}100 101ParseResult Parser::parseNameOrFileLineColRange(LocationAttr &loc) {102  auto *ctx = getContext();103  auto str = getToken().getStringValue();104  consumeToken(Token::string);105 106  std::optional<unsigned> startLine, startColumn, endLine, endColumn;107 108  // If the next token is ':' this is a filelinecol location.109  if (consumeIf(Token::colon)) {110    // Parse the line number.111    if (getToken().isNot(Token::integer))112      return emitWrongTokenError(113          "expected integer line number in FileLineColRange");114    startLine = getToken().getUnsignedIntegerValue();115    if (!startLine)116      return emitWrongTokenError(117          "expected integer line number in FileLineColRange");118    consumeToken(Token::integer);119 120    // Parse the ':'.121    if (getToken().isNot(Token::colon)) {122      loc = FileLineColRange::get(StringAttr::get(ctx, str), *startLine);123      return success();124    }125    consumeToken(Token::colon);126 127    // Parse the column number.128    if (getToken().isNot(Token::integer)) {129      return emitWrongTokenError(130          "expected integer column number in FileLineColRange");131    }132    startColumn = getToken().getUnsignedIntegerValue();133    if (!startColumn.has_value())134      return emitError("expected integer column number in FileLineColRange");135    consumeToken(Token::integer);136 137    if (!isCurrentTokenAKeyword() || getTokenSpelling() != "to") {138      loc = FileLineColLoc::get(ctx, str, *startLine, *startColumn);139      return success();140    }141    consumeToken();142 143    // Parse the line number.144    if (getToken().is(Token::integer)) {145      endLine = getToken().getUnsignedIntegerValue();146      if (!endLine) {147        return emitWrongTokenError(148            "expected integer line number in FileLineColRange");149      }150      consumeToken(Token::integer);151    }152 153    // Parse the ':'.154    if (getToken().isNot(Token::colon)) {155      return emitWrongTokenError(156          "expected either integer or `:` post `to` in FileLineColRange");157    }158    consumeToken(Token::colon);159 160    // Parse the column number.161    if (getToken().isNot(Token::integer)) {162      return emitWrongTokenError(163          "expected integer column number in FileLineColRange");164    }165    endColumn = getToken().getUnsignedIntegerValue();166    if (!endColumn.has_value())167      return emitError("expected integer column number in FileLineColRange");168    consumeToken(Token::integer);169 170    if (endLine.has_value()) {171      loc = FileLineColRange::get(StringAttr::get(ctx, str), *startLine,172                                  *startColumn, *endLine, *endColumn);173    } else {174      loc = FileLineColRange::get(StringAttr::get(ctx, str), *startLine,175                                  *startColumn, *endColumn);176    }177    return success();178  }179 180  // Otherwise, this is a NameLoc.181 182  // Check for a child location.183  if (consumeIf(Token::l_paren)) {184    // Parse the child location.185    LocationAttr childLoc;186    if (parseLocationInstance(childLoc))187      return failure();188 189    loc = NameLoc::get(StringAttr::get(ctx, str), childLoc);190 191    // Parse the closing ')'.192    if (parseToken(Token::r_paren,193                   "expected ')' after child location of NameLoc"))194      return failure();195  } else {196    loc = NameLoc::get(StringAttr::get(ctx, str));197  }198 199  return success();200}201 202ParseResult Parser::parseLocationInstance(LocationAttr &loc) {203  // Handle aliases.204  if (getToken().is(Token::hash_identifier)) {205    Attribute locAttr = parseExtendedAttr(Type());206    if (!locAttr)207      return failure();208    if (!(loc = dyn_cast<LocationAttr>(locAttr)))209      return emitError("expected location attribute, but got") << locAttr;210    return success();211  }212 213  // Handle either name or filelinecol locations.214  if (getToken().is(Token::string))215    return parseNameOrFileLineColRange(loc);216 217  // Bare tokens required for other cases.218  if (!getToken().is(Token::bare_identifier))219    return emitWrongTokenError("expected location instance");220 221  // Check for the 'callsite' signifying a callsite location.222  if (getToken().getSpelling() == "callsite")223    return parseCallSiteLocation(loc);224 225  // If the token is 'fused', then this is a fused location.226  if (getToken().getSpelling() == "fused")227    return parseFusedLocation(loc);228 229  // Check for a 'unknown' for an unknown location.230  if (getToken().getSpelling() == "unknown") {231    consumeToken(Token::bare_identifier);232    loc = UnknownLoc::get(getContext());233    return success();234  }235 236  return emitWrongTokenError("expected location instance");237}238