From fa1145a8d2f1bd00a60d0ed4572901d2b1403157 Mon Sep 17 00:00:00 2001 From: Isaac Richter Date: Mon, 27 Jul 2020 11:49:24 +0300 Subject: [PATCH] [lld][ELF] Add LOG2CEIL builtin ldscript function This patch adds support for the LOG2CEIL builtin function in linker scripts: https://sourceware.org/binutils/docs/ld/Builtin-Functions.html#index-LOG2CEIL_0028exp_0029 As documented for LD, and to keep compatibility, LOG2CEIL(0) returns 0 (not -inf). The test vectors are somewhat arbitrary. We check minimum values (0-4); middle values (2^32, and 2^32+1); and the maximum value (2^64-1). The checks for LOG2CEIL explicitly use full 64-bit values (16 hex digits). This is needed to properly verify that -inf and other interesting results aren't returned. (For some reason, all other tests in operators.test use only 14 digits.) Differential revision: https://reviews.llvm.org/D84054 --- lld/ELF/ScriptParser.cpp | 10 ++++++++++ lld/test/ELF/linkerscript/operators.test | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index fea6b7a274e7..17ac7ff6d5f4 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/ScopedPrinter.h" #include @@ -1329,6 +1330,15 @@ Expr ScriptParser::readPrimary() { return cmd->getLMA(); }; } + if (tok == "LOG2CEIL") { + expect("("); + Expr a = readExpr(); + expect(")"); + return [=] { + // LOG2CEIL(0) is defined to be 0. + return llvm::Log2_64_Ceil(std::max(a().getValue(), UINT64_C(1))); + }; + } if (tok == "MAX" || tok == "MIN") { expect("("); Expr a = readExpr(); diff --git a/lld/test/ELF/linkerscript/operators.test b/lld/test/ELF/linkerscript/operators.test index 1d40c81321d9..8ba8ee7ea41d 100644 --- a/lld/test/ELF/linkerscript/operators.test +++ b/lld/test/ELF/linkerscript/operators.test @@ -38,6 +38,14 @@ SECTIONS { minus_abs = _end - _start; max = MAX(11, 22); min = MIN(11, 22); + log2ceil0 = LOG2CEIL(0); + log2ceil1 = LOG2CEIL(1); + log2ceil2 = LOG2CEIL(2); + log2ceil3 = LOG2CEIL(3); + log2ceil4 = LOG2CEIL(4); + log2ceil100000000 = LOG2CEIL(0x100000000); + log2ceil100000001 = LOG2CEIL(0x100000001); + log2ceilmax = LOG2CEIL(0xffffffffffffffff); logicaland1 = 0 && 0; logicaland2 = 0 && 1; logicaland3 = 1 && 0; @@ -78,6 +86,14 @@ SECTIONS { # CHECK-NEXT: 0000000000fff0 A minus_abs # CHECK-NEXT: 00000000000016 A max # CHECK-NEXT: 0000000000000b A min +# CHECK-NEXT: 0000000000000000 A log2ceil0 +# CHECK-NEXT: 0000000000000000 A log2ceil1 +# CHECK-NEXT: 0000000000000001 A log2ceil2 +# CHECK-NEXT: 0000000000000002 A log2ceil3 +# CHECK-NEXT: 0000000000000002 A log2ceil4 +# CHECK-NEXT: 0000000000000020 A log2ceil100000000 +# CHECK-NEXT: 0000000000000021 A log2ceil100000001 +# CHECK-NEXT: 0000000000000040 A log2ceilmax # CHECK-NEXT: 00000000000000 A logicaland1 # CHECK-NEXT: 00000000000000 A logicaland2 # CHECK-NEXT: 00000000000000 A logicaland3