brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.1 KiB · f60b5d2 Raw
198 lines · cpp
1//===-- PostfixExpressionTest.cpp -----------------------------------------===//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 "lldb/Symbol/PostfixExpression.h"10#include "lldb/Utility/DataExtractor.h"11#include "lldb/Utility/StreamString.h"12#include "llvm/ADT/StringExtras.h"13#include "llvm/DebugInfo/DIContext.h"14#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"15#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"16#include "llvm/Support/FormatVariadic.h"17#include "llvm/Support/raw_ostream.h"18#include "gmock/gmock.h"19#include "gtest/gtest.h"20 21using namespace lldb_private;22using namespace lldb_private::postfix;23 24static std::string ToString(BinaryOpNode::OpType type) {25  switch (type) {26  case BinaryOpNode::Align:27    return "@";28  case BinaryOpNode::Minus:29    return "-";30  case BinaryOpNode::Plus:31    return "+";32  }33  llvm_unreachable("Fully covered switch!");34}35 36static std::string ToString(UnaryOpNode::OpType type) {37  switch (type) {38  case UnaryOpNode::Deref:39    return "^";40  }41  llvm_unreachable("Fully covered switch!");42}43 44struct ASTPrinter : public Visitor<std::string> {45protected:46  std::string Visit(BinaryOpNode &binary, Node *&) override {47    return std::string(48        llvm::formatv("{0}({1}, {2})", ToString(binary.GetOpType()),49                      Dispatch(binary.Left()), Dispatch(binary.Right())));50  }51 52  std::string Visit(InitialValueNode &, Node *&) override { return "InitialValue"; }53 54  std::string Visit(IntegerNode &integer, Node *&) override {55    return std::string(llvm::formatv("int({0})", integer.GetValue()));56  }57 58  std::string Visit(RegisterNode &reg, Node *&) override {59    return std::string(llvm::formatv("reg({0})", reg.GetRegNum()));60  }61 62  std::string Visit(SymbolNode &symbol, Node *&) override {63    return std::string(symbol.GetName());64  }65 66  std::string Visit(UnaryOpNode &unary, Node *&) override {67    return std::string(llvm::formatv("{0}({1})", ToString(unary.GetOpType()),68                                     Dispatch(unary.Operand())));69  }70 71public:72  static std::string Print(Node *node) {73    if (node)74      return ASTPrinter().Dispatch(node);75    return "nullptr";76  }77};78 79static std::string ParseOneAndStringify(llvm::StringRef expr) {80  llvm::BumpPtrAllocator alloc;81  return ASTPrinter::Print(ParseOneExpression(expr, alloc));82}83 84TEST(PostfixExpression, ParseOneExpression) {85  EXPECT_EQ("int(47)", ParseOneAndStringify("47"));86  EXPECT_EQ("$foo", ParseOneAndStringify("$foo"));87  EXPECT_EQ("+(int(1), int(2))", ParseOneAndStringify("1 2 +"));88  EXPECT_EQ("-(int(1), int(2))", ParseOneAndStringify("1 2 -"));89  EXPECT_EQ("@(int(1), int(2))", ParseOneAndStringify("1 2 @"));90  EXPECT_EQ("+(int(1), +(int(2), int(3)))", ParseOneAndStringify("1 2 3 + +"));91  EXPECT_EQ("+(+(int(1), int(2)), int(3))", ParseOneAndStringify("1 2 + 3 +"));92  EXPECT_EQ("^(int(1))", ParseOneAndStringify("1 ^"));93  EXPECT_EQ("^(^(int(1)))", ParseOneAndStringify("1 ^ ^"));94  EXPECT_EQ("^(+(int(1), ^(int(2))))", ParseOneAndStringify("1 2 ^ + ^"));95  EXPECT_EQ("-($foo, int(47))", ParseOneAndStringify("$foo 47 -"));96  EXPECT_EQ("+(int(47), int(-42))", ParseOneAndStringify("47 -42 +"));97 98  EXPECT_EQ("nullptr", ParseOneAndStringify("+"));99  EXPECT_EQ("nullptr", ParseOneAndStringify("^"));100  EXPECT_EQ("nullptr", ParseOneAndStringify("1 +"));101  EXPECT_EQ("nullptr", ParseOneAndStringify("1 2 ^"));102  EXPECT_EQ("nullptr", ParseOneAndStringify("1 2 3 +"));103  EXPECT_EQ("nullptr", ParseOneAndStringify("^ 1"));104  EXPECT_EQ("nullptr", ParseOneAndStringify("+ 1 2"));105  EXPECT_EQ("nullptr", ParseOneAndStringify("1 + 2"));106  EXPECT_EQ("nullptr", ParseOneAndStringify("1 2"));107  EXPECT_EQ("nullptr", ParseOneAndStringify(""));108}109 110static std::vector<std::pair<std::string, std::string>>111ParseFPOAndStringify(llvm::StringRef prog) {112  llvm::BumpPtrAllocator alloc;113  std::vector<std::pair<llvm::StringRef, Node *>> parsed =114      ParseFPOProgram(prog, alloc);115  std::vector<std::pair<std::string, std::string>> result;116  for (const auto &p : parsed)117    result.emplace_back(p.first.str(), ASTPrinter::Print(p.second));118  return result;119}120 121TEST(PostfixExpression, ParseFPOProgram) {122  EXPECT_THAT(ParseFPOAndStringify("a 1 ="),123              testing::ElementsAre(std::make_pair("a", "int(1)")));124  EXPECT_THAT(ParseFPOAndStringify("a 1 = b 2 3 + ="),125              testing::ElementsAre(std::make_pair("a", "int(1)"),126                                   std::make_pair("b", "+(int(2), int(3))")));127 128  EXPECT_THAT(ParseFPOAndStringify(""), testing::IsEmpty());129  EXPECT_THAT(ParseFPOAndStringify("="), testing::IsEmpty());130  EXPECT_THAT(ParseFPOAndStringify("a 1"), testing::IsEmpty());131  EXPECT_THAT(ParseFPOAndStringify("a 1 = ="), testing::IsEmpty());132  EXPECT_THAT(ParseFPOAndStringify("a 1 + ="), testing::IsEmpty());133  EXPECT_THAT(ParseFPOAndStringify("= a 1 ="), testing::IsEmpty());134}135 136static std::string ParseAndGenerateDWARF(llvm::StringRef expr) {137  llvm::BumpPtrAllocator alloc;138  Node *ast = ParseOneExpression(expr, alloc);139  if (!ast)140    return "Parse failed.";141  if (!ResolveSymbols(ast, [&](SymbolNode &symbol) -> Node * {142        if (symbol.GetName() == "INIT")143          return MakeNode<InitialValueNode>(alloc);144 145        uint32_t num;146        if (to_integer(symbol.GetName().drop_front(), num))147          return MakeNode<RegisterNode>(alloc, num);148        return nullptr;149      })) {150    return "Resolution failed.";151  }152 153  const size_t addr_size = 4;154  StreamString dwarf(Stream::eBinary, addr_size, lldb::eByteOrderLittle);155  ToDWARF(*ast, dwarf);156 157  // print dwarf expression to comparable textual representation158  llvm::DataExtractor extractor(dwarf.GetString(), /*IsLittleEndian=*/true,159                                addr_size);160 161  std::string result;162  llvm::raw_string_ostream os(result);163  llvm::DWARFExpression E(extractor, addr_size, llvm::dwarf::DWARF32);164  llvm::printDwarfExpression(&E, os, llvm::DIDumpOptions(), nullptr);165  return result;166}167 168TEST(PostfixExpression, ToDWARF) {169  EXPECT_EQ("DW_OP_consts +0", ParseAndGenerateDWARF("0"));170 171  EXPECT_EQ("DW_OP_breg1 +0", ParseAndGenerateDWARF("R1"));172 173  EXPECT_EQ("DW_OP_bregx 0x41 +0", ParseAndGenerateDWARF("R65"));174 175  EXPECT_EQ("DW_OP_pick 0x0", ParseAndGenerateDWARF("INIT"));176 177  EXPECT_EQ("DW_OP_pick 0x0, DW_OP_pick 0x1, DW_OP_plus",178            ParseAndGenerateDWARF("INIT INIT +"));179 180  EXPECT_EQ("DW_OP_breg1 +0, DW_OP_pick 0x1, DW_OP_plus",181            ParseAndGenerateDWARF("R1 INIT +"));182 183  EXPECT_EQ("DW_OP_consts +1, DW_OP_pick 0x1, DW_OP_deref, DW_OP_plus",184            ParseAndGenerateDWARF("1 INIT ^ +"));185 186  EXPECT_EQ("DW_OP_consts +4, DW_OP_consts +5, DW_OP_plus",187            ParseAndGenerateDWARF("4 5 +"));188 189  EXPECT_EQ("DW_OP_consts +4, DW_OP_consts +5, DW_OP_minus",190            ParseAndGenerateDWARF("4 5 -"));191 192  EXPECT_EQ("DW_OP_consts +4, DW_OP_deref", ParseAndGenerateDWARF("4 ^"));193 194  EXPECT_EQ("DW_OP_breg6 +0, DW_OP_consts +128, DW_OP_lit1, DW_OP_minus, "195            "DW_OP_not, DW_OP_and",196            ParseAndGenerateDWARF("R6 128 @"));197}198