Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -105,6 +105,13 @@ return V; } +uint64_t static getConstantValue(StringRef C) { + if (C == "COMMONPAGESIZE" || C == "MAXPAGESIZE") + return Target->PageSize; + error("unknown constant: " + C); + return 0; +} + // This is a part of the operator-precedence parser to evaluate // arithmetic expressions in SECTIONS command. This function evaluates an // integer literal, a parenthesized expression, the ALIGN function, @@ -124,6 +131,34 @@ expect(")"); return alignTo(Dot, V); } + if (Tok == "CONSTANT") { + expect("("); + uint64_t V = getConstantValue(next()); + expect(")"); + return V; + } + // Documentations says there are two ways to compute + // the value of DATA_SEGMENT_ALIGN command, depending on whether the second + // uses fewer COMMONPAGESIZE sized pages for the data segment(area between the + // result of this expression and `DATA_SEGMENT_END') than the first or not. + // That is possible optimization, that we do not support, so we compute that + // function always as (ALIGN(MAXPAGESIZE) + (. & (MAXPAGESIZE - 1))) now. + if (Tok == "DATA_SEGMENT_ALIGN") { + expect("("); + uint64_t L = parseExpr(); + expect(","); + parseExpr(); + expect(")"); + return alignTo(Dot, L) + (Dot & (L - 1)); + } + // Since we do not support the optimization from comment above, + // we can just ignore that command. + if (Tok == "DATA_SEGMENT_END") { + expect("("); + expect("."); + expect(")"); + return Dot; + } uint64_t V = 0; if (Tok.getAsInteger(0, V)) setError("malformed number: " + Tok); Index: lld/trunk/test/ELF/linkerscript-locationcounter.s =================================================================== --- lld/trunk/test/ELF/linkerscript-locationcounter.s +++ lld/trunk/test/ELF/linkerscript-locationcounter.s @@ -30,6 +30,13 @@ # RUN: .eq : { *(.eq) } \ # RUN: . = 0x2 != 0x1 ? 0x23000 : 0x999999; \ # RUN: .neq : { *(.neq) } \ +# RUN: . = CONSTANT (MAXPAGESIZE) * 0x24; \ +# RUN: .maxpagesize : { *(.maxpagesize) } \ +# RUN: . = CONSTANT (COMMONPAGESIZE) * 0x25; \ +# RUN: .commonpagesize : { *(.commonpagesize) } \ +# RUN: . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); \ +# RUN: .datasegmentalign : { *(.datasegmentalign) } \ +# RUN: . = DATA_SEGMENT_END (.); \ # RUN: }" > %t.script # RUN: ld.lld %t --script %t.script -o %t2 # RUN: llvm-readobj -s %t2 | FileCheck %s @@ -244,6 +251,51 @@ # CHECK-NEXT: AddressAlignment: # CHECK-NEXT: EntrySize: # CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: +# CHECK-NEXT: Name: .maxpagesize +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x24000 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: +# CHECK-NEXT: Name: .commonpagesize +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x25000 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: +# CHECK-NEXT: Name: .datasegmentalign +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x26008 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: } ## Mailformed number error. # RUN: echo "SECTIONS { \ @@ -338,3 +390,12 @@ .section .neq, "a" .quad 0 + +.section .maxpagesize, "a" +.quad 0 + +.section .commonpagesize, "a" +.quad 0 + +.section .datasegmentalign, "a" +.quad 0