sfertile created this revision.
sfertile added reviewers: hubert.reinterpretcast, DiggerLin, nemanjai, MaskRay, 
tejohnson, mehdi_amini, phosek, arda.
Herald added subscribers: ormris, StephenFan, steven_wu, kbarton, hiraditya, 
inglorion, mgorny.
Herald added a project: All.
sfertile requested review of this revision.
Herald added projects: clang, LLVM.
Herald added a subscriber: cfe-commits.

The traditional system compiler (xlc) on AIX uses a 'fat' object format for LTO 
by default, embedding the intermediate representation into a special '.ipa' 
section in native XCOFF object files. Then at link time depending on command 
line options either a native link or an ipa link can be performed. This patch 
adds support for embedding the pre-link IR into the module which is then 
codegened to a native XCOFF object with the bitcode emebededed in the .info 
section. The .info section representation starts with a magic number, followed 
by an 8-byte size, an identifier string and a 4-byte unsigned difference, 
finally followed by the payload. The magic number and identifier string indcate 
to the linker that the embedded metadata is bitcode and it is appropriate for 
use in LTO.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130777

Files:
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/BackendUtil.cpp
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/CodeGen/PowerPC/aix-embedded-bitcode.c
  clang/test/CodeGen/embed-lto-metadata.c
  clang/test/Driver/embedded-lto.c
  llvm/include/llvm/Bitcode/EmbedBitcodePass.h
  llvm/include/llvm/MC/MCStreamer.h
  llvm/include/llvm/MC/MCXCOFFStreamer.h
  llvm/lib/Bitcode/Writer/CMakeLists.txt
  llvm/lib/Bitcode/Writer/EmbedBitcodePass.cpp
  llvm/lib/MC/MCAsmStreamer.cpp
  llvm/lib/MC/MCStreamer.cpp
  llvm/lib/Passes/PassBuilder.cpp
  llvm/lib/Passes/PassRegistry.def
  llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
  llvm/test/Bitcode/embed-multiple.ll
  llvm/test/Bitcode/embed-unsupported-object-format.ll
  llvm/test/Bitcode/embed.ll
  llvm/test/CodeGen/PowerPC/aix-embeded-bitcode.ll
  llvm/test/CodeGen/PowerPC/aix-embeded-module-padding.ll
  llvm/test/Transforms/Util/embeded-lto-TLI-mappings.ll

