[llvm] r348363 - [llvm-rc] Support not expressions.

Martin Storsjo via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 5 05:22:57 PST 2018


Author: mstorsjo
Date: Wed Dec  5 05:22:56 2018
New Revision: 348363

URL: http://llvm.org/viewvc/llvm-project?rev=348363&view=rev
Log:
[llvm-rc] Support not expressions.

Patch by Jacek Caban!

Differential Revision: https://reviews.llvm.org/D55242

Added:
    llvm/trunk/test/tools/llvm-rc/Inputs/not-expr.rc
    llvm/trunk/test/tools/llvm-rc/not-expr.test
Modified:
    llvm/trunk/tools/llvm-rc/ResourceFileWriter.cpp
    llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp
    llvm/trunk/tools/llvm-rc/ResourceScriptParser.h
    llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp
    llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h

Added: llvm/trunk/test/tools/llvm-rc/Inputs/not-expr.rc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/Inputs/not-expr.rc?rev=348363&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/Inputs/not-expr.rc (added)
+++ llvm/trunk/test/tools/llvm-rc/Inputs/not-expr.rc Wed Dec  5 05:22:56 2018
@@ -0,0 +1,17 @@
+not DIALOGEX // not as an identifier
+0,
+3 | not 1, // = 2
+61 + not 1, // = 60
+not 1 | 3,  // = 3
+7 | (not 1 + not 2) // = 4
+STYLE   0xff00ff03 & ~(not (1|2)) // = 0xff00ff03
+EXSTYLE 0xff00ff03 | ~(not (1|2)) | not 8 // = 0xfffffff7
+{
+    GROUPBOX "", 0,
+        not 1, // = 0
+        15 + (((not 1 | not 2 | not 4) | 2)), // = 10
+        0, 0, 0x34 - (not 1) + (not 0x14) // expression evaluates to 0x20 with not mask 0x15, which clears 0x5 bits of default
+                                          // groupbox class style 0x50000007, resulting with style 0x50000022
+    GROUPBOX "", 1, 0,0,0,0,(not 7) | 1   // expression evaluates to 1 with not mask 0x7, which clears 0x7 bits of groupbox default
+                                          // class style 0x50000007, but sets bit 1, resulting with style 0x50000001
+}

Added: llvm/trunk/test/tools/llvm-rc/not-expr.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-rc/not-expr.test?rev=348363&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-rc/not-expr.test (added)
+++ llvm/trunk/test/tools/llvm-rc/not-expr.test Wed Dec  5 05:22:56 2018
@@ -0,0 +1,20 @@
+; RUN: llvm-rc /FO %t %p/Inputs/not-expr.rc
+; RUN: llvm-readobj %t | FileCheck %s --check-prefix=NOTEXPR
+
+; NOTEXPR: Resource type (int): 5
+; NOTEXPR-NEXT: Resource name (string): NOT
+; NOTEXPR-NEXT: Data version: 0
+; NOTEXPR-NEXT: Memory flags: 0x1030
+; NOTEXPR-NEXT: Language ID: 1033
+; NOTEXPR-NEXT: Version (major): 0
+; NOTEXPR-NEXT: Version (minor): 0
+; NOTEXPR-NEXT: Characteristics: 0
+; NOTEXPR-NEXT: Data size: 96
+; NOTEXPR-NEXT: Data: (
+; NOTEXPR-NEXT:   0000: 0100FFFF 04000000 F7FFFFFF 03FF00FF  |................|
+; NOTEXPR-NEXT:   0010: 02000000 02003C00 03000000 00000000  |......<.........|
+; NOTEXPR-NEXT:   0020: 00000000 00000000 22000050 00000A00  |........"..P....|
+; NOTEXPR-NEXT:   0030: 00000000 00000000 FFFF8000 00000000  |................|
+; NOTEXPR-NEXT:   0040: 00000000 00000000 01000050 00000000  |...........P....|
+; NOTEXPR-NEXT:   0050: 00000000 01000000 FFFF8000 00000000  |................|
+; NOTEXPR-NEXT: )

