diff options
author | Martin Storsjo <martin@martin.st> | 2018-12-05 13:22:56 +0000 |
---|---|---|
committer | Martin Storsjo <martin@martin.st> | 2018-12-05 13:22:56 +0000 |
commit | d0afe724d1f5ca3e0a46e75849450a934ffa5ef2 (patch) | |
tree | 25e93ff9bf602eb78d53188e8b625406c173b4d7 | |
parent | 8fdaf5c915de88bb7026afb709460a0d6bf81162 (diff) | |
download | bcm5719-llvm-d0afe724d1f5ca3e0a46e75849450a934ffa5ef2.tar.gz bcm5719-llvm-d0afe724d1f5ca3e0a46e75849450a934ffa5ef2.zip |
[llvm-rc] Support not expressions.
Patch by Jacek Caban!
Differential Revision: https://reviews.llvm.org/D55242
llvm-svn: 348363
-rw-r--r-- | llvm/test/tools/llvm-rc/Inputs/not-expr.rc | 17 | ||||
-rw-r--r-- | llvm/test/tools/llvm-rc/not-expr.test | 20 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceFileWriter.cpp | 7 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptParser.cpp | 41 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptParser.h | 4 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptStmt.cpp | 2 | ||||
-rw-r--r-- | llvm/tools/llvm-rc/ResourceScriptStmt.h | 58 |
7 files changed, 129 insertions, 20 deletions
diff --git a/llvm/test/tools/llvm-rc/Inputs/not-expr.rc b/llvm/test/tools/llvm-rc/Inputs/not-expr.rc new file mode 100644 index 00000000000..1b5c8177393 --- /dev/null +++ b/llvm/test/tools/llvm-rc/Inputs/not-expr.rc @@ -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 +} diff --git a/llvm/test/tools/llvm-rc/not-expr.test b/llvm/test/tools/llvm-rc/not-expr.test new file mode 100644 index 00000000000..c60223425c7 --- /dev/null +++ b/llvm/test/tools/llvm-rc/not-expr.test @@ -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: ) diff --git a/llvm/tools/llvm-rc/ResourceFileWriter.cpp b/llvm/tools/llvm-rc/ResourceFileWriter.cpp index e69d4793dd1..7fe95669083 100644 --- a/llvm/tools/llvm-rc/ResourceFileWriter.cpp +++ b/llvm/tools/llvm-rc/ResourceFileWriter.cpp @@ -987,7 +987,8 @@ Error ResourceFileWriter::writeSingleDialogControl(const Control &Ctl, 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::writeSingleDialogControl(const Control &Ctl, 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::writeSingleDialogControl(const Control &Ctl, 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); } diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.cpp b/llvm/tools/llvm-rc/ResourceScriptParser.cpp index 09c88ff879a..c66fc4fc2e7 100644 --- a/llvm/tools/llvm-rc/ResourceScriptParser.cpp +++ b/llvm/tools/llvm-rc/ResourceScriptParser.cpp @@ -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; } } diff --git a/llvm/tools/llvm-rc/ResourceScriptParser.h b/llvm/tools/llvm-rc/ResourceScriptParser.h index 4f047f34fc0..20d8ff9624d 100644 --- a/llvm/tools/llvm-rc/ResourceScriptParser.h +++ b/llvm/tools/llvm-rc/ResourceScriptParser.h @@ -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. diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.cpp b/llvm/tools/llvm-rc/ResourceScriptStmt.cpp index 325707226c4..7b8b0def4c9 100644 --- a/llvm/tools/llvm-rc/ResourceScriptStmt.cpp +++ b/llvm/tools/llvm-rc/ResourceScriptStmt.cpp @@ -151,7 +151,7 @@ raw_ostream &Control::log(raw_ostream &OS) const { << ", loc: (" << X << ", " << Y << "), size: [" << Width << ", " << Height << "]"; if (Style) - OS << ", style: " << *Style; + OS << ", style: " << (*Style).getValue(); if (ExtStyle) OS << ", ext. style: " << *ExtStyle; if (HelpID) diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.h b/llvm/tools/llvm-rc/ResourceScriptStmt.h index 0051f83fcf2..3ba1f6619eb 100644 --- a/llvm/tools/llvm-rc/ResourceScriptStmt.h +++ b/llvm/tools/llvm-rc/ResourceScriptStmt.h @@ -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), |