Index: llvm/test/Transforms/Util/embeded-lto-TLI-mappings.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/Util/embeded-lto-TLI-mappings.ll
@@ -0,0 +1,20 @@
+; RUN: opt -vector-library=MASSV  -passes='function(inject-tli-mappings),embed-bitcode' -S < %s | FileCheck %s
+
+target triple = "powerpc-unknown-aix"
+
+; CHECK: @llvm.compiler.used = appending global [3 x ptr] [ptr @__sind2, ptr @__log10f4, ptr @llvm.embedded.module], section "llvm.metadata"
+
+define double @sin_f64(double %in) {
+  %call = tail call double @sin(double %in)
+  ret double %call
+}
+
+declare double @sin(double) #0
+
+define float @call_llvm.log10.f32(float %in) {
+  %call = tail call float @llvm.log10.f32(float %in)
+  ret float %call
+}
+
+declare float @llvm.log10.f32(float) #0
+attributes #0 = { nounwind readnone }
Index: llvm/test/CodeGen/PowerPC/aix-embeded-module-padding.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/PowerPC/aix-embeded-module-padding.ll
@@ -0,0 +1,20 @@
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | \
+; RUN: FileCheck %s
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | \
+; RUN: FileCheck %s
+
+target datalayout = "E-m:a-p:32:32-i64:64-n32"
+target triple = "powerpc-ibm-aix7.2.0.0"
+
+@c = local_unnamed_addr global i8 -85, align 1
+@llvm.embedded.module = private constant [1647 x i8] c"BC\C0\DE5\14\00\00\05\00\00\00b\0C0$MY\BEf\9D\FB\B4O\1B\C8$D\012\05\00!\0C\00\00_\01\00\00\0B\02!\00\02\00\00\00\16\00\00\00\07\81#\91A\C8\04I\06\1029\92\01\84\0C%\05\08\19\1E\04\8Bb\80\0CE\02B\92\0BBd\102\148\08\18K\0A22\88Hp\C4!#D\12\87\8C\10A\92\02d\C8\08\B1\14 CF\88 \C9\0122\84\18*(*\901|\B0\\\91 \C3\C8\00\00\00\89 \00\00\0B\00\00\002\22\C8\08 bF\00!+$\98\0C!%$\98\0C\19'\0C\85\A4\90`2d\\ $c\82\80\98#@\08\03\01s\04`\00\00\13,xx\87{(\07y\80\87qh\83t\10\87vh\83pH\07|\B8\037\90\037\80\037\80\83\0DX)\B4A;\E8A8\B4\01<\E8\C1\1C\C8\81\1E\CC\81\1C\B4A:\D8\01\1D\E8\81\1D\D0A\1B\B8\C3\1C\C8\81\D2\03B\84\04\90!#EB\00\8D\10\86}$\A41\16\E27\16'\00\16_\D8!\01\01 \08@\00\00\80\00\00\00\00\04\80\C4\06\81\C2d\01\00\00Y \00\00\00\07\00\00\002\1E\98\0C\19\11L\90\8C\09&G\C6\04CB\AD\06\D0J\A0\08\CAa\04\00\00\00\B1\18\00\00\9B\00\00\003\08\80\1C\C4\E1\1Cf\14\01=\88C8\84\C3\8CB\80\07yx\07s\98q\0C\E6\00\0F\ED\10\0E\F4\80\0E3\0CB\1E\C2\C1\1D\CE\A1\1Cf0\05=\88C8\84\83\1B\CC\03=\C8C=\8C\03=\CCx\8Ctp\07{\08\07yH\87pp\07zp\03vx\87p \87\19\CC\11\0E\EC\90\0E\E10\0Fn0\0F\E3\F0\0E\F0P\0E3\10\C4\1D\DE!\1C\D8!\1D\C2a\1Ef0\89;\BC\83;\D0C9\B4\03<\BC\83<\84\03;\CC\F0\14v`\07{h\077h\87rh\077\80\87p\90\87p`\07v(\07v\F8\05vx\87w\80\87_\08\87q\18\87r\98\87y\98\81,\EE\F0\0E\EE\E0\0E\F5\C0\0E\EC0\03b\C8\A1\1C\E4\A1\1C\CC\A1\1C\E4\A1\1C\DCa\1C\CA!\1C\C4\81\1D\CAa\06\D6\90C9\C8C9\98C9\C8C9\B8\C38\94C8\88\03;\94\C3/\BC\83<\FC\82;\D4\03;\B0\C3\0C\C7i\87pX\87rp\83th\07x`\87t\18\87t\A0\87\19\CES\0F\EE\00\0F\F2P\0E\E4\90\0E\E3@\0F\E1 \0E\ECP\0E3 (\1D\DC\C1\1E\C2A\1E\D2!\1C\DC\81\1E\DC\E0\1C\E4\E1\1D\EA\01\1Ef\18Q8\B0C:\9C\83;\CCP$v`\07{h\077`\87wx\07x\98QL\F4\90\0F\F0P\0E3\1Ej\1E\CAa\1C\E8!\1D\DE\C1\1D~\01\1E\E4\A1\1C\CC!\1D\F0a\06T\85\838\CC\C3;\B0C=\D0C9\FC\C2<\E4C;\88\C3;\B0\C3\8C\C5\0A\87y\98\87w\18\87t\08\07z(\07r\98\81\\\E3\10\0E\EC\C0\0E\E5P\0E\F30#\C1\D2A\1E\E4\E1\17\D8\E1\1D\DE\01\1EfH\19;\B0\83=\B4\83\1B\84\C38\8CC9\CC\C3<\B8\C19\C8\C3;\D4\03<\CCH\B4q\08\07v`\07q\08\87qX\87\19\DB\C6\0E\EC`\0F\ED\E0\06\F0 \0F\E50\0F\E5 \0F\F6P\0En\10\0E\E30\0E\E50\0F\F3\E0\06\E9\E0\0E\E4P\0E\F80#\E2\ECa\1C\C2\81\1D\D8\E1\17\EC!\1D\E6!\1D\C4!\1D\D8!\1D\E8!\1Ff \9D;\BCC=\B8\039\94\839\CCX\BCpp\07wx\07z\08\07zH\87wp\87\19\CB\E7\0E\EF0\0F\E1\E0\0E\E9@\0F\E9\A0\0F\E5\00y \00\00>\00\00\00r\1EH C\88\0C\19\09r2H #\81\8C\91\91\D1D\A0\10(d<12B\8E\90!\A3X &\01JrH\B2\00\00\00\00wchar_sizePIC LevelThinLTOEnableSplitLTOUnitIBM Open XL C/C++ for AIX, (IBM Internal Development Branch), clang version 15.0.0\00\00#\08\830\820\0C#\08\031\820\143\0CFp\CC0 \C21\C3`\0C\C9\0C\83A\183\04\85\8C\04&(#66\BB6\97\B67\B2:\B62\173\B6\B0\B3\B9Q\88DY\98T\D8\D8\EC\DA\\\D2\C8\CA\DC\E8F\09\1A\00\A9\18\00\00%\00\00\00\0B\0Ar(\87w\80\07zXp\98C=\B8\C38\B0C9\D0\C3\82\E6\1C\C6\A1\0D\E8A\1E\C2\C1\1D\E6!\1D\E8!\1D\DE\C1\1D\164\E3`\0E\E7P\0F\E1 \0F\E4@\0F\E1 \0F\E7P\0E\F4\B0\80\81\07y(\87p`\07vx\87q\08\07z(\07rXp\9C\C38\B4\01;\A4\83=\94\C3\02k\1C\D8!\1C\DC\E1\1C\DC \1C\E4a\1C\DC \1C\E8\81\1E\C2a\1C\D0\A1\1C\C8a\1C\C2\81\1D\D8a\C1\01\0F\F4 \0F\E1P\0F\F4\80\0E\00\00\00\00\D1\10\00\00\06\00\00\00\07\CC<\A4\83;\9C\03;\94\03=\A0\83<\94C8\90\C3\01\00\00\00q \00\00\02\00\00\002\0E\10\22\04\00\00\00\00\00\00\00e\0C\00\00\1F\00\00\00\12\03\94\F0\00\00\00\00\03\00\00\00\01\00\00\00\09\00\00\00L\00\00\00\01\00\00\00X\00\00\00\00\00\00\00X\00\00\00\01\00\00\00p\00\00\00\00\00\00\00\0A\00\00\00\16\00\00\00 \00\00\00\0F\00\00\00\01\00\00\00\00\00\00\00p\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\01\00\00\00\FF\FF\FF\FF\00\04\00\00\00\00\00\00]\0C\00\00\0F\00\00\00\12\03\94o\00\00\00\00c15.0.0gitpowerpc-ibm-aix7.2.0.0single_global.c\00\00\00\00\00\0A\0B\0C", section ".NeedsPadding", align 1
+@llvm.compiler.used = appending global [1 x i8*] [i8* getelementptr inbounds ([1647 x i8], [1647 x i8]* @llvm.embedded.module, i32 0, i32 0)], section "llvm.metadata"
+
+; CHECK: .info , 0xffffffff # Magic
+; CHECK: .info , 0x00000000, 0x00000690 # Length
+; CHECK: .info , 0x2e4e6565, 0x64735061, 0x6464696e, 0x67000000 # Identifier string
+; CHECK: .info , 0x00000021 # Size difference
+;; Start of embeded module
+; CHECK: .info , 0x4243c0de,
+;; Trailing padding
+; CHECK: .info , 0x0a0b0c00
Index: llvm/test/CodeGen/PowerPC/aix-embeded-bitcode.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/PowerPC/aix-embeded-bitcode.ll
@@ -0,0 +1,27 @@
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | \
+; RUN: FileCheck %s
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | \
+; RUN: FileCheck %s
+
+; CHECK-NOT: .info , 0x434d444c, 0x494e4500
+; CHECK: .info , 0xffffffff # Magic
+; CHECK: .info , 0x00000000, 0x00000c24 # Length
+; CHECK: .info , 0x4c4c564d, 0x4c544f00 # Identifier string
+; CHECK: .info , 0x00000018 # Size difference
+; CHECK: .info , 0x4243c0de,
+; CHECK-NOT: .info , 0x434d444c, 0x494e4500
+
+@.str = private unnamed_addr constant [13 x i8] c"Hello World!\00", align 1
+@a = external local_unnamed_addr global i32, align 4
+@llvm.embedded.module = private constant [3084 x i8] c"BC\C0\DE5\14\00\00\05\00\00\00b\0C0$MY\BEf\9D\FB\B4O\1B\C8$D\012\05\00!\0C\00\00\B0\02\00\00\0B\02!\00\02\00\00\00\16\00\00\00\07\81#\91A\C8\04I\06\1029\92\01\84\0C%\05\08\19\1E\04\8Bb\80\10E\02B\92\0BB\84\102\148\08\18K\0A2B\88Hp\C4!#D\12\87\8C\10A\92\02d\C8\08\B1\14 CF\88 \C9\012B\84\18*(*\901|\B0\\\91 \C4\C8\00\00\00\89 \00\00\0F\00\00\002\22\08\09 bF\00!+$\98\10!%$\98\10\19'\0C\85\A4\90`Bd\\ $d\82\A0\99#@\B4\01(\E6\08\C0\80\C6\04CE`\849\C2\81\809\02P\18\01\00\00Q\18\00\00\FB\00\00\00\1Bx%\F8\FF\FF\FF\FF\01\90\08s\90\87ph\87rh\03xx\87tp\07z(\07y\00\DC\E1\1D\DC\A1\1C\00\A2\1D\D2\C1\1D\DA\80\1D\CA\E1\1C\C2\81\1D\DA\C0\1E\CAa\1C\E8\E1\1D\E4\A1\0D\EE!\1D\C8\81\1E\D0\01\80\03\80p\87wh\03z\90\87p\80\07xH\07w8\876h\87p\A0\07t\00\E8A\1E\EA\A1\1C\00b\1E\E8!\1C\C6a\1D\DA\00\1E\E4\E1\1D\E8\A1\1C\C6\81\1E\DEA\1E\DA@\1C\EA\C1\1C\CC\A1\1C\E4\A1\0D\E6!\1D\F4\A1\1C\00<\00\08z\08\07y8\87r\A0\876\18\07x\A8\07\00\1E\EEA\1E\EE\00 \E8!\1C\E4\E1\1C\CA\81\1E\DA\C0\1C\CA!\1C\E8\A1\1E\E4\A1\1C\E6\01X\83p`\07zH\07{(\87q`\835\10\07x(\07yh\07r`\835(\07|\A0\07rH\07{`\835H\87y\08\876\B0\079\80\03;h\83tp\87y\A0\07y\A8\87q\A0\87tx\07w\98\076X\03{\98\07|`\836\18\07y\10\87t\A0\87y`\836\18\07y\C8\07x\A0\87w`\836 \87t\90\87r\18\07zh\83vx\07{(\076h\03t\A0\87v`\836H\87y\08\876\B0\079\80\83;h\83tp\87y\A0\07y\A8\87q\A0\87tx\07w\98\076h\83t\98\87ph\03{\98\038h\83tp\87y\A0\07y\A8\87q\A0\87tx\07w\98\076h\03xx\87{(\07y\C0\836\B0\87r\18\07zx\07y`\836\80\87w\B8\87r\90\87<h\03{(\87q\A0\87w\90\076h\03x\90\87t\B0\87t`\87r8\87r \076h\83x\A8\87p \87{x\07y \876\08\07zx\87vH\87q\98\076h\03yx\07xh\03x\90\87w\A0\87r\18\07z`\836\98\07x(\07`\03\A8\08\FF\FF\FF\FF?\10\E6 \0F\E1\D0\0E\E5\D0\06\F0\F0\0E\E9\E0\0E\F4P\0E\F2\00\B8\C3;\B8C9\00\84;\BCC\1B\D0\83<\84\03<\C0C:\B8\C39\B4A;\84\03=\A0\03@\0F\F2P\0F\E5\00\10\F3@\0F\E10\0E\EB\D0\06\F0 \0F\EF@\0F\E50\0E\F4\F0\0E\F2\D0\06\E2P\0F\E6`\0E\E5 \0Fm0\0F\E9\A0\0F\E5\00\E0\01@\D0C8\C8\C39\94\03=\B4\C18\C0C=\00\F0p\0F\F2p\07\00A\0F\E1 \0F\E7P\0E\F4\D0\06\E6P\0E\E1@\0F\F5 \0F\E50\0F\C0\1A\84\03;\D0C:\D8C9\8C\03\1B\AC\818\C0C9\C8C;\90\03\1B\ACA9\E0\03=\90C:\D8\03\1B\ACA:\CCC8\B4\81=\C8\01\1C\D8A\1B\A4\83;\CC\03=\C8C=\8C\03=\A4\C3;\B8\C3<\B0\C1\1A\D8\C3<\E0\03\1B\B4\C18\C8\838\A4\03=\CC\03\1B\B4\C18\C8C>\C0\03=\BC\03\1B\B4\019\A4\83<\94\C38\D0C\1B\B4\C3;\D8C9\B0A\1B\A0\03=\B4\03\1B\B4A:\CCC8\B4\81=\C8\01\1C\DCA\1B\A4\83;\CC\03=\C8C=\8C\03=\A4\C3;\B8\C3<\B0A\1B\A4\C3<\84C\1B\D8\C3\1C\C0A\1B\A4\83;\CC\03=\C8C=\8C\03=\A4\C3;\B8\C3<\B0A\1B\C0\C3;\DCC9\C8\03\1E\B4\81=\94\C38\D0\C3;\C8\03\1B\B4\01<\BC\C3=\94\83<\E4A\1B\D8C9\8C\03=\BC\83<\B0A\1B\C0\83<\A4\83=\A4\03;\94\C39\94\039\B0A\1B\C4C=\84\039\DC\C3;\C8\039\B4A8\D0\C3;\B4C:\8C\C3<\B0A\1B\C8\C3;\C0C\1B\C0\83<\BC\03=\94\C38\D0\03\1B\B4\C1<\C0C9\00\1B\88!\00Ha\03A\FC\FF\FF\FF\FF\00H\00\00I\18\00\00\03\00\00\00\13\82`\82 \0C\13\04b\00\00\00\13,xx\87{(\07y\80\87qh\83t\10\87vh\83pH\07|\B8\037\90\037\80\037\80\83\0DX)\B4A;\E8A8\B4\01<\E8\C1\1C\C8\81\1E\CC\81\1C\B4A:\D8\01\1D\E8\81\1D\D0A\1B\B8\C3\1C\C8\81\D2\03B\84D\90!#ED\00\8D\10\865\18\00i|a\C7\04\10\C1\A0$\01\00\00\01\00\00@@\00\C0\8E\89\08\06\01\00\06\00\00\04\00\00\00\80\00\80!UA\14\00\00\04\00\00\00\02\00\00\00\00\00\040\A4J\1A\04\08\00\01\00\00@\00\00\00\00\00\80\00$6\08\14\A6\15\00\00\C8\02\01\00\0A\00\00\002\1E\98\10\19\11L\90\8C\09&G\C6\04C\9A\12(\82r\18\01\A0\1D\01\A0P\06Yf\B3\DF\A0\EB[\CE&\87\00\00\B1\18\00\00\9B\00\00\003\08\80\1C\C4\E1\1Cf\14\01=\88C8\84\C3\8CB\80\07yx\07s\98q\0C\E6\00\0F\ED\10\0E\F4\80\0E3\0CB\1E\C2\C1\1D\CE\A1\1Cf0\05=\88C8\84\83\1B\CC\03=\C8C=\8C\03=\CCx\8Ctp\07{\08\07yH\87pp\07zp\03vx\87p \87\19\CC\11\0E\EC\90\0E\E10\0Fn0\0F\E3\F0\0E\F0P\0E3\10\C4\1D\DE!\1C\D8!\1D\C2a\1Ef0\89;\BC\83;\D0C9\B4\03<\BC\83<\84\03;\CC\F0\14v`\07{h\077h\87rh\077\80\87p\90\87p`\07v(\07v\F8\05vx\87w\80\87_\08\87q\18\87r\98\87y\98\81,\EE\F0\0E\EE\E0\0E\F5\C0\0E\EC0\03b\C8\A1\1C\E4\A1\1C\CC\A1\1C\E4\A1\1C\DCa\1C\CA!\1C\C4\81\1D\CAa\06\D6\90C9\C8C9\98C9\C8C9\B8\C38\94C8\88\03;\94\C3/\BC\83<\FC\82;\D4\03;\B0\C3\0C\C7i\87pX\87rp\83th\07x`\87t\18\87t\A0\87\19\CES\0F\EE\00\0F\F2P\0E\E4\90\0E\E3@\0F\E1 \0E\ECP\0E3 (\1D\DC\C1\1E\C2A\1E\D2!\1C\DC\81\1E\DC\E0\1C\E4\E1\1D\EA\01\1Ef\18Q8\B0C:\9C\83;\CCP$v`\07{h\077`\87wx\07x\98QL\F4\90\0F\F0P\0E3\1Ej\1E\CAa\1C\E8!\1D\DE\C1\1D~\01\1E\E4\A1\1C\CC!\1D\F0a\06T\85\838\CC\C3;\B0C=\D0C9\FC\C2<\E4C;\88\C3;\B0\C3\8C\C5\0A\87y\98\87w\18\87t\08\07z(\07r\98\81\\\E3\10\0E\EC\C0\0E\E5P\0E\F30#\C1\D2A\1E\E4\E1\17\D8\E1\1D\DE\01\1EfH\19;\B0\83=\B4\83\1B\84\C38\8CC9\CC\C3<\B8\C19\C8\C3;\D4\03<\CCH\B4q\08\07v`\07q\08\87qX\87\19\DB\C6\0E\EC`\0F\ED\E0\06\F0 \0F\E50\0F\E5 \0F\F6P\0En\10\0E\E30\0E\E50\0F\F3\E0\06\E9\E0\0E\E4P\0E\F80#\E2\ECa\1C\C2\81\1D\D8\E1\17\EC!\1D\E6!\1D\C4!\1D\D8!\1D\E8!\1Ff \9D;\BCC=\B8\039\94\839\CCX\BCpp\07wx\07z\08\07zH\87wp\87\19\CB\E7\0E\EF0\0F\E1\E0\0E\E9@\0F\E9\A0\0F\E5\00y \00\00<\00\00\00r\1EH C\88\0C\19\09r2H #\81\8C\91\91\D1D\A0\10(d<12B\8E\90!\A3X \FD\00JrH\A9\00\00\00\00wchar_sizePIC LevelThinLTOEnableSplitLTOUnitXL C/C++ for AIX, (IBM Internal Development Branch), clang version 15.0.0\00\00\00#\08\031\820\14#\08\831\820\1C3\0CFp\CC0 \C21\C3`\0C\C9\0C\83A\183\04\85\8C\04&(#66\BB6\97\B67\B2:\B62\173\B6\B0\B3\B9Q\88DY\98T\D8\D8\EC\DA\\\D2\C8\CA\DC\E8F\09\1A\00\A9\18\00\00%\00\00\00\0B\0Ar(\87w\80\07zXp\98C=\B8\C38\B0C9\D0\C3\82\E6\1C\C6\A1\0D\E8A\1E\C2\C1\1D\E6!\1D\E8!\1D\DE\C1\1D\164\E3`\0E\E7P\0F\E1 \0F\E4@\0F\E1 \0F\E7P\0E\F4\B0\80\81\07y(\87p`\07vx\87q\08\07z(\07rXp\9C\C38\B4\01;\A4\83=\94\C3\02k\1C\D8!\1C\DC\E1\1C\DC \1C\E4a\1C\DC \1C\E8\81\1E\C2a\1C\D0\A1\1C\C8a\1C\C2\81\1D\D8a\C1\01\0F\F4 \0F\E1P\0F\F4\80\0E\00\00\00\00\D1\10\00\00\06\00\00\00\07\CC<\A4\83;\9C\03;\94\03=\A0\83<\94C8\90\C3\01\00\00\00a \00\00'\00\00\00\13\04A,\10\00\00\00\03\00\00\00tC\1D\81\00\0C\C7p\00\00\00\00\F10\00\00\12\00\00\00\22G\C8\90Q\0E\C4\19\00\00\00\00\C3\13\01\00intomnipotent charSimple C/C++ TBAA\00\13\84\05\D9\10D\1B\06h\926\0C\0F%m\18\AAJ\02\00#\06\C5\10\82`\80 \01-36\08\07\02\00\03\00\00\00\07P\10\CD\14a\B6@\08\C0\B2\00\011\00\00\02\00\00\00[\86 \A8\00\00\00\00\00\00\00\00\C1 \00\00\13\00\00\00\A3\04\C9P\01\22\AA\00!2\84\88\10!B\C4\08\89\1A@\88\0C!\22D\88\101BR\0E\10\22c\84\C4\BC D\86\88\11\12\F2\80\10\19BRZ\10\22d\84J\00\1A@\0C\01\18\00\02\06\0C\00\17\82\82\C1\82\00\00\00\00\00q \00\00\03\00\00\002\0E\10\22\84\02\F6\04\00\00\00\00\00\00\00\00e\0C\00\001\00\00\00\12\03\94x\01\00\00\00\03\00\00\00\16\00\00\00\09\00\00\00L\00\00\00\01\00\00\00X\00\00\00\00\00\00\00X\00\00\00\04\00\00\00\B8\00\00\00\00\00\00\00\1F\00\00\00\16\00\00\005\00\00\00\06\00\00\00\04\00\00\00\00\00\00\00\B8\00\00\00\00\00\00\00\00\00\00\00\04\00\00\00\00\00\00\00\05\00\00\00\04\00\00\00\05\00\00\00\04\00\00\00\FF\FF\FF\FF\00$\00\00\09\00\00\00\0D\00\00\00\09\00\00\00\0D\00\00\00\FF\FF\FF\FF\08$\00\00;\00\00\00\07\00\00\00\00\00\00\00\04\00\00\00\FF\FF\FF\FF\00\18\00\00\04\00\00\00\01\00\00\00\04\00\00\00\01\00\00\00\FF\FF\FF\FF\08\04\00\00\00\00\00\00]\0C\00\00\14\00\00\00\12\03\94\A2\00\00\00\00.stramainexternal_func15.0.0gitpowerpc-ibm-aix7.2.0.0main.cL...str\00\00\00\00\00\00", section "LLVMLTO", align 1
+@llvm.compiler.used = appending global [1 x i8*] [i8* getelementptr inbounds ([3084 x i8], [3084 x i8]* @llvm.embedded.module, i32 0, i32 0)], section "llvm.metadata"
+
+; Function Attrs: nounwind
+define i32 @main() local_unnamed_addr {
+entry:
+  %call = tail call i32 @external_func(i8* noundef getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i32 0, i32 0))
+  %0 = load i32, i32* @a, align 4
+  ret i32 %0
+}
+
+declare i32 @external_func(i8* noundef) local_unnamed_addr
Index: llvm/test/Bitcode/embed.ll
===================================================================
--- /dev/null
+++ llvm/test/Bitcode/embed.ll
@@ -0,0 +1,9 @@
+; RUN: opt --mtriple powerpc64-unknown-aix < %s -passes=embed-bitcode -S | FileCheck %s
+
+ target triple = "powerpc-ibm-aix7.2.0.0"
+
+ @a = global i32 1
+
+ ; CHECK: @a = global i32 1
+ ; CHECK: @llvm.embedded.module = private constant [1288 x i8] c"{{.*}}", section "LLVMLTO", align 1
+ ; CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr @llvm.embedded.module], section "llvm.metadata"
Index: llvm/test/Bitcode/embed-unsupported-object-format.ll
===================================================================
--- /dev/null
+++ llvm/test/Bitcode/embed-unsupported-object-format.ll
@@ -0,0 +1,5 @@
+; RUN: not --crash opt --mtriple powerpc64le-unknown-linux < %s -passes=embed-bitcode -S 2>&1 | FileCheck %s
+
+@a = global i32 1
+
+; CHECK: LLVM ERROR: Embed bitcode pass currently only supports XCOFF object format.
Index: llvm/test/Bitcode/embed-multiple.ll
===================================================================
--- /dev/null
+++ llvm/test/Bitcode/embed-multiple.ll
@@ -0,0 +1,6 @@
+; RUN: not --crash opt --mtriple powerpc64-unknown-aix < %s -passes=embed-bitcode -S 2>&1 | FileCheck %s
+
+@a = global i32 1
+@llvm.embedded.module = private constant [4 x i8] c"BC\C0\DE"
+
+; CHECK: LLVM ERROR: Can only embed the module once.
Index: llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
===================================================================
--- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -2392,6 +2392,39 @@
 }
 
 void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {
+  if (GV->getName().equals("llvm.embedded.module")) {
+    // Bitcode is stored in the intitalizer.
+    assert(GV->hasInitializer() && "embedded module must have intializer.");
+
+    // The globals CSECT name is emitted as part of the info directive to
+    // allow consumers to determine what the embedded bitcode is for.
+    SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
+    MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
+        getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
+
+    // The embeded module must be an array of bytes.
+    const ConstantDataArray *EmbeddedModule =
+        dyn_cast<ConstantDataArray>(GV->getInitializer());
+    assert(EmbeddedModule && "EmbededModule must be a constant data array.");
+    const ArrayType *ArrayTy = EmbeddedModule->getType();
+    assert(ArrayTy->getElementType()->isIntegerTy(8) &&
+           "Expected an array of bytes.");
+
+    SmallVector<uint8_t> Metadata;
+    uint64_t ElementCount = ArrayTy->getNumElements();
+    Metadata.reserve(ElementCount);
+
+    for (uint64_t I = 0; I != ElementCount; ++I) {
+      uint64_t Element = EmbeddedModule->getElementAsInteger(I);
+      assert(Element <= UINT8_MAX && "Element must represent a byte value.");
+      Metadata.push_back((uint8_t)Element);
+    }
+
+    OutStreamer->emitXCOFFInfoDirective(Csect->getSymbolTableName(), Metadata);
+    return;
+  }
+
+  // Any other special LLVM globals are unexpected.
   assert(!GV->getName().startswith("llvm.") &&
          "Unhandled intrinsic global variable.");
 
Index: llvm/lib/Passes/PassRegistry.def
===================================================================
--- llvm/lib/Passes/PassRegistry.def
+++ llvm/lib/Passes/PassRegistry.def
@@ -56,6 +56,7 @@
 MODULE_PASS("debugify", NewPMDebugifyPass())
 MODULE_PASS("dot-callgraph", CallGraphDOTPrinterPass())
 MODULE_PASS("elim-avail-extern", EliminateAvailableExternallyPass())
+MODULE_PASS("embed-bitcode", EmbedBitcodePass())
 MODULE_PASS("extract-blocks", BlockExtractorPass())
 MODULE_PASS("forceattrs", ForceFunctionAttrsPass())
 MODULE_PASS("function-import", FunctionImportPass())
Index: llvm/lib/Passes/PassBuilder.cpp
===================================================================
--- llvm/lib/Passes/PassBuilder.cpp
+++ llvm/lib/Passes/PassBuilder.cpp
@@ -72,6 +72,7 @@
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Analysis/TypeBasedAliasAnalysis.h"
+#include "llvm/Bitcode/EmbedBitcodePass.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/PassManager.h"
Index: llvm/lib/MC/MCStreamer.cpp
===================================================================
--- llvm/lib/MC/MCStreamer.cpp
+++ llvm/lib/MC/MCStreamer.cpp
@@ -1190,6 +1190,12 @@
   llvm_unreachable("emitXCOFFRefDirective is only supported on XCOFF targets");
 }
 