Modified: llvm/trunk/tools/llvm-rc/ResourceFileWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceFileWriter.cpp?rev=348363&r1=348362&r2=348363&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceFileWriter.cpp (original)
+++ llvm/trunk/tools/llvm-rc/ResourceFileWriter.cpp Wed Dec  5 05:22:56 2018
@@ -987,7 +987,8 @@ Error ResourceFileWriter::writeSingleDia
   padStream(sizeof(uint32_t));
 
   auto TypeInfo = Control::SupportedCtls.lookup(Ctl.Type);
-  uint32_t CtlStyle = TypeInfo.Style | Ctl.Style.getValueOr(0);
+  IntWithNotMask CtlStyle(TypeInfo.Style);
+  CtlStyle |= Ctl.Style.getValueOr(RCInt(0));
   uint32_t CtlExtStyle = Ctl.ExtStyle.getValueOr(0);
 
   // DIALOG(EX) item header prefix.
@@ -995,7 +996,7 @@ Error ResourceFileWriter::writeSingleDia
     struct {
       ulittle32_t Style;
       ulittle32_t ExtStyle;
-    } Prefix{ulittle32_t(CtlStyle), ulittle32_t(CtlExtStyle)};
+    } Prefix{ulittle32_t(CtlStyle.getValue()), ulittle32_t(CtlExtStyle)};
     writeObject(Prefix);
   } else {
     struct {
@@ -1003,7 +1004,7 @@ Error ResourceFileWriter::writeSingleDia
       ulittle32_t ExtStyle;
       ulittle32_t Style;
     } Prefix{ulittle32_t(Ctl.HelpID.getValueOr(0)), ulittle32_t(CtlExtStyle),
-             ulittle32_t(CtlStyle)};
+             ulittle32_t(CtlStyle.getValue())};
     writeObject(Prefix);
   }
 

