createEmbedObjectFile creates a new object file with the given contents, for the embed package.
(data, hexSum, sourceFile, sourceDir, tmpdir string, compilerConfig *compiler.Config)
| 1089 | // createEmbedObjectFile creates a new object file with the given contents, for |
| 1090 | // the embed package. |
| 1091 | func createEmbedObjectFile(data, hexSum, sourceFile, sourceDir, tmpdir string, compilerConfig *compiler.Config) (string, error) { |
| 1092 | // TODO: this works for small files, but can be a problem for larger files. |
| 1093 | // For larger files, it seems more appropriate to generate the object file |
| 1094 | // manually without going through LLVM. |
| 1095 | // On the other hand, generating DWARF like we do here can be difficult |
| 1096 | // without assistance from LLVM. |
| 1097 | |
| 1098 | // Create new LLVM module just for this file. |
| 1099 | ctx := llvm.NewContext() |
| 1100 | defer ctx.Dispose() |
| 1101 | mod := ctx.NewModule("data") |
| 1102 | defer mod.Dispose() |
| 1103 | |
| 1104 | // Create data global. |
| 1105 | value := ctx.ConstString(data, false) |
| 1106 | globalName := "embed/file_" + hexSum |
| 1107 | global := llvm.AddGlobal(mod, value.Type(), globalName) |
| 1108 | global.SetInitializer(value) |
| 1109 | global.SetLinkage(llvm.LinkOnceODRLinkage) |
| 1110 | global.SetGlobalConstant(true) |
| 1111 | global.SetUnnamedAddr(true) |
| 1112 | global.SetAlignment(1) |
| 1113 | if compilerConfig.GOOS != "darwin" { |
| 1114 | // MachO doesn't support COMDATs, while COFF requires it (to avoid |
| 1115 | // "duplicate symbol" errors). ELF works either way. |
| 1116 | // Therefore, only use a COMDAT on non-MachO systems (aka non-MacOS). |
| 1117 | global.SetComdat(mod.Comdat(globalName)) |
| 1118 | } |
| 1119 | |
| 1120 | // Add DWARF debug information to this global, so that it is |
| 1121 | // correctly counted when compiling with the -size= flag. |
| 1122 | dibuilder := llvm.NewDIBuilder(mod) |
| 1123 | dibuilder.CreateCompileUnit(llvm.DICompileUnit{ |
| 1124 | Language: 0xb, // DW_LANG_C99 (0xc, off-by-one?) |
| 1125 | File: sourceFile, |
| 1126 | Dir: sourceDir, |
| 1127 | Producer: "TinyGo", |
| 1128 | Optimized: false, |
| 1129 | }) |
| 1130 | ditype := dibuilder.CreateArrayType(llvm.DIArrayType{ |
| 1131 | SizeInBits: uint64(len(data)) * 8, |
| 1132 | AlignInBits: 8, |
| 1133 | ElementType: dibuilder.CreateBasicType(llvm.DIBasicType{ |
| 1134 | Name: "byte", |
| 1135 | SizeInBits: 8, |
| 1136 | Encoding: llvm.DW_ATE_unsigned_char, |
| 1137 | }), |
| 1138 | Subscripts: []llvm.DISubrange{ |
| 1139 | { |
| 1140 | Lo: 0, |
| 1141 | Count: int64(len(data)), |
| 1142 | }, |
| 1143 | }, |
| 1144 | }) |
| 1145 | difile := dibuilder.CreateFile(sourceFile, sourceDir) |
| 1146 | diglobalexpr := dibuilder.CreateGlobalVariableExpression(difile, llvm.DIGlobalVariableExpression{ |
| 1147 | Name: globalName, |
| 1148 | File: difile, |