+void MCStreamer::emitXCOFFInfoDirective(StringRef Name,
+                                        const SmallVector<uint8_t> &Metadaga) {
+  llvm_unreachable("emitXCOFFInfoDirective is only supported on"
+                   "XCOFF targets");
+}
+
 void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
 void MCStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
                                         StringRef Name, bool KeepOriginalSym) {}
Index: llvm/lib/MC/MCAsmStreamer.cpp
===================================================================
--- llvm/lib/MC/MCAsmStreamer.cpp
+++ llvm/lib/MC/MCAsmStreamer.cpp
@@ -31,6 +31,7 @@
 #include "llvm/MC/MCSymbolXCOFF.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/Endian.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormattedStream.h"
@@ -196,6 +197,8 @@
                                 StringRef Rename) override;
 
   void emitXCOFFRefDirective(StringRef Name) override;
+  void emitXCOFFInfoDirective(StringRef Name,
+                              const SmallVector<uint8_t> &Metadata) override;
 
   void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
@@ -941,6 +944,111 @@
   EmitEOL();
 }
 
+void MCAsmStreamer::emitXCOFFInfoDirective(
+    StringRef Name, const SmallVector<uint8_t> &Metadata) {
+  const char *InfoDirective = "\t.info , ";
+  // Start with the .info pseudo-op, and the magic number indicating embedded
+  // metadata format.
+  OS << InfoDirective << format_hex(0Xffffffff, 10);
+  if (IsVerboseAsm)
+    OS << " # Magic";
+  EmitEOL();
+
+  // NameSize does not include the null terminator of the string. Since we are
+  // padding out to a word boundary anyway, we can calcualte the padding in the
+  // range [1,4] instead of [0,3] to account for the terminator.
+  size_t NameSize = Name.size();
+  uint32_t NamePaddingSize = 4 - NameSize % 4;
+
+  // Metadata needs to be padded out to an even word size.
+  size_t MetadataSize = Metadata.size();
+  uint32_t MetadataPaddingSize = MetadataSize % 4 ? 4 - (MetadataSize % 4) : 0;
+
+  // Total length of all the metadata. We have:
+  // * 4 byte magic
+  // * 8 byte length
+  // * The (null terminated) name string + padding
+  // * The word sized difference between the first length and the length
+  //   of the payload.
+  // * The payload padded to a word boundary.
+  uint64_t Length = 4 + sizeof(Length) + NameSize + NamePaddingSize +
+                    sizeof(uint32_t) + MetadataSize + MetadataPaddingSize;
+  uint32_t Difference = Length - MetadataSize;
+
+  // Emit the 8-byte length as 2 seperate words.
+  OS << InfoDirective;
+  OS << format_hex(uint32_t(Length << 32), 10) << ", ";
+  OS << format_hex(uint32_t(Length), 10);
+  if (IsVerboseAsm)
+    OS << " # Length";
+  EmitEOL();
+
+  // Write out the full word portion of the identifying string.
+  OS << InfoDirective;
+  const char *NameData = Name.data();
+  while (NameData + 4 <= Name.data() + NameSize) {
+    uint32_t NextWord = llvm::support::endian::read32be(NameData);
+    OS << format_hex(NextWord, 10) << ", ";
+    NameData += 4;
+  }
+
+  // Write out the remainder of the identifier and the null-terminating
+  // padding.
+  uint32_t NextWord = 0;
+  if (NamePaddingSize == 3)
+    NextWord = NameData[0] << 24;
+  else if (NamePaddingSize == 2)
+    NextWord = NameData[0] << 24 | NameData[1] << 16;
+  else if (NamePaddingSize == 1)
+    NextWord = NameData[0] << 24 | NameData[1] << 16 | NameData[2] << 8;
+
+  OS << format_hex(NextWord, 10);
+  if (IsVerboseAsm)
+    OS << " # Identifier string";
+  EmitEOL();
+
+  // Emit the size difference used to calculate the payload size and
+  // end the first line.
+  OS << InfoDirective;
+  OS << format_hex(Difference, 10);
+  if (IsVerboseAsm)
+    OS << " # Size difference";
+  EmitEOL();
+
+  // The assembler has a limit on the number of oprands in an expression.
+  // For the .info pseudo op we excced that limit even with relatively small
+  // payloads. Break this up to multiple .info directives to accomadate this
+  // limitation. The number of bytes written here is chosen just to kkep the
+  // assembly readable.
+  uint64_t Index = 0;
+  while (Index + 4 <= MetadataSize) {
+    OS << "\t.info ";
+    uint64_t End = std::min(Index + 40, MetadataSize);
+    while (Index + 4 <= End) {
+      OS << ", ";
+      uint32_t NextWord =
+          llvm::support::endian::read32be(Metadata.data() + Index);
+      OS << format_hex(NextWord, 10);
+      Index += 4;
+    }
+    EmitEOL();
+  }
+
+  if (MetadataPaddingSize) {
+    // If there is padding, then we have at least one byte of payload left to
+    // emit.
+    uint32_t LastWord = Metadata[Index] << 24;
+    if (MetadataPaddingSize == 2)
+      LastWord |= Metadata[Index + 1] << 16;
+    else if (MetadataPaddingSize == 1)
+      LastWord |= ((Metadata[Index + 1] << 16) | (Metadata[Index + 2] << 8));
+
+    OS << InfoDirective;
+    OS << format_hex(LastWord, 10);
+    EmitEOL();
+  }
+}
+
 void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
   assert(MAI->hasDotTypeDotSizeDirective());
   OS << "\t.size\t";
