Index: llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor-bad-offset.rc
===================================================================
--- /dev/null
+++ llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor-bad-offset.rc
@@ -0,0 +1,2 @@
+50 CURSOR "cursor-bad-offset.cur"
+
Index: llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor-bad-type.rc
===================================================================
--- /dev/null
+++ llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor-bad-type.rc
@@ -0,0 +1 @@
+100 ICON "cursor.cur"
Index: llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor-eof.rc
===================================================================
--- /dev/null
+++ llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor-eof.rc
@@ -0,0 +1 @@
+72 CURSOR "cursor-eof.cur"
Index: llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor-nonexistent.rc
===================================================================
--- /dev/null
+++ llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor-nonexistent.rc
@@ -0,0 +1 @@
+500 CURSOR "this-file-does-not-exist.cur"
Index: llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor-nonsense.rc
===================================================================
--- /dev/null
+++ llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor-nonsense.rc
@@ -0,0 +1 @@
+1 ICON "tag-icon-cursor-nonsense.rc"
Index: llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor.rc
===================================================================
--- /dev/null
+++ llvm/test/tools/llvm-rc/Inputs/tag-icon-cursor.rc
@@ -0,0 +1,6 @@
+4464 CURSOR "cursor.cur"
+4465 CUrsoR "cursor-8.cur"
+100 ICON "icon-old.ico"
+4466 cURSOR "cursor-32.cur"
+100 ICON "icon-new.ico"
+100 iCon "icon-png.ico"
Index: llvm/test/tools/llvm-rc/tag-icon-cursor.test
===================================================================
--- /dev/null
+++ llvm/test/tools/llvm-rc/tag-icon-cursor.test
@@ -0,0 +1,353 @@
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: cp %p/Inputs/icon*.ico .
+; RUN: cp %p/Inputs/cursor*.cur .
+; RUN: cp %p/Inputs/tag-icon-cursor-nonsense.rc .
+
+; RUN: llvm-rc /FO %t/tag-icon-cursor.res %p/Inputs/tag-icon-cursor.rc
+; RUN: llvm-readobj %t/tag-icon-cursor.res | FileCheck %s
+
+; CHECK: Resource type (int): 1
+; CHECK-NEXT: Resource name (int): 1
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 308
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 0A000B00 28000000 20000000 40000000  |....(... ...@...|
+; CHECK-NEXT:   0010: 01000100 00000000 80000000 00000000  |................|
+; CHECK-NEXT:   0020: 00000000 02000000 00000000 00000000  |................|
+; (...)
+; CHECK-DAG:    0110: FFFFFFFF FFFFFFFF FFFFFFFF F3CFFFFF  |................|
+; CHECK-NEXT:   0120: F3CFFFFF FFFFFFFF FFFFFFFF FFFFFFFF  |................|
+; CHECK-NEXT:   0130: FFFFFFFF                             |....|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 12
+; CHECK-NEXT: Resource name (int): 4464
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1030
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 20
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 00000200 01002000 40000100 01003401  |...... .@.....4.|
+; CHECK-NEXT:   0010: 00000100                             |....|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 1
+; CHECK-NEXT: Resource name (int): 2
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 2220
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 01000C00 28000000 20000000 40000000  |....(... ...@...|
+; CHECK-NEXT:   0010: 01000800 00000000 00040000 00000000  |................|
+; CHECK-NEXT:   0020: 00000000 00010000 00000000 00000000  |................|
+; (...)
+; CHECK-DAG:    0880: C001FFFF F557FFFF F557FFFF F551FFFF  |.....W...W...Q..|
+; CHECK-NEXT:   0890: C005FFFF B557FFFF F557FFFF F557FFFF  |.....W...W...W..|
+; CHECK-NEXT:   08A0: C001FFFF F557FFFF FFFFFFFF           |.....W......|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 12
+; CHECK-NEXT: Resource name (int): 4465
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1030
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 20
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 00000200 01002000 40000100 0800AC08  |...... .@.......|
+; CHECK-NEXT:   0010: 00000200                             |....|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 3
+; CHECK-NEXT: Resource name (int): 3
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 1128
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 28000000 10000000 20000000 01002000  |(....... ..... .|
+; CHECK-NEXT:   0010: 00000000 00040000 C30E0000 C30E0000  |................|
+; CHECK-NEXT:   0020: 00000000 00000000 FFFFFFFF FFFFFFFF  |................|
+; (...)
+; CHECK-DAG:    0440: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   0450: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   0460: 00000000 00000000                    |........|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 3
+; CHECK-NEXT: Resource name (int): 4
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 2440
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 28000000 18000000 30000000 01002000  |(.......0..... .|
+; CHECK-NEXT:   0010: 00000000 00090000 C30E0000 C30E0000  |................|
+; CHECK-NEXT:   0020: 00000000 00000000 FFFFFFFF FFFFFFFF  |................|
+; (...)
+; CHECK-DAG:    0960: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   0970: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   0980: 00000000 00000000                    |........|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 3
+; CHECK-NEXT: Resource name (int): 5
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 4264
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 28000000 20000000 40000000 01002000  |(... ...@..... .|
+; CHECK-NEXT:   0010: 00000000 00100000 C30E0000 C30E0000  |................|
+; CHECK-NEXT:   0020: 00000000 00000000 FFFFFFFF FFFFFFFF  |................|
+; (...)
+; CHECK-DAG:    1080: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   1090: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   10A0: 00000000 00000000                    |........|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 3
+; CHECK-NEXT: Resource name (int): 6
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 9640
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 28000000 30000000 60000000 01002000  |(...0...`..... .|
+; CHECK-NEXT:   0010: 00000000 00240000 C30E0000 C30E0000  |.....$..........|
+; CHECK-NEXT:   0020: 00000000 00000000 FFFFFFFF FFFFFFFF  |................|
+; (...)
+; CHECK-DAG:    2580: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   2590: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   25A0: 00000000 00000000                    |........|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 14
+; CHECK-NEXT: Resource name (int): 100
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1030
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 62
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 00000100 04001010 00000100 20006804  |............ .h.|
+; CHECK-NEXT:   0010: 00000300 18180000 01002000 88090000  |.......... .....|
+; CHECK-NEXT:   0020: 04002020 00000100 2000A810 00000500  |..  .... .......|
+; CHECK-NEXT:   0030: 30300000 01002000 A8250000 0600      |00.... ..%....|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 1
+; CHECK-NEXT: Resource name (int): 7
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 4268
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 0D000600 28000000 20000000 40000000  |....(... ...@...|
+; CHECK-NEXT:   0010: 01002000 00000000 00100000 00000000  |.. .............|
+; CHECK-NEXT:   0020: 00000000 00000000 00000000 00000000  |................|
+; (...)
+; CHECK-DAG:    1080: E027FFFF C3F3FFFF FFFFFFFF FFFFFFFF  |.'..............|
+; CHECK-NEXT:   1090: FFFFFFFF F3CFFFFF F3CFFFFF FFFFFFFF  |................|
+; CHECK-NEXT:   10A0: FFFFFFFF FFFFFFFF FFFFFFFF           |............|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 12
+; CHECK-NEXT: Resource name (int): 4466
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1030
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 20
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 00000200 01002000 40000100 2000AC10  |...... .@... ...|
+; CHECK-NEXT:   0010: 00000700                             |....|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 3
+; CHECK-NEXT: Resource name (int): 8
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 1128
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 28000000 10000000 20000000 01002000  |(....... ..... .|
+; CHECK-NEXT:   0010: 00000000 00040000 C30E0000 C30E0000  |................|
+; CHECK-NEXT:   0020: 00000000 00000000 FFFFFFFF FFFFFFFF  |................|
+; (...)
+; CHECK-DAG:    0440: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   0450: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   0460: 00000000 00000000                    |........|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 3
+; CHECK-NEXT: Resource name (int): 9
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 2440
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 28000000 18000000 30000000 01002000  |(.......0..... .|
+; CHECK-NEXT:   0010: 00000000 00090000 C30E0000 C30E0000  |................|
+; CHECK-NEXT:   0020: 00000000 00000000 FFFFFFFF FFFFFFFF  |................|
+; (...)
+; CHECK-DAG:    0960: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   0970: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   0980: 00000000 00000000                    |........|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 3
+; CHECK-NEXT: Resource name (int): 10
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 4264
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 28000000 20000000 40000000 01002000  |(... ...@..... .|
+; CHECK-NEXT:   0010: 00000000 00100000 C30E0000 C30E0000  |................|
+; CHECK-NEXT:   0020: 00000000 00000000 FFFFFFFF FFFFFFFF  |................|
+; (...)
+; CHECK-DAG:    1080: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   1090: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   10A0: 00000000 00000000                    |........|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 3
+; CHECK-NEXT: Resource name (int): 11
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 9640
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 28000000 30000000 60000000 01002000  |(...0...`..... .|
+; CHECK-NEXT:   0010: 00000000 00240000 C30E0000 C30E0000  |.....$..........|
+; CHECK-NEXT:   0020: 00000000 00000000 FFFFFFFF FFFFFFFF  |................|
+; (...)
+; CHECK-DAG:    2580: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   2590: 00000000 00000000 00000000 00000000  |................|
+; CHECK-NEXT:   25A0: 00000000 00000000                    |........|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 14
+; CHECK-NEXT: Resource name (int): 100
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1030
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 62
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 00000100 04001010 00000100 20006804  |............ .h.|
+; CHECK-NEXT:   0010: 00000800 18180000 01002000 88090000  |.......... .....|
+; CHECK-NEXT:   0020: 09002020 00000100 2000A810 00000A00  |..  .... .......|
+; CHECK-NEXT:   0030: 30300000 01002000 A8250000 0B00      |00.... ..%....|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 3
+; CHECK-NEXT: Resource name (int): 12
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1010
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 82
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 89504E47 0D0A1A0A 0000000D 49484452  |.PNG........IHDR|
+; CHECK-NEXT:   0010: 00000010 00000010 08060000 001FF3FF  |................|
+; CHECK-NEXT:   0020: 61000000 19494441 5438CB63 FC0F040C  |a....IDAT8.c....|
+; CHECK-NEXT:   0030: 1400C651 03460D18 3560B818 0000251F  |...Q.F..5`....%.|
+; CHECK-NEXT:   0040: 3FD1D6DC 546E0000 00004945 4E44AE42  |?...Tn....IEND.B|
+; CHECK-NEXT:   0050: 6082                                 |`.|
+; CHECK-NEXT: )
+
+; CHECK-DAG:  Resource type (int): 14
+; CHECK-NEXT: Resource name (int): 100
+; CHECK-NEXT: Data version: 0
+; CHECK-NEXT: Memory flags: 0x1030
+; CHECK-NEXT: Language ID: 1033
+; CHECK-NEXT: Version (major): 0
+; CHECK-NEXT: Version (minor): 0
+; CHECK-NEXT: Characteristics: 0
+; CHECK-NEXT: Data size: 20
+; CHECK-NEXT: Data: (
+; CHECK-NEXT:   0000: 00000100 01001010 00000100 20005200  |............ .R.|
+; CHECK-NEXT:   0010: 00000C00                             |....|
+; CHECK-NEXT: )
+
+
+; RUN: not llvm-rc /FO %t/1 %p/Inputs/tag-icon-cursor-nonexistent.rc 2>&1 | FileCheck %s --check-prefix NOFILE
+; NOFILE: llvm-rc: Error in CURSOR statement (ID 500):
+; NOFILE-NEXT: Error opening cursor 'this-file-does-not-exist.cur':
+
+
+; RUN: not llvm-rc /FO %t/1 %p/Inputs/tag-icon-cursor-nonsense.rc 2>&1 | FileCheck %s --check-prefix NONSENSE
+
+; NONSENSE: llvm-rc: Error in ICON statement (ID 1):
+; NONSENSE-NEXT: Incorrect icon/cursor Reserved field; should be 0.
+
+
+; RUN: not llvm-rc /FO %t/1 %p/Inputs/tag-icon-cursor-eof.rc 2>&1 | FileCheck %s --check-prefix EOF
+
+; EOF: llvm-rc: Error in CURSOR statement (ID 72):
+; EOF-NEXT: Stream Error: The stream is too short to perform the requested operation.
+
+
+; RUN: not llvm-rc /FO %t/1 %p/Inputs/tag-icon-cursor-bad-offset.rc 2>&1 | FileCheck %s --check-prefix OFFSET
+
+; OFFSET: llvm-rc: Error in CURSOR statement (ID 50):
+; OFFSET-NEXT: Stream Error: The specified offset is invalid for the current stream.
+
+
+; RUN: not llvm-rc /FO %t/1 %p/Inputs/tag-icon-cursor-bad-type.rc 2>&1 | FileCheck %s --check-prefix BADTYPE
+
+; BADTYPE: llvm-rc: Error in ICON statement (ID 100):
+; BADTYPE-NEXT: Incorrect icon/cursor ResType field; should be 1.
Index: llvm/tools/llvm-rc/ResourceFileWriter.h
===================================================================
--- llvm/tools/llvm-rc/ResourceFileWriter.h
+++ llvm/tools/llvm-rc/ResourceFileWriter.h
@@ -25,14 +25,16 @@
 class ResourceFileWriter : public Visitor {
 public:
   ResourceFileWriter(std::unique_ptr<raw_fd_ostream> Stream)
-      : FS(std::move(Stream)) {
+      : FS(std::move(Stream)), IconCursorID(1) {
     assert(FS && "Output stream needs to be provided to the serializator");
   }
 
   Error visitNullResource(const RCResource *) override;
   Error visitAcceleratorsResource(const RCResource *) override;
+  Error visitCursorResource(const RCResource *) override;
   Error visitDialogResource(const RCResource *) override;
   Error visitHTMLResource(const RCResource *) override;
+  Error visitIconResource(const RCResource *) override;
   Error visitMenuResource(const RCResource *) override;
 
   Error visitCaptionStmt(const CaptionStmt *) override;
@@ -76,6 +78,13 @@
                                bool IsLastItem);
   Error writeAcceleratorsBody(const RCResource *);
 
+  // CursorResource and IconResource
+  Error visitIconOrCursorResource(const RCResource *);
+  Error visitIconOrCursorGroup(const RCResource *);
+  Error visitSingleIconOrCursor(const RCResource *);
+  Error writeSingleIconOrCursorBody(const RCResource *);
+  Error writeIconOrCursorGroupBody(const RCResource *);
+
   // DialogResource
   Error writeSingleDialogControl(const Control &, bool IsExtended);
   Error writeDialogBody(const RCResource *);
@@ -120,6 +129,10 @@
   Error appendFile(StringRef Filename);
 
   void padStream(uint64_t Length);
+
+  // Icon and cursor IDs are allocated starting from 1 and increasing for
+  // each icon/cursor dumped. This maintains the current ID to be allocated.
+  uint16_t IconCursorID;
 };
 
 } // namespace rc
Index: llvm/tools/llvm-rc/ResourceFileWriter.cpp
===================================================================
--- llvm/tools/llvm-rc/ResourceFileWriter.cpp
+++ llvm/tools/llvm-rc/ResourceFileWriter.cpp
@@ -220,10 +220,18 @@
   return writeResource(Res, &ResourceFileWriter::writeAcceleratorsBody);
 }
 
+Error ResourceFileWriter::visitCursorResource(const RCResource *Res) {
+  return handleError(visitIconOrCursorResource(Res), Res);
+}
+
 Error ResourceFileWriter::visitDialogResource(const RCResource *Res) {
   return writeResource(Res, &ResourceFileWriter::writeDialogBody);
 }
 
+Error ResourceFileWriter::visitIconResource(const RCResource *Res) {
+  return handleError(visitIconOrCursorResource(Res), Res);
+}
+
 Error ResourceFileWriter::visitCaptionStmt(const CaptionStmt *Stmt) {
   ObjectData.Caption = Stmt->Value;
   return Error::success();
@@ -422,6 +430,261 @@
   return Error::success();
 }
 
+// --- CursorResource and IconResource helpers. --- //
+
+// ICONRESDIR structure. Describes a single icon in resouce group.
+//
+// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648016.aspx
+struct IconResDir {
+  uint8_t Width;
+  uint8_t Height;
+  uint8_t ColorCount;
+  uint8_t Reserved;
+};
+
+// CURSORDIR structure. Describes a single cursor in resource group.
+//
+// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648011(v=vs.85).aspx
+struct CursorDir {
+  ulittle16_t Width;
+  ulittle16_t Height;
+};
+
+// RESDIRENTRY structure, stripped from the last item. Stripping made
+// for compatibility with RESDIR.
+//
+// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648026(v=vs.85).aspx
+struct ResourceDirEntryStart {
+  union {
+    CursorDir Cursor; // Used in CURSOR resources.
+    IconResDir Icon;  // Used in .ico and .cur files, and ICON resources.
+  };
+  ulittle16_t Planes;   // HotspotX (.cur files but not CURSOR resource).
+  ulittle16_t BitCount; // HotspotY (.cur files but not CURSOR resource).
+  ulittle32_t Size;
+  // ulittle32_t ImageOffset;  // Offset to image data (ICONDIRENTRY only).
+  // ulittle16_t IconID;       // Resource icon ID (RESDIR only).
+};
+
+// BITMAPINFOHEADER structure. Describes basic information about the bitmap
+// being read.
+//
+// Ref: msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspx
+struct BitmapInfoHeader {
+  ulittle32_t Size;
+  ulittle32_t Width;
+  ulittle32_t Height;
+  ulittle16_t Planes;
+  ulittle16_t BitCount;
+  ulittle32_t Compression;
+  ulittle32_t SizeImage;
+  ulittle32_t XPelsPerMeter;
+  ulittle32_t YPelsPerMeter;
+  ulittle32_t ClrUsed;
+  ulittle32_t ClrImportant;
+};
+
+// Group icon directory header. Called ICONDIR in .ico/.cur files and
+// NEWHEADER in .res files.
+//
+// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648023(v=vs.85).aspx
+struct GroupIconDir {
+  ulittle16_t Reserved; // Always 0.
+  ulittle16_t ResType;  // 1 for icons, 2 for cursors.
+  ulittle16_t ResCount; // Number of items.
+};
+
+enum class IconCursorGroupType { Icon, Cursor };
+
+class SingleIconCursorResource : public RCResource {
+public:
+  IconCursorGroupType Type;
+  const ResourceDirEntryStart &Header;
+  ArrayRef<uint8_t> Image;
+
+  SingleIconCursorResource(IconCursorGroupType ResourceType,
+                           const ResourceDirEntryStart &HeaderEntry,
+                           ArrayRef<uint8_t> ImageData)
+      : Type(ResourceType), Header(HeaderEntry), Image(ImageData) {}
+
+  Twine getResourceTypeName() const override { return "Icon/cursor image"; }
+  IntOrString getResourceType() const override {
+    return Type == IconCursorGroupType::Icon ? RkSingleIcon : RkSingleCursor;
+  }
+  uint16_t getMemoryFlags() const override {
+    return MfDiscardable | MfMoveable;
+  }
+  ResourceKind getKind() const override { return RkSingleCursorOrIconRes; }
+  static bool classof(const RCResource *Res) {
+    return Res->getKind() == RkSingleCursorOrIconRes;
+  }
+};
+
+class IconCursorGroupResource : public RCResource {
+public:
+  IconCursorGroupType Type;
+  GroupIconDir Header;
+  std::vector<ResourceDirEntryStart> ItemEntries;
+
+  IconCursorGroupResource(IconCursorGroupType ResourceType,
+                          const GroupIconDir &HeaderData,
+                          std::vector<ResourceDirEntryStart> &&Entries)
+      : Type(ResourceType), Header(HeaderData),
+        ItemEntries(std::move(Entries)) {}
+
+  Twine getResourceTypeName() const override { return "Icon/cursor group"; }
+  IntOrString getResourceType() const override {
+    return Type == IconCursorGroupType::Icon ? RkIconGroup : RkCursorGroup;
+  }
+  ResourceKind getKind() const override { return RkCursorOrIconGroupRes; }
+  static bool classof(const RCResource *Res) {
+    return Res->getKind() == RkCursorOrIconGroupRes;
+  }
+};
+
+Error ResourceFileWriter::writeSingleIconOrCursorBody(
+    const RCResource *Base) {
+  auto *Res = cast<SingleIconCursorResource>(Base);
+  if (Res->Type == IconCursorGroupType::Cursor) {
+    // In case of cursors, two WORDS are appended to the beginning
+    // of the resource: HotspotX (Planes in RESDIRENTRY),
+    // and HotspotY (BitCount).
+    //
+    // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648026.aspx
+    //  (Remarks section).
+    writeObject(Res->Header.Planes);
+    writeObject(Res->Header.BitCount);
+  }
+
+  writeObject(Res->Image);
+  return Error::success();
+}
+
+Error ResourceFileWriter::writeIconOrCursorGroupBody(const RCResource *Base) {
+  auto *Res = cast<IconCursorGroupResource>(Base);
+  writeObject(Res->Header);
+  for (auto Item : Res->ItemEntries) {
+    writeObject(Item);
+    writeObject(ulittle16_t(IconCursorID++));
+  }
+  return Error::success();
+}
+
+Error ResourceFileWriter::visitSingleIconOrCursor(const RCResource *Res) {
+  return writeResource(Res, &ResourceFileWriter::writeSingleIconOrCursorBody);
+}
+
+Error ResourceFileWriter::visitIconOrCursorGroup(const RCResource *Res) {
+  return writeResource(Res, &ResourceFileWriter::writeIconOrCursorGroupBody);
+}
+
+Error ResourceFileWriter::visitIconOrCursorResource(const RCResource *Base) {
+  IconCursorGroupType Type;
+  StringRef FileStr;
+  IntOrString ResName = Base->ResName;
+
+  if (auto *IconRes = dyn_cast<IconResource>(Base)) {
+    FileStr = IconRes->IconLoc;
+    Type = IconCursorGroupType::Icon;
+  } else {
+    auto *CursorRes = dyn_cast<CursorResource>(Base);
+    FileStr = CursorRes->CursorLoc;
+    Type = IconCursorGroupType::Cursor;
+  }
+
+  bool IsLong;
+  stripQuotes(FileStr, IsLong);
+  ErrorOr<std::unique_ptr<MemoryBuffer>> File =
+      MemoryBuffer::getFile(FileStr, -1, false);
+
+  if (!File)
+    return make_error<StringError>(
+        "Error opening " +
+            Twine(Type == IconCursorGroupType::Icon ? "icon" : "cursor") +
+            " '" + FileStr + "': " + File.getError().message(),
+        File.getError());
+
+  BinaryStreamReader Reader((*File)->getBuffer(), support::little);
+
+  // Read the file headers.
+  //   - At the beginning, ICONDIR/NEWHEADER header.
+  //   - Then, a number of RESDIR headers follow. These contain offsets
+  //       to data.
+  const GroupIconDir *Header;
+
+  RETURN_IF_ERROR(Reader.readObject(Header));
+  if (Header->Reserved != 0)
+    return createError("Incorrect icon/cursor Reserved field; should be 0.");
+  uint16_t NeededType = Type == IconCursorGroupType::Icon ? 1 : 2;
+  if (Header->ResType != NeededType)
+    return createError("Incorrect icon/cursor ResType field; should be " +
+                       Twine(NeededType) + ".");
+
+  uint16_t NumItems = Header->ResCount;
+
+  // Read single ico/cur headers.
+  std::vector<ResourceDirEntryStart> ItemEntries;
+  ItemEntries.reserve(NumItems);
+  std::vector<uint32_t> ItemOffsets(NumItems);
+  for (size_t ID = 0; ID < NumItems; ++ID) {
+    const ResourceDirEntryStart *Object;
+    RETURN_IF_ERROR(Reader.readObject(Object));
+    ItemEntries.push_back(*Object);
+    RETURN_IF_ERROR(Reader.readInteger(ItemOffsets[ID]));
+  }
+
+  // Now write each icon/cursors one by one. At first, all the contents
+  // without ICO/CUR header. This is described by SingleIconCursorResource.
+  for (size_t ID = 0; ID < NumItems; ++ID) {
+    // Load the fragment of file.
+    Reader.setOffset(ItemOffsets[ID]);
+    ArrayRef<uint8_t> Image;
+    RETURN_IF_ERROR(Reader.readArray(Image, ItemEntries[ID].Size));
+    SingleIconCursorResource SingleRes(Type, ItemEntries[ID], Image);
+    SingleRes.setName(IconCursorID + ID);
+    RETURN_IF_ERROR(visitSingleIconOrCursor(&SingleRes));
+  }
+
+  // Now, write all the headers concatenated into a separate resource.
+  for (size_t ID = 0; ID < NumItems; ++ID) {
+    if (Type == IconCursorGroupType::Icon) {
+      // rc.exe seems to always set NumPlanes to 1. No idea why it happens.
+      ItemEntries[ID].Planes = 1;
+      continue;
+    }
+
+    // We need to rewrite the cursor headers.
+    const auto &OldHeader = ItemEntries[ID];
+    ResourceDirEntryStart NewHeader;
+    NewHeader.Cursor.Width = OldHeader.Icon.Width;
+    // Each cursor in fact stores two bitmaps, one under another.
+    // Height provided in cursor definition describes the height of the
+    // cursor, whereas the value existing in resource definition describes
+    // the height of the bitmap. Therefore, we need to double this height.
+    NewHeader.Cursor.Height = OldHeader.Icon.Height * 2;
+
+    // Now, we actually need to read the bitmap header to find
+    // the number of planes and the number of bits per pixel.
+    Reader.setOffset(ItemOffsets[ID]);
+    const BitmapInfoHeader *BMPHeader;
+    RETURN_IF_ERROR(Reader.readObject(BMPHeader));
+    NewHeader.Planes = BMPHeader->Planes;
+    NewHeader.BitCount = BMPHeader->BitCount;
+
+    // Two WORDs were written at the beginning of the resource (hotspot
+    // location). This is reflected in Size field.
+    NewHeader.Size = OldHeader.Size + 2 * sizeof(uint16_t);
+
+    ItemEntries[ID] = NewHeader;
+  }
+
+  IconCursorGroupResource HeaderRes(Type, *Header, std::move(ItemEntries));
+  HeaderRes.setName(ResName);
+  RETURN_IF_ERROR(visitIconOrCursorGroup(&HeaderRes));
+
+  return Error::success();
+}
+
 // --- DialogResource helpers. --- //
 
 Error ResourceFileWriter::writeSingleDialogControl(const Control &Ctl,
Index: llvm/tools/llvm-rc/ResourceScriptStmt.h
===================================================================
--- llvm/tools/llvm-rc/ResourceScriptStmt.h
+++ llvm/tools/llvm-rc/ResourceScriptStmt.h
@@ -74,9 +74,13 @@
   // (TYPE in RESOURCEHEADER structure). The numeric value assigned to each
   // kind is equal to this type ID.
   RkNull = 0,
+  RkSingleCursor = 1,
+  RkSingleIcon = 3,
   RkMenu = 4,
   RkDialog = 5,
   RkAccelerators = 9,
+  RkCursorGroup = 12,
+  RkIconGroup = 14,
   RkVersionInfo = 16,
   RkHTML = 23,
 
@@ -88,7 +92,9 @@
   RkBase,
   RkCursor,
   RkIcon,
-  RkUser
+  RkUser,
+  RkSingleCursorOrIconRes,
+  RkCursorOrIconGroupRes
 };
 
 // Non-zero memory flags.
@@ -258,22 +264,38 @@
 //
 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380920(v=vs.85).aspx
 class CursorResource : public RCResource {
+public:
   StringRef CursorLoc;
 
-public:
   CursorResource(StringRef Location) : CursorLoc(Location) {}
   raw_ostream &log(raw_ostream &) const override;
+
+  Twine getResourceTypeName() const override { return "CURSOR"; }
+  Error visit(Visitor *V) const override {
+    return V->visitCursorResource(this);
+  }
+  ResourceKind getKind() const override { return RkCursor; }
+  static bool classof(const RCResource *Res) {
+    return Res->getKind() == RkCursor;
+  }
 };
 
 // ICON resource. Represents a single ".ico" file containing a group of icons.
 //
 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381018(v=vs.85).aspx
 class IconResource : public RCResource {
+public:
   StringRef IconLoc;
 
-public:
   IconResource(StringRef Location) : IconLoc(Location) {}
   raw_ostream &log(raw_ostream &) const override;
+
+  Twine getResourceTypeName() const override { return "ICON"; }
+  Error visit(Visitor *V) const override { return V->visitIconResource(this); }
+  ResourceKind getKind() const override { return RkIcon; }
+  static bool classof(const RCResource *Res) {
+    return Res->getKind() == RkIcon;
+  }
 };
 
 // HTML resource. Represents a local webpage that is to be embedded into the
Index: llvm/tools/llvm-rc/ResourceVisitor.h
===================================================================
--- llvm/tools/llvm-rc/ResourceVisitor.h
+++ llvm/tools/llvm-rc/ResourceVisitor.h
@@ -32,8 +32,10 @@
 public:
   virtual Error visitNullResource(const RCResource *) = 0;
   virtual Error visitAcceleratorsResource(const RCResource *) = 0;
+  virtual Error visitCursorResource(const RCResource *) = 0;
   virtual Error visitDialogResource(const RCResource *) = 0;
   virtual Error visitHTMLResource(const RCResource *) = 0;
+  virtual Error visitIconResource(const RCResource *) = 0;
   virtual Error visitMenuResource(const RCResource *) = 0;
 
   virtual Error visitCaptionStmt(const CaptionStmt *) = 0;