diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp --- 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 @@ 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 --- a/lld/test/ELF/linkerscript/operators.test +++ b/lld/test/ELF/linkerscript/operators.test @@ -38,6 +38,14 @@ 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 @@ # 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