Index: llvm/lib/Bitcode/Writer/EmbedBitcodePass.cpp
===================================================================
--- /dev/null
+++ llvm/lib/Bitcode/Writer/EmbedBitcodePass.cpp
@@ -0,0 +1,52 @@
+//===- EmbedBitcodePass.cpp - Pass that embeds the bitcode into a global---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// EmbedBitcodePass implementation.
+//
+//===----------------------------------------------------------------------===//
+//
+#include "llvm/Bitcode/EmbedBitcodePass.h"
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/Bitcode/BitcodeWriter.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
+
+using namespace llvm;
+
+PreservedAnalyses EmbedBitcodePass::run(Module &M, ModuleAnalysisManager &AM) {
+  if (M.getGlobalVariable("llvm.embedded.module", true))
+    report_fatal_error("Can only embed the module once.");
+
+  Triple T(M.getTargetTriple());
+  if (T.getObjectFormat() != Triple::XCOFF)
+    report_fatal_error(
+        "Embed bitcode pass currently only supports XCOFF object format.");
+
+  std::string Data;
+  raw_string_ostream OS(Data);
+  WriteBitcodeToFile(M, OS, /* ShouldPreserveUseListOrder */ true);
+  ArrayRef<uint8_t> ModuleData((const uint8_t *)OS.str().data(),
+                               OS.str().size());
+  Constant *ModuleConstant = ConstantDataArray::get(M.getContext(), ModuleData);
+
+  llvm::GlobalVariable *EM = new llvm::GlobalVariable(
+      M, ModuleConstant->getType(), true, llvm::GlobalValue::PrivateLinkage,
+      ModuleConstant);
+
+  EM->setSection("LLVMLTO");
+  EM->setAlignment(Align(1));
+  EM->setName("llvm.embedded.module");
+  appendToCompilerUsed(M, {EM});
+
+  return PreservedAnalyses::all();
+}
Index: llvm/lib/Bitcode/Writer/CMakeLists.txt
===================================================================
--- llvm/lib/Bitcode/Writer/CMakeLists.txt
+++ llvm/lib/Bitcode/Writer/CMakeLists.txt
@@ -2,6 +2,7 @@
   BitWriter.cpp
   BitcodeWriter.cpp
   BitcodeWriterPass.cpp
