forked from OSchip/llvm-project
Add support library.
The parsing routines in the linker script to parse strings encoded in various formats(hexadecimal, octal, decimal, etc), is needed by the GNU driver too. This library provides helper functions for all flavors and flavors to add helper functions which other flavors may make use of. llvm-svn: 221583
This commit is contained in:
parent
0de6a9b5bf
commit
c937b4923e
|
@ -0,0 +1,45 @@
|
|||
//===-- lld/Support/NumParse.h - Number parsing -----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// \brief Parses string in various formats to decimal.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_SUPPORT_NUM_PARSE_H
|
||||
#define LLD_SUPPORT_NUM_PARSE_H
|
||||
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
namespace lld {
|
||||
|
||||
/// \brief Convert a string in decimal to decimal.
|
||||
llvm::ErrorOr<uint64_t> parseDecimal(StringRef str);
|
||||
|
||||
/// \brief Convert a string in octal to decimal.
|
||||
llvm::ErrorOr<uint64_t> parseOctal(StringRef str);
|
||||
|
||||
/// \brief Convert a string in Binary to decimal.
|
||||
llvm::ErrorOr<uint64_t> parseBinary(StringRef str);
|
||||
|
||||
/// \brief Convert a string in Hexadecimal to decimal.
|
||||
llvm::ErrorOr<uint64_t> parseHex(StringRef str);
|
||||
|
||||
/// \brief Parse a number represested in a string as
|
||||
// Hexadecimal, Octal, Binary or Decimal to decimal
|
||||
llvm::ErrorOr<uint64_t> parseNum(StringRef str, bool parseExtensions = true);
|
||||
}
|
||||
|
||||
#endif // LLD_SUPPORT_NUM_PARSE_H
|
|
@ -3,3 +3,4 @@ add_subdirectory(Core)
|
|||
add_subdirectory(Driver)
|
||||
add_subdirectory(Passes)
|
||||
add_subdirectory(ReaderWriter)
|
||||
add_subdirectory(Support)
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
LLD_LEVEL := ..
|
||||
|
||||
# ARCMigrate and Rewrite are always needed because of libclang.
|
||||
PARALLEL_DIRS = Config Core Driver Passes ReaderWriter
|
||||
PARALLEL_DIRS = Config Core Driver Passes ReaderWriter Support
|
||||
|
||||
include $(LLD_LEVEL)/../../Makefile.config
|
||||
|
||||
|
|
|
@ -18,4 +18,5 @@ add_lld_library(lldReaderWriter
|
|||
target_link_libraries(lldReaderWriter ${cmake_2_8_12_INTERFACE}
|
||||
lldCore
|
||||
lldPasses
|
||||
lldSupport
|
||||
)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/ReaderWriter/LinkerScript.h"
|
||||
#include "lld/Support/NumParse.h"
|
||||
|
||||
namespace lld {
|
||||
namespace script {
|
||||
|
@ -89,56 +90,7 @@ void Token::dump(raw_ostream &os) const {
|
|||
os << _range << "\n";
|
||||
}
|
||||
|
||||
static llvm::ErrorOr<uint64_t> parseDecimal(StringRef str) {
|
||||
uint64_t res = 0;
|
||||
for (auto &c : str) {
|
||||
res *= 10;
|
||||
if (c < '0' || c > '9')
|
||||
return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
|
||||
res += c - '0';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static llvm::ErrorOr<uint64_t> parseOctal(StringRef str) {
|
||||
uint64_t res = 0;
|
||||
for (auto &c : str) {
|
||||
res <<= 3;
|
||||
if (c < '0' || c > '7')
|
||||
return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
|
||||
res += c - '0';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static llvm::ErrorOr<uint64_t> parseBinary(StringRef str) {
|
||||
uint64_t res = 0;
|
||||
for (auto &c : str) {
|
||||
res <<= 1;
|
||||
if (c != '0' && c != '1')
|
||||
return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
|
||||
res += c - '0';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static llvm::ErrorOr<uint64_t> parseHex(StringRef str) {
|
||||
uint64_t res = 0;
|
||||
for (auto &c : str) {
|
||||
res <<= 4;
|
||||
if (c >= '0' && c <= '9')
|
||||
res += c - '0';
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
res += c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
res += c - 'A' + 10;
|
||||
else
|
||||
return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool parseHexToByteStream(StringRef str, std::string &buf) {
|
||||
bool parseHexToByteStream(StringRef str, std::string &buf) {
|
||||
unsigned char byte = 0;
|
||||
bool dumpByte = str.size() % 2;
|
||||
for (auto &c : str) {
|
||||
|
@ -178,63 +130,6 @@ static void dumpByteStream(raw_ostream &os, StringRef stream) {
|
|||
}
|
||||
}
|
||||
|
||||
static llvm::ErrorOr<uint64_t> parseNum(StringRef str) {
|
||||
unsigned multiplier = 1;
|
||||
enum NumKind { decimal, hex, octal, binary };
|
||||
NumKind kind = llvm::StringSwitch<NumKind>(str)
|
||||
.StartsWith("0x", hex)
|
||||
.StartsWith("0X", hex)
|
||||
.StartsWith("0", octal)
|
||||
.Default(decimal);
|
||||
|
||||
// Parse scale
|
||||
if (str.endswith("K")) {
|
||||
multiplier = 1 << 10;
|
||||
str = str.drop_back();
|
||||
} else if (str.endswith("M")) {
|
||||
multiplier = 1 << 20;
|
||||
str = str.drop_back();
|
||||
}
|
||||
|
||||
// Parse type
|
||||
if (str.endswith_lower("o")) {
|
||||
kind = octal;
|
||||
str = str.drop_back();
|
||||
} else if (str.endswith_lower("h")) {
|
||||
kind = hex;
|
||||
str = str.drop_back();
|
||||
} else if (str.endswith_lower("d")) {
|
||||
kind = decimal;
|
||||
str = str.drop_back();
|
||||
} else if (str.endswith_lower("b")) {
|
||||
kind = binary;
|
||||
str = str.drop_back();
|
||||
}
|
||||
|
||||
llvm::ErrorOr<uint64_t> res(0);
|
||||
switch (kind) {
|
||||
case hex:
|
||||
if (str.startswith_lower("0x"))
|
||||
str = str.drop_front(2);
|
||||
res = parseHex(str);
|
||||
break;
|
||||
case octal:
|
||||
res = parseOctal(str);
|
||||
break;
|
||||
case decimal:
|
||||
res = parseDecimal(str);
|
||||
break;
|
||||
case binary:
|
||||
res = parseBinary(str);
|
||||
break;
|
||||
}
|
||||
if (res.getError())
|
||||
return res;
|
||||
|
||||
*res = *res * multiplier;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Lexer::canStartNumber(char c) const {
|
||||
return '0' <= c && c <= '9';
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
add_lld_library(lldSupport
|
||||
NumParse.cpp
|
||||
)
|
|
@ -0,0 +1,133 @@
|
|||
//===-- lld/Support/NumParse.cpp - Number parsing ---------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// \brief Parses string in various formats to decimal.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Support/NumParse.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace lld {
|
||||
/// \brief Convert a string in decimal to decimal.
|
||||
llvm::ErrorOr<uint64_t> parseDecimal(StringRef str) {
|
||||
uint64_t res = 0;
|
||||
for (auto &c : str) {
|
||||
res *= 10;
|
||||
if (c < '0' || c > '9')
|
||||
return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
|
||||
res += c - '0';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// \brief Convert a string in octal to decimal.
|
||||
llvm::ErrorOr<uint64_t> parseOctal(StringRef str) {
|
||||
uint64_t res = 0;
|
||||
for (auto &c : str) {
|
||||
res <<= 3;
|
||||
if (c < '0' || c > '7')
|
||||
return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
|
||||
res += c - '0';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// \brief Convert a string in Binary to decimal.
|
||||
llvm::ErrorOr<uint64_t> parseBinary(StringRef str) {
|
||||
uint64_t res = 0;
|
||||
for (auto &c : str) {
|
||||
res <<= 1;
|
||||
if (c != '0' && c != '1')
|
||||
return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
|
||||
res += c - '0';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// \brief Convert a string in Hexadecimal to decimal.
|
||||
llvm::ErrorOr<uint64_t> parseHex(StringRef str) {
|
||||
uint64_t res = 0;
|
||||
for (auto &c : str) {
|
||||
res <<= 4;
|
||||
if (c >= '0' && c <= '9')
|
||||
res += c - '0';
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
res += c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
res += c - 'A' + 10;
|
||||
else
|
||||
return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// \brief Parse a number represested in a string as
|
||||
// Hexadecimal, Octal, Binary or Decimal to decimal
|
||||
llvm::ErrorOr<uint64_t> parseNum(StringRef str, bool parseExtensions) {
|
||||
unsigned multiplier = 1;
|
||||
enum NumKind { decimal, hex, octal, binary };
|
||||
NumKind kind = llvm::StringSwitch<NumKind>(str)
|
||||
.StartsWith("0x", hex)
|
||||
.StartsWith("0X", hex)
|
||||
.StartsWith("0", octal)
|
||||
.Default(decimal);
|
||||
|
||||
if (parseExtensions) {
|
||||
// Parse scale
|
||||
if (str.endswith("K")) {
|
||||
multiplier = 1 << 10;
|
||||
str = str.drop_back();
|
||||
} else if (str.endswith("M")) {
|
||||
multiplier = 1 << 20;
|
||||
str = str.drop_back();
|
||||
}
|
||||
|
||||
// Parse type
|
||||
if (str.endswith_lower("o")) {
|
||||
kind = octal;
|
||||
str = str.drop_back();
|
||||
} else if (str.endswith_lower("h")) {
|
||||
kind = hex;
|
||||
str = str.drop_back();
|
||||
} else if (str.endswith_lower("d")) {
|
||||
kind = decimal;
|
||||
str = str.drop_back();
|
||||
} else if (str.endswith_lower("b")) {
|
||||
kind = binary;
|
||||
str = str.drop_back();
|
||||
}
|
||||
}
|
||||
|
||||
llvm::ErrorOr<uint64_t> res(0);
|
||||
switch (kind) {
|
||||
case hex:
|
||||
if (str.startswith_lower("0x"))
|
||||
str = str.drop_front(2);
|
||||
res = parseHex(str);
|
||||
break;
|
||||
case octal:
|
||||
res = parseOctal(str);
|
||||
break;
|
||||
case decimal:
|
||||
res = parseDecimal(str);
|
||||
break;
|
||||
case binary:
|
||||
res = parseBinary(str);
|
||||
break;
|
||||
}
|
||||
if (res.getError())
|
||||
return res;
|
||||
|
||||
*res = *res * multiplier;
|
||||
return res;
|
||||
}
|
||||
}
|
|
@ -19,9 +19,9 @@ LEVEL := $(LLD_LEVEL)/../..
|
|||
include $(LEVEL)/Makefile.config
|
||||
|
||||
LINK_COMPONENTS := $(TARGETS_TO_BUILD)
|
||||
USEDLIBS = lldDriver.a lldConfig.a \
|
||||
USEDLIBS = lldDriver.a lldConfig.a lldSupport.a \
|
||||
lldELF.a lldMachO.a lldPasses.a lldPECOFF.a lldYAML.a \
|
||||
lldReaderWriter.a lldCore.a lldNative.a \
|
||||
lldReaderWriter.a lldCore.a lldSupport.a lldNative.a \
|
||||
lldHexagonELFTarget.a lldPPCELFTarget.a lldMipsELFTarget.a \
|
||||
lldX86ELFTarget.a lldX86_64ELFTarget.a lldAArch64ELFTarget.a \
|
||||
LLVMOption.a
|
||||
|
|
|
@ -15,5 +15,7 @@ USEDLIBS = lldDriver.a lldConfig.a \
|
|||
lldHexagonELFTarget.a lldPPCELFTarget.a lldMipsELFTarget.a \
|
||||
lldX86ELFTarget.a lldX86_64ELFTarget.a lldYAML.a \
|
||||
LLVMObject.a LLVMMCParser.a LLVMMC.a LLVMBitReader.a \
|
||||
LLVMCore.a LLVMOption.a LLVMSupport.a lldAArch64ELFTarget.a
|
||||
LLVMCore.a LLVMOption.a LLVMSupport.a lldAArch64ELFTarget.a \
|
||||
lldSupport.a
|
||||
|
||||
include $(LLD_LEVEL)/unittests/Makefile
|
||||
|
|
|
@ -19,6 +19,6 @@ LEVEL := $(LLD_LEVEL)/../..
|
|||
include $(LEVEL)/Makefile.config
|
||||
|
||||
LINK_COMPONENTS := $(TARGETS_TO_BUILD)
|
||||
USEDLIBS = lldReaderWriter.a LLVMSupport.a
|
||||
USEDLIBS = lldReaderWriter.a lldSupport.a LLVMSupport.a
|
||||
|
||||
include $(LLD_LEVEL)/Makefile
|
||||
|
|
Loading…
Reference in New Issue