summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/LinkerScript.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter/LinkerScript.cpp')
-rw-r--r--lld/lib/ReaderWriter/LinkerScript.cpp109
1 files changed, 107 insertions, 2 deletions
diff --git a/lld/lib/ReaderWriter/LinkerScript.cpp b/lld/lib/ReaderWriter/LinkerScript.cpp
index 080e5336498..3984408b605 100644
--- a/lld/lib/ReaderWriter/LinkerScript.cpp
+++ b/lld/lib/ReaderWriter/LinkerScript.cpp
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "lld/ReaderWriter/LinkerScript.h"
-#include "lld/Support/NumParse.h"
namespace lld {
namespace script {
@@ -90,7 +89,56 @@ void Token::dump(raw_ostream &os) const {
os << _range << "\n";
}
-bool parseHexToByteStream(StringRef str, std::string &buf) {
+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) {
unsigned char byte = 0;
bool dumpByte = str.size() % 2;
for (auto &c : str) {
@@ -130,6 +178,63 @@ 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';
}
OpenPOWER on IntegriCloud