+  EmbedBitcodePass.cpp
   ValueEnumerator.cpp
 
   DEPENDS
Index: llvm/include/llvm/MC/MCXCOFFStreamer.h
===================================================================
--- llvm/include/llvm/MC/MCXCOFFStreamer.h
+++ llvm/include/llvm/MC/MCXCOFFStreamer.h
@@ -41,6 +41,12 @@
     report_fatal_error("emitXCOFFRenameDirective is not implemented yet on "
                        "object generation path");
   }
+
+  void emitXCOFFInfoDirective(const StringRef Name,
+                              const SmallVector<uint8_t> &Metadata) override {
+    report_fatal_error("emitXCOFFInfoDirective is not implemented yet on "
+                       "object generation path");
+  }
 };
 
 } // end namespace llvm
Index: llvm/include/llvm/MC/MCStreamer.h
===================================================================
--- llvm/include/llvm/MC/MCStreamer.h
+++ llvm/include/llvm/MC/MCStreamer.h
@@ -634,6 +634,9 @@
   /// \param Sym - The symbol on the .ref directive.
   virtual void emitXCOFFRefDirective(StringRef Sym);
 
+  virtual void emitXCOFFInfoDirective(StringRef Name,
+                                      const SmallVector<uint8_t> &Metadata);
+
   /// Emit an ELF .size directive.
   ///
   /// This corresponds to an assembler statement such as:
