Recommitted r267132 "[ELF] - implemented ternary operator for linkerscript expressions"
authorGeorge Rimar <grimar@accesssoftek.com>
Fri, 22 Apr 2016 11:28:54 +0000 (11:28 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Fri, 22 Apr 2016 11:28:54 +0000 (11:28 +0000)
With fix: removed redundant Dot parameter.

Original commit message:
[ELF] - implemented ternary operator for linkerscript expressions

Patch implements ternary operator for linkerscript expressions.
Like:

SECTIONS {
 . = 0x1 ? 0x2 : 0x3;
...
}

Differential revision: http://reviews.llvm.org/D19332

llvm-svn: 267140

lld/ELF/LinkerScript.cpp
lld/ELF/LinkerScript.h
lld/test/ELF/linkerscript-locationcounter.s

index 9fcb2f6..77ba023 100644 (file)
@@ -97,6 +97,17 @@ uint64_t LinkerScript<ELFT>::parsePrimary(ArrayRef<StringRef> &Tokens) {
   return getInteger(Tok);
 }
 
+template <class ELFT>
+uint64_t LinkerScript<ELFT>::parseTernary(ArrayRef<StringRef> &Tokens,
+                                          uint64_t Cond) {
+  next(Tokens);
+  uint64_t V = parseExpr(Tokens);
+  if (!expect(Tokens, ":"))
+    return 0;
+  uint64_t W = parseExpr(Tokens);
+  return Cond ? V : W;
+}
+
 static uint64_t apply(StringRef Op, uint64_t L, uint64_t R) {
   if (Op == "+")
     return L + R;
@@ -126,6 +137,9 @@ uint64_t LinkerScript<ELFT>::parseExpr1(ArrayRef<StringRef> &Tokens,
   while (!Tokens.empty()) {
     // Read an operator and an expression.
     StringRef Op1 = Tokens.front();
+    if (Op1 == "?")
+      return parseTernary(Tokens, Lhs);
+
     if (precedence(Op1) < MinPrec)
       return Lhs;
     next(Tokens);
index dfffb98..25c668f 100644 (file)
@@ -93,6 +93,7 @@ private:
   uint64_t parseExpr(ArrayRef<StringRef> &Tokens);
   uint64_t parsePrimary(ArrayRef<StringRef> &Tokens);
   uint64_t parseExpr1(ArrayRef<StringRef> &Tokens, uint64_t Lhs, int MinPrec);
+  uint64_t parseTernary(ArrayRef<StringRef> &Tokens, uint64_t Cond);
   typename ELFT::uint Dot;
 };
 
index e2a67a7..51d1c39 100644 (file)
 # RUN:  .bracket : { *(.bracket) } \
 # RUN:  . = 0x17000 & 0x15000; \
 # RUN:  .and : { *(.and) } \
+# RUN:  . = 0x1 ? 0x16000 : 0x999999; \
+# RUN:  .ternary1 : { *(.ternary1) } \
+# RUN:  . = 0x0 ? 0x999999 : 0x17000; \
+# RUN:  .ternary2 : { *(.ternary2) } \
 # RUN: }" > %t.script
 # RUN: ld.lld %t --script %t.script -o %t2
 # RUN: llvm-readobj -s %t2 | FileCheck %s
 # CHECK-NEXT:   AddressAlignment:
 # CHECK-NEXT:   EntrySize:
 # CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT:   Index:
+# CHECK-NEXT:   Name: .ternary1
+# CHECK-NEXT:   Type: SHT_PROGBITS
+# CHECK-NEXT:   Flags [
+# CHECK-NEXT:     SHF_ALLOC
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Address: 0x16000
+# 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: .ternary2
+# CHECK-NEXT:   Type: SHT_PROGBITS
+# CHECK-NEXT:   Flags [
+# CHECK-NEXT:     SHF_ALLOC
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Address: 0x17000
+# 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 { \
 # RUN:  FileCheck --check-prefix=DIVZERO %s
 # DIVZERO: division by zero
 
+## Broken ternary operator expression.
+# RUN: echo "SECTIONS { \
+# RUN:  . = 0x1 ? 0x2; \
+# RUN: }" > %t.script
+# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \
+# RUN:  FileCheck --check-prefix=TERNERR %s
+# TERNERR: : expected
+
 .globl _start;
 _start:
 nop
@@ -170,3 +212,9 @@ nop
 
 .section .and, "a"
 .quad 0
+
+.section .ternary1, "a"
+.quad 0
+
+.section .ternary2, "a"
+.quad 0