Index: lld/ELF/ScriptParser.cpp =================================================================== --- lld/ELF/ScriptParser.cpp +++ lld/ELF/ScriptParser.cpp @@ -1329,6 +1329,16 @@ return cmd->getLMA(); }; } + if (tok == "LOG2CEIL") { + expect("("); + Expr a = readExpr(); + expect(")"); + return [=] { + /* LOG2CEIL(0) is defined to be 0 */ + return std::ceil( + std::log2(std::max(a().getValue(), static_cast(1)))); + }; + } if (tok == "MAX" || tok == "MIN") { expect("("); Expr a = readExpr(); Index: lld/test/ELF/linkerscript/operators.test =================================================================== --- lld/test/ELF/linkerscript/operators.test +++ 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); + log2ceil0ff = LOG2CEIL(0x0ff); + log2ceil100 = LOG2CEIL(0x100); + log2ceil1ff = LOG2CEIL(0x1ff); 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: 0000000000000008 A log2ceil0ff +# CHECK-NEXT: 0000000000000008 A log2ceil100 +# CHECK-NEXT: 0000000000000009 A log2ceil1ff # CHECK-NEXT: 00000000000000 A logicaland1 # CHECK-NEXT: 00000000000000 A logicaland2 # CHECK-NEXT: 00000000000000 A logicaland3