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:
Shankar Easwaran 2014-11-10 14:54:34 +00:00
parent 0de6a9b5bf
commit c937b4923e
10 changed files with 192 additions and 112 deletions

View File

@ -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

View File

@ -3,3 +3,4 @@ add_subdirectory(Core)
add_subdirectory(Driver)
add_subdirectory(Passes)
add_subdirectory(ReaderWriter)
add_subdirectory(Support)

View File

@ -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

View File

@ -18,4 +18,5 @@ add_lld_library(lldReaderWriter
target_link_libraries(lldReaderWriter ${cmake_2_8_12_INTERFACE}
lldCore
lldPasses
lldSupport
)

View File

@ -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';
}

View File

@ -0,0 +1,3 @@
add_lld_library(lldSupport
NumParse.cpp
)

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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