Index: llvm/test/tools/llvm-rc/Inputs/tag-user.rc =================================================================== --- /dev/null +++ llvm/test/tools/llvm-rc/Inputs/tag-user.rc @@ -0,0 +1,8 @@ +500 500 { + 1, 2, 3, 4, 5, "data", L"wide data", 0xABCD, 0xABCDEF01L +} + +NAME1 NAME2 {} + +600 600 "bitmap.bmp" + Index: llvm/test/tools/llvm-rc/tag-user.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-rc/tag-user.test @@ -0,0 +1,53 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: cp %p/Inputs/bitmap.bmp . +; RUN: llvm-rc /FO %t/tag-user.res %p/Inputs/tag-user.rc +; RUN: llvm-readobj %t/tag-user.res | FileCheck %s + +; CHECK: Resource type (int): 500 +; CHECK-NEXT: Resource name (int): 500 +; CHECK-NEXT: Data version: 0 +; CHECK-NEXT: Memory flags: 0x30 +; CHECK-NEXT: Language ID: 1033 +; CHECK-NEXT: Version (major): 0 +; CHECK-NEXT: Version (minor): 0 +; CHECK-NEXT: Characteristics: 0 +; CHECK-NEXT: Data size: 38 +; CHECK-NEXT: Data: ( +; CHECK-NEXT: 0000: 01000200 03000400 05006461 74617700 |..........dataw.| +; CHECK-NEXT: 0010: 69006400 65002000 64006100 74006100 |i.d.e. .d.a.t.a.| +; CHECK-NEXT: 0020: CDAB01EF CDAB |......| +; CHECK-NEXT: ) + +; CHECK-DAG: Resource type (string): NAME2 +; CHECK-NEXT: Resource name (string): NAME1 +; CHECK-NEXT: Data version: 0 +; CHECK-NEXT: Memory flags: 0x30 +; CHECK-NEXT: Language ID: 1033 +; CHECK-NEXT: Version (major): 0 +; CHECK-NEXT: Version (minor): 0 +; CHECK-NEXT: Characteristics: 0 +; CHECK-NEXT: Data size: 0 +; CHECK-NEXT: Data:: () + +; CHECK-DAG: Resource type (int): 600 +; CHECK-NEXT: Resource name (int): 600 +; CHECK-NEXT: Data version: 0 +; CHECK-NEXT: Memory flags: 0x30 +; CHECK-NEXT: Language ID: 1033 +; CHECK-NEXT: Version (major): 0 +; CHECK-NEXT: Version (minor): 0 +; CHECK-NEXT: Characteristics: 0 +; CHECK-NEXT: Data size: 110 +; CHECK-NEXT: Data: ( +; CHECK-NEXT: 0000: 424D6E00 00000000 00003600 00002800 |BMn.......6...(.| +; CHECK-NEXT: 0010: 00000200 00000700 00000100 18000000 |................| +; CHECK-NEXT: 0020: 00003800 00000000 00000000 00000000 |..8.............| +; CHECK-NEXT: 0030: 00000000 00005BB3 855BB385 0000FFFF |......[..[......| +; CHECK-NEXT: 0040: FFFFFFFF 0000FFFF FFFFFFFF 0000FFFF |................| +; CHECK-NEXT: 0050: FFFFFFFF 00005BB3 85FFFFFF 0000FFFF |......[.........| +; CHECK-NEXT: 0060: FF0EC9FF 0000241C EDFFFFFF 0000 |......$.......| +; CHECK-NEXT: ) + + Index: llvm/tools/llvm-rc/ResourceFileWriter.h =================================================================== --- llvm/tools/llvm-rc/ResourceFileWriter.h +++ llvm/tools/llvm-rc/ResourceFileWriter.h @@ -38,6 +38,7 @@ Error visitMenuResource(const RCResource *) override; Error visitVersionInfoResource(const RCResource *) override; Error visitStringTableResource(const RCResource *) override; + Error visitUserDefinedResource(const RCResource *) override; Error visitCaptionStmt(const CaptionStmt *) override; Error visitCharacteristicsStmt(const CharacteristicsStmt *) override; @@ -127,6 +128,9 @@ Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle, uint16_t StringID, StringRef String); + // User defined resource + Error writeUserDefinedBody(const RCResource *); + // VersionInfoResource Error writeVersionInfoBody(const RCResource *); Error writeVersionInfoBlock(const VersionInfoBlock &); Index: llvm/tools/llvm-rc/ResourceFileWriter.cpp =================================================================== --- llvm/tools/llvm-rc/ResourceFileWriter.cpp +++ llvm/tools/llvm-rc/ResourceFileWriter.cpp @@ -298,6 +298,9 @@ return Error::success(); } +Error ResourceFileWriter::visitUserDefinedResource(const RCResource *Res) { + return writeResource(Res, &ResourceFileWriter::writeUserDefinedBody); +} Error ResourceFileWriter::visitVersionInfoResource(const RCResource *Res) { return writeResource(Res, &ResourceFileWriter::writeVersionInfoBody); @@ -1050,6 +1053,43 @@ return Error::success(); } +// --- UserDefinedResource helpers. --- // + +Error ResourceFileWriter::writeUserDefinedBody(const RCResource *Base) { + auto *Res = cast(Base); + + if (Res->IsFileResource) + return appendFile(Res->FileLoc); + + for (auto &Elem : Res->Contents) { + if (Elem.isInt()) { + RETURN_IF_ERROR( + checkRCInt(Elem.getInt(), "Number in user-defined resource")); + writeRCInt(Elem.getInt()); + continue; + } + + SmallVector ProcessedString; + bool IsLongString; + RETURN_IF_ERROR(processString(Elem.getString(), + NullHandlingMethod::UserResource, + IsLongString, ProcessedString)); + + for (auto Ch : ProcessedString) { + if (IsLongString) { + writeObject(ulittle16_t(Ch)); + continue; + } + + RETURN_IF_ERROR(checkNumberFits( + Ch, "Character in narrow string in user-defined resoutce")); + writeObject(uint8_t(Ch)); + } + } + + return Error::success(); +} + // --- VersionInfoResourceResource helpers. --- // Error ResourceFileWriter::writeVersionInfoBlock(const VersionInfoBlock &Blk) { Index: llvm/tools/llvm-rc/ResourceScriptStmt.h =================================================================== --- llvm/tools/llvm-rc/ResourceScriptStmt.h +++ llvm/tools/llvm-rc/ResourceScriptStmt.h @@ -594,18 +594,29 @@ // * a link to the file, e.g. NAME TYPE "filename", // * or contains a list of integers and strings, e.g. NAME TYPE {1, "a", 2}. class UserDefinedResource : public RCResource { +public: IntOrString Type; StringRef FileLoc; std::vector Contents; bool IsFileResource; -public: UserDefinedResource(IntOrString ResourceType, StringRef FileLocation) : Type(ResourceType), FileLoc(FileLocation), IsFileResource(true) {} UserDefinedResource(IntOrString ResourceType, std::vector &&Data) : Type(ResourceType), Contents(std::move(Data)), IsFileResource(false) {} raw_ostream &log(raw_ostream &) const override; + IntOrString getResourceType() const override { return Type; } + Twine getResourceTypeName() const override { return Type; } + uint16_t getMemoryFlags() const override { return MfPure | MfMoveable; } + + Error visit(Visitor *V) const override { + return V->visitUserDefinedResource(this); + } + ResourceKind getKind() const override { return RkUser; } + static bool classof(const RCResource *Res) { + return Res->getKind() == RkUser; + } }; // -- VERSIONINFO resource and its helper classes -- Index: llvm/tools/llvm-rc/ResourceVisitor.h =================================================================== --- llvm/tools/llvm-rc/ResourceVisitor.h +++ llvm/tools/llvm-rc/ResourceVisitor.h @@ -38,6 +38,7 @@ virtual Error visitIconResource(const RCResource *) = 0; virtual Error visitMenuResource(const RCResource *) = 0; virtual Error visitStringTableResource(const RCResource *) = 0; + virtual Error visitUserDefinedResource(const RCResource *) = 0; virtual Error visitVersionInfoResource(const RCResource *) = 0; virtual Error visitCaptionStmt(const CaptionStmt *) = 0;