Index: llvm/include/llvm/Bitcode/EmbedBitcodePass.h
===================================================================
--- /dev/null
+++ llvm/include/llvm/Bitcode/EmbedBitcodePass.h
@@ -0,0 +1,36 @@
+//===-- EmbedBitcodePass.h - Embeds bitcode into global ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file provides apass which embeds the bitcode into a global variable.
+///
+//===----------------------------------------------------------------------===//
+//
+#ifndef LLVM_BITCODE_EMBEDBITCODEPASS_H
+#define LLVM_BITCODE_EMBEDBITCODEPASS_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class Module;
+class ModulePass;
+class Pass;
+
+/// Pass embeds the current module into a global variable.
+class EmbedBitcodePass : public PassInfoMixin<EmbedBitcodePass> {
+public:
+  EmbedBitcodePass(){};
+
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
+
+  static bool isRequired() { return true; }
+};
+
+} // end namespace llvm.
+
+#endif
Index: clang/test/Driver/embedded-lto.c
===================================================================
--- /dev/null
+++ clang/test/Driver/embedded-lto.c
@@ -0,0 +1,8 @@
+// RUN: %clang -target powerpc-unknown-aix-xcoff -flto -fembedded-lto -### %s -c -o /dev/null 2>&1 | FileCheck --check-prefix=WLTO %s
+// RUN %clang -target powerpc64-unknown-aix-xcoff -flto -fembedded-lto -### %s -c -o /dev/null 2>&1 | FileCheck --check-prefix=WLTO %s
+
+// RUN %clang -target powerpc-unknown-aix-xcoff  -fmebedded-lto -### %s -c -o /dev/null 2>&1 | FileCheck --check-prefix=WOLTO %s
+// RUN %clang -target powerpc64-unknown-aix-xcoff -fembedded-lto -### %s -c -o /dev/null 2>&1 | FileCheck --check-prefix=WOLTO %s
+
+// WLTO: "-fembedded-lto"
+// WOLTO-NOT:  "-fembedded-lto"
Index: clang/test/CodeGen/embed-lto-metadata.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/embed-lto-metadata.c
@@ -0,0 +1,9 @@
+// RUN: %clang -cc1 -triple powerpc64-unknown-aix-xcoff -S -flto=full -fembedded-lto -emit-llvm < %s  | FileCheck %s
+// RUN: %clang -cc1 -triple powerpc-unknown-aix-xcoff -S -flto=full -fembedded-lto -emit-llvm < %s  | FileCheck %s
+
+// CHECK: !{{[0-9]+}} = !{i32 1, !"ThinLTO", i32 0}
+// CHECK: !{{[0-9]+}} = !{i32 1, !"EnableSplitLTOUnit", i32 1}
+
+int test(void) {
+  return 0xabcd;
+}
Index: clang/test/CodeGen/PowerPC/aix-embedded-bitcode.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/PowerPC/aix-embedded-bitcode.c
@@ -0,0 +1,13 @@
+// REQUIRES: powerpc-registered-target
+// RUN: %clang_cc1 -flto -fembedded-lto  -S -triple powerpc-unknown-aix < %s | \
+// RUN:   FileCheck %s
+//
+// RUN: %clang_cc1 -flto -fembedded-lto -S -triple powerpc64-unknown-aix < %s | \
+// RUN:   FileCheck %s
+extern int puts(const char*);
+
+int external_func(const char* msg) {
+          return puts(msg);
+}
+
+// CHECK: .info , 0xffffffff # Magic
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -7140,6 +7140,10 @@
     }
   }
 
+  if (IsUsingLTO && LTOMode == LTOK_Full &&
+      Args.getLastArg(options::OPT_fembedded_lto))
+    CmdArgs.push_back("-fembedded-lto");
+
   if (Args.hasArg(options::OPT_forder_file_instrumentation)) {
      CmdArgs.push_back("-forder-file-instrumentation");
      // Enable order file instrumentation when ThinLTO is not on. When ThinLTO is
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -4633,6 +4633,9 @@
     if (isUsingLTO() && TargetDeviceOffloadKind == Action::OFK_None) {
       types::ID Output =
           Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
+      if (Args.hasArg(options::OPT_fembedded_lto))
+        Output = types::TY_PP_Asm;
+
       return C.MakeAction<BackendJobAction>(Input, Output);
     }
     if (isUsingLTO(/* IsOffload */ true) &&
Index: clang/lib/CodeGen/BackendUtil.cpp
===================================================================
--- clang/lib/CodeGen/BackendUtil.cpp
+++ clang/lib/CodeGen/BackendUtil.cpp
@@ -25,6 +25,7 @@
 #include "llvm/Bitcode/BitcodeReader.h"
 #include "llvm/Bitcode/BitcodeWriter.h"
 #include "llvm/Bitcode/BitcodeWriterPass.h"
+#include "llvm/Bitcode/EmbedBitcodePass.h"
 #include "llvm/CodeGen/RegAllocRegistry.h"
 #include "llvm/CodeGen/SchedulerRegistry.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
@@ -970,6 +971,17 @@
     break;
   }
 
+  // Run pass to embed the bitcode into the module to preserve for
+  // LTO usage.
+  if (CodeGenOpts.EmbedLTOObjects) {
+    if (!TheModule->getModuleFlag("ThinLTO"))
+      TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
+    if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
+      TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
+                               uint32_t(1));
+    MPM.addPass(EmbedBitcodePass());
+  }
+
   // Now that we have all of the passes ready, run them.
   {
     PrettyStackTraceString CrashInfo("Optimizer");
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2174,6 +2174,11 @@
   Flags<[CoreOption, CC1Option]>, Group<f_Group>,
   HelpText<"Write minimized bitcode to <file> for the ThinLTO thin link only">,
   MarshallingInfoString<CodeGenOpts<"ThinLinkBitcodeFile">>;
+
+def fembedded_lto : Flag<["-"], "fembedded-lto">, Flags<[CC1Option]>,
+  HelpText<"Embed the bitcode into the module and generate object code from an -flto compile.">,
+  MarshallingInfoFlag<CodeGenOpts<"EmbedLTOObjects">>;
+
 def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">,
                                 Group<f_Group>, Flags<[NoXarchOption, CoreOption]>;
 defm merge_all_constants : BoolFOption<"merge-all-constants",
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -358,6 +358,7 @@
 CODEGENOPT(VirtualFunctionElimination, 1, 0) ///< Whether to apply the dead
                                              /// virtual function elimination
                                              /// optimization.
+CODEGENOPT(EmbedLTOObjects, 1, 0)
 
 /// Whether to use public LTO visibility for entities in std and stdext
 /// namespaces. This is enabled by clang-cl's /MT and /MTd flags.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to