Modified: llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp?rev=348363&r1=348362&r2=348363&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptParser.cpp Wed Dec  5 05:22:56 2018
@@ -114,16 +114,23 @@ void RCParser::consume() {
 
 // An integer description might consist of a single integer or
 // an arithmetic expression evaluating to the integer. The expressions
-// can contain the following tokens: <int> ( ) + - | & ~. Their meaning
-// is the same as in C++.
+// can contain the following tokens: <int> ( ) + - | & ~ not. Their meaning
+// is the same as in C++ except for 'not' expression.
 // The operators in the original RC implementation have the following
 // precedence:
-//   1) Unary operators (- ~),
+//   1) Unary operators (- ~ not),
 //   2) Binary operators (+ - & |), with no precedence.
 //
+// 'not' expression is mostly useful for style values. It evaluates to 0,
+// but value given to the operator is stored separately from integer value.
+// It's mostly useful for control style expressions and causes bits from
+// default control style to be excluded from generated style. For binary
+// operators the mask from the right operand is applied to the left operand
+// and masks from both operands are combined in operator result.
+//
 // The following grammar is used to parse the expressions Exp1:
 //   Exp1 ::= Exp2 || Exp1 + Exp2 || Exp1 - Exp2 || Exp1 | Exp2 || Exp1 & Exp2
-//   Exp2 ::= -Exp2 || ~Exp2 || Int || (Exp1).
+//   Exp2 ::= -Exp2 || ~Exp2 || not Expr2 || Int || (Exp1).
 // (More conveniently, Exp1 is a non-empty sequence of Exp2 expressions,
 // separated by binary operators.)
 //
@@ -139,12 +146,15 @@ void RCParser::consume() {
 //    1 => 01 00, -1 => ff ff, --1 => 01 00, ---1 => ff ff;
 //    1 => 01 00, ~1 => fe ff, ~~1 => 01 00, ~~~1 => fe ff.
 
-Expected<RCInt> RCParser::readInt() { return parseIntExpr1(); }
+Expected<RCInt> RCParser::readInt() {
+  ASSIGN_OR_RETURN(Value, parseIntExpr1());
+  return (*Value).getValue();
+}
 
-Expected<RCInt> RCParser::parseIntExpr1() {
+Expected<IntWithNotMask> RCParser::parseIntExpr1() {
   // Exp1 ::= Exp2 || Exp1 + Exp2 || Exp1 - Exp2 || Exp1 | Exp2 || Exp1 & Exp2.
   ASSIGN_OR_RETURN(FirstResult, parseIntExpr2());
-  RCInt Result = *FirstResult;
+  IntWithNotMask Result = *FirstResult;
 
   while (!isEof() && look().isBinaryOp()) {
     auto OpToken = read();
@@ -175,8 +185,8 @@ Expected<RCInt> RCParser::parseIntExpr1(
   return Result;
 }
 
-Expected<RCInt> RCParser::parseIntExpr2() {
-  // Exp2 ::= -Exp2 || ~Exp2 || Int || (Exp1).
+Expected<IntWithNotMask> RCParser::parseIntExpr2() {
+  // Exp2 ::= -Exp2 || ~Exp2 || not Expr2 || Int || (Exp1).
   static const char ErrorMsg[] = "'-', '~', integer or '('";
 
   if (isEof())
@@ -205,6 +215,13 @@ Expected<RCInt> RCParser::parseIntExpr2(
     return *Result;
   }
 
+  case Kind::Identifier: {
+    if (!read().value().equals_lower("not"))
+      return getExpectedError(ErrorMsg, true);
+    ASSIGN_OR_RETURN(Result, parseIntExpr2());
+    return IntWithNotMask(0, (*Result).getValue());
+  }
+
   default:
     return getExpectedError(ErrorMsg);
   }
@@ -539,13 +556,13 @@ Expected<Control> RCParser::parseControl
   RETURN_IF_ERROR(consumeType(Kind::Comma));
 
   IntOrString Class;
-  Optional<uint32_t> Style;
+  Optional<IntWithNotMask> Style;
   if (ClassUpper == "CONTROL") {
     // CONTROL text, id, class, style, x, y, width, height [, exstyle] [, helpID]
     ASSIGN_OR_RETURN(ClassStr, readString());
     RETURN_IF_ERROR(consumeType(Kind::Comma));
     Class = *ClassStr;
-    ASSIGN_OR_RETURN(StyleVal, readInt());
+    ASSIGN_OR_RETURN(StyleVal, parseIntExpr1());
     RETURN_IF_ERROR(consumeType(Kind::Comma));
     Style = *StyleVal;
   } else {
@@ -557,7 +574,7 @@ Expected<Control> RCParser::parseControl
 
   if (ClassUpper != "CONTROL") {
     if (consumeOptionalType(Kind::Comma)) {
-      ASSIGN_OR_RETURN(Val, readInt());
+      ASSIGN_OR_RETURN(Val, parseIntExpr1());
       Style = *Val;
     }
   }

Modified: llvm/trunk/tools/llvm-rc/ResourceScriptParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptParser.h?rev=348363&r1=348362&r2=348363&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptParser.h (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptParser.h Wed Dec  5 05:22:56 2018
@@ -89,8 +89,8 @@ private:
   Expected<IntOrString> readTypeOrName();  // Parse an integer or an identifier.
 
   // Helper integer expression parsing methods.
-  Expected<RCInt> parseIntExpr1();
-  Expected<RCInt> parseIntExpr2();
+  Expected<IntWithNotMask> parseIntExpr1();
+  Expected<IntWithNotMask> parseIntExpr2();
 
   // Advance the state by one, discarding the current token.
   // If the discarded token had an incorrect type, fail.

Modified: llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp?rev=348363&r1=348362&r2=348363&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptStmt.cpp Wed Dec  5 05:22:56 2018
@@ -151,7 +151,7 @@ raw_ostream &Control::log(raw_ostream &O
      << ", loc: (" << X << ", " << Y << "), size: [" << Width << ", " << Height
      << "]";
   if (Style)
-    OS << ", style: " << *Style;
+    OS << ", style: " << (*Style).getValue();
   if (ExtStyle)
     OS << ", ext. style: " << *ExtStyle;
   if (HelpID)

Modified: llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h?rev=348363&r1=348362&r2=348363&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h (original)
+++ llvm/trunk/tools/llvm-rc/ResourceScriptStmt.h Wed Dec  5 05:22:56 2018
@@ -67,6 +67,59 @@ public:
   }
 };
 
+class IntWithNotMask {
+private:
+  RCInt Value;
+  int32_t NotMask;
+
+public:
+  IntWithNotMask() : IntWithNotMask(RCInt(0)) {}
+  IntWithNotMask(RCInt Value, int32_t NotMask = 0) : Value(Value), NotMask(NotMask) {}
+
+  RCInt getValue() const {
+    return Value;
+  }
+
+  uint32_t getNotMask() const {
+    return NotMask;
+  }
+
+  IntWithNotMask &operator+=(const IntWithNotMask &Rhs) {
+    Value &= ~Rhs.NotMask;
+    Value += Rhs.Value;
+    NotMask |= Rhs.NotMask;
+    return *this;
+  }
+
+  IntWithNotMask &operator-=(const IntWithNotMask &Rhs) {
+    Value &= ~Rhs.NotMask;
+    Value -= Rhs.Value;
+    NotMask |= Rhs.NotMask;
+    return *this;
+  }
+
+  IntWithNotMask &operator|=(const IntWithNotMask &Rhs) {
+    Value &= ~Rhs.NotMask;
+    Value |= Rhs.Value;
+    NotMask |= Rhs.NotMask;
+    return *this;
+  }
+
+  IntWithNotMask &operator&=(const IntWithNotMask &Rhs) {
+    Value &= ~Rhs.NotMask;
+    Value &= Rhs.Value;
+    NotMask |= Rhs.NotMask;
+    return *this;
+  }
+
+  IntWithNotMask operator-() const { return {-Value, NotMask}; }
+  IntWithNotMask operator~() const { return {~Value, 0}; }
+
+  friend raw_ostream &operator<<(raw_ostream &OS, const IntWithNotMask &Int) {
+    return OS << Int.Value;
+  }
+};
+
 // A class holding a name - either an integer or a reference to the string.
 class IntOrString {
 private:
@@ -556,7 +609,8 @@ public:
   StringRef Type;
   IntOrString Title;
   uint32_t ID, X, Y, Width, Height;
-  Optional<uint32_t> Style, ExtStyle, HelpID;
+  Optional<IntWithNotMask> Style;
+  Optional<uint32_t> ExtStyle, HelpID;
   IntOrString Class;
 
   // Control classes as described in DLGITEMTEMPLATEEX documentation.
@@ -580,7 +634,7 @@ public:
 
   Control(StringRef CtlType, IntOrString CtlTitle, uint32_t CtlID,
           uint32_t PosX, uint32_t PosY, uint32_t ItemWidth, uint32_t ItemHeight,
-          Optional<uint32_t> ItemStyle, Optional<uint32_t> ExtItemStyle,
+          Optional<IntWithNotMask> ItemStyle, Optional<uint32_t> ExtItemStyle,
           Optional<uint32_t> CtlHelpID, IntOrString CtlClass)
       : Type(CtlType), Title(CtlTitle), ID(CtlID), X(PosX), Y(PosY),
         Width(ItemWidth), Height(ItemHeight), Style(ItemStyle),




More information about the llvm-commits mailing list