|
| 1 | +import driver.session; |
| 2 | +import lib.llvm.llvm; |
| 3 | +import middle.trans; |
| 4 | +import std._str; |
| 5 | + |
| 6 | +import lib.llvm.llvm.ModuleRef; |
| 7 | +import lib.llvm.llvm.ValueRef; |
| 8 | +import lib.llvm.mk_pass_manager; |
| 9 | +import lib.llvm.mk_target_data; |
| 10 | +import lib.llvm.mk_type_names; |
| 11 | + |
| 12 | +tag output_type { |
| 13 | + output_type_none; |
| 14 | + output_type_bitcode; |
| 15 | + output_type_assembly; |
| 16 | + output_type_object; |
| 17 | +} |
| 18 | + |
| 19 | +mod Write { |
| 20 | + fn is_object_or_assembly(output_type ot) -> bool { |
| 21 | + if (ot == output_type_assembly) { |
| 22 | + ret true; |
| 23 | + } |
| 24 | + if (ot == output_type_object) { |
| 25 | + ret true; |
| 26 | + } |
| 27 | + ret false; |
| 28 | + } |
| 29 | + |
| 30 | + // Decides what to call an intermediate file, given the name of the output |
| 31 | + // and the extension to use. |
| 32 | + fn mk_intermediate_name(str output_path, str extension) -> str { |
| 33 | + auto dot_pos = _str.index(output_path, '.' as u8); |
| 34 | + auto stem; |
| 35 | + if (dot_pos < 0) { |
| 36 | + stem = output_path; |
| 37 | + } else { |
| 38 | + stem = _str.substr(output_path, 0u, dot_pos as uint); |
| 39 | + } |
| 40 | + ret stem + "." + extension; |
| 41 | + } |
| 42 | + |
| 43 | + fn run_passes(session.session sess, ModuleRef llmod, str output) { |
| 44 | + auto pm = mk_pass_manager(); |
| 45 | + auto opts = sess.get_opts(); |
| 46 | + |
| 47 | + // TODO: run the linter here also, once there are llvm-c bindings for |
| 48 | + // it. |
| 49 | + |
| 50 | + // Generate a pre-optimization intermediate file if -save-temps was |
| 51 | + // specified. |
| 52 | + if (opts.save_temps) { |
| 53 | + alt (opts.output_type) { |
| 54 | + case (output_type_bitcode) { |
| 55 | + if (opts.optimize) { |
| 56 | + auto filename = mk_intermediate_name(output, |
| 57 | + "no-opt.bc"); |
| 58 | + llvm.LLVMWriteBitcodeToFile(llmod, |
| 59 | + _str.buf(filename)); |
| 60 | + } |
| 61 | + } |
| 62 | + case (_) { |
| 63 | + auto filename = mk_intermediate_name(output, "bc"); |
| 64 | + llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(filename)); |
| 65 | + } |
| 66 | + } |
| 67 | + } |
| 68 | + |
| 69 | + // FIXME: This is mostly a copy of the bits of opt's -O2 that are |
| 70 | + // available in the C api. |
| 71 | + // FIXME2: We might want to add optimization levels like -O1, -O2, |
| 72 | + // -Os, etc |
| 73 | + // FIXME3: Should we expose and use the pass lists used by the opt |
| 74 | + // tool? |
| 75 | + if (opts.optimize) { |
| 76 | + auto fpm = mk_pass_manager(); |
| 77 | + |
| 78 | + // createStandardFunctionPasses |
| 79 | + llvm.LLVMAddTypeBasedAliasAnalysisPass(fpm.llpm); |
| 80 | + llvm.LLVMAddBasicAliasAnalysisPass(fpm.llpm); |
| 81 | + llvm.LLVMAddCFGSimplificationPass(fpm.llpm); |
| 82 | + llvm.LLVMAddScalarReplAggregatesPass(fpm.llpm); |
| 83 | + llvm.LLVMAddEarlyCSEPass(fpm.llpm); |
| 84 | + |
| 85 | + llvm.LLVMRunPassManager(fpm.llpm, llmod); |
| 86 | + |
| 87 | + // createStandardModulePasses |
| 88 | + llvm.LLVMAddTypeBasedAliasAnalysisPass(pm.llpm); |
| 89 | + llvm.LLVMAddBasicAliasAnalysisPass(pm.llpm); |
| 90 | + llvm.LLVMAddGlobalOptimizerPass(pm.llpm); |
| 91 | + llvm.LLVMAddIPSCCPPass(pm.llpm); |
| 92 | + llvm.LLVMAddDeadArgEliminationPass(pm.llpm); |
| 93 | + llvm.LLVMAddInstructionCombiningPass(pm.llpm); |
| 94 | + llvm.LLVMAddCFGSimplificationPass(pm.llpm); |
| 95 | + llvm.LLVMAddPruneEHPass(pm.llpm); |
| 96 | + llvm.LLVMAddFunctionInliningPass(pm.llpm); |
| 97 | + llvm.LLVMAddFunctionAttrsPass(pm.llpm); |
| 98 | + llvm.LLVMAddScalarReplAggregatesPassSSA(pm.llpm); |
| 99 | + llvm.LLVMAddEarlyCSEPass(pm.llpm); |
| 100 | + llvm.LLVMAddSimplifyLibCallsPass(pm.llpm); |
| 101 | + llvm.LLVMAddJumpThreadingPass(pm.llpm); |
| 102 | + llvm.LLVMAddCorrelatedValuePropagationPass(pm.llpm); |
| 103 | + llvm.LLVMAddCFGSimplificationPass(pm.llpm); |
| 104 | + llvm.LLVMAddInstructionCombiningPass(pm.llpm); |
| 105 | + llvm.LLVMAddTailCallEliminationPass(pm.llpm); |
| 106 | + llvm.LLVMAddCFGSimplificationPass(pm.llpm); |
| 107 | + llvm.LLVMAddReassociatePass(pm.llpm); |
| 108 | + llvm.LLVMAddLoopRotatePass(pm.llpm); |
| 109 | + llvm.LLVMAddLICMPass(pm.llpm); |
| 110 | + llvm.LLVMAddLoopUnswitchPass(pm.llpm); |
| 111 | + llvm.LLVMAddInstructionCombiningPass(pm.llpm); |
| 112 | + llvm.LLVMAddIndVarSimplifyPass(pm.llpm); |
| 113 | + llvm.LLVMAddLoopIdiomPass(pm.llpm); |
| 114 | + llvm.LLVMAddLoopDeletionPass(pm.llpm); |
| 115 | + llvm.LLVMAddLoopUnrollPass(pm.llpm); |
| 116 | + llvm.LLVMAddInstructionCombiningPass(pm.llpm); |
| 117 | + llvm.LLVMAddGVNPass(pm.llpm); |
| 118 | + llvm.LLVMAddMemCpyOptPass(pm.llpm); |
| 119 | + llvm.LLVMAddSCCPPass(pm.llpm); |
| 120 | + llvm.LLVMAddInstructionCombiningPass(pm.llpm); |
| 121 | + llvm.LLVMAddJumpThreadingPass(pm.llpm); |
| 122 | + llvm.LLVMAddCorrelatedValuePropagationPass(pm.llpm); |
| 123 | + llvm.LLVMAddDeadStoreEliminationPass(pm.llpm); |
| 124 | + llvm.LLVMAddAggressiveDCEPass(pm.llpm); |
| 125 | + llvm.LLVMAddCFGSimplificationPass(pm.llpm); |
| 126 | + llvm.LLVMAddStripDeadPrototypesPass(pm.llpm); |
| 127 | + llvm.LLVMAddDeadTypeEliminationPass(pm.llpm); |
| 128 | + llvm.LLVMAddConstantMergePass(pm.llpm); |
| 129 | + } |
| 130 | + |
| 131 | + if (opts.verify) { |
| 132 | + llvm.LLVMAddVerifierPass(pm.llpm); |
| 133 | + } |
| 134 | + |
| 135 | + // TODO: Write .s if -c was specified and -save-temps was on. |
| 136 | + if (is_object_or_assembly(opts.output_type)) { |
| 137 | + let int LLVMAssemblyFile = 0; |
| 138 | + let int LLVMObjectFile = 1; |
| 139 | + let int LLVMNullFile = 2; |
| 140 | + auto FileType; |
| 141 | + if (opts.output_type == output_type_object) { |
| 142 | + FileType = LLVMObjectFile; |
| 143 | + } else { |
| 144 | + FileType = LLVMAssemblyFile; |
| 145 | + } |
| 146 | + |
| 147 | + // Write optimized bitcode if --save-temps was on. |
| 148 | + if (opts.save_temps) { |
| 149 | + alt (opts.output_type) { |
| 150 | + case (output_type_bitcode) { /* nothing to do */ } |
| 151 | + case (_) { |
| 152 | + auto filename = mk_intermediate_name(output, |
| 153 | + "opt.bc"); |
| 154 | + llvm.LLVMRunPassManager(pm.llpm, llmod); |
| 155 | + llvm.LLVMWriteBitcodeToFile(llmod, |
| 156 | + _str.buf(filename)); |
| 157 | + pm = mk_pass_manager(); |
| 158 | + } |
| 159 | + } |
| 160 | + } |
| 161 | + |
| 162 | + llvm.LLVMRustWriteOutputFile(pm.llpm, llmod, |
| 163 | + _str.buf(x86.get_target_triple()), |
| 164 | + _str.buf(output), |
| 165 | + FileType); |
| 166 | + llvm.LLVMDisposeModule(llmod); |
| 167 | + ret; |
| 168 | + } |
| 169 | + |
| 170 | + llvm.LLVMRunPassManager(pm.llpm, llmod); |
| 171 | + |
| 172 | + llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output)); |
| 173 | + llvm.LLVMDisposeModule(llmod); |
| 174 | + } |
| 175 | +} |
| 176 | + |
0 commit comments