Add a -S option for producing assembly. I will move more of it to
rust once the necessary APIs are available in C.
This commit is contained in:
parent
790084ced1
commit
2214b6835d
@ -60,12 +60,12 @@ impure fn compile_input(session.session sess,
|
||||
str input, str output,
|
||||
bool shared,
|
||||
bool optimize,
|
||||
bool parse_only,
|
||||
trans.output_type ot,
|
||||
vec[str] library_search_paths) {
|
||||
auto def = tup(0, 0);
|
||||
auto p = parser.new_parser(sess, env, def, input, 0u);
|
||||
auto crate = parse_input(sess, p, input);
|
||||
if (parse_only) {ret;}
|
||||
if (ot == trans.output_type_none) {ret;}
|
||||
crate = creader.read_crates(sess, crate, library_search_paths);
|
||||
crate = resolve.resolve_crate(sess, crate);
|
||||
capture.check_for_captures(sess, crate);
|
||||
@ -74,7 +74,8 @@ impure fn compile_input(session.session sess,
|
||||
auto type_cache = typeck_result._1;
|
||||
// FIXME: uncomment once typestate_check works
|
||||
// crate = typestate_check.check_crate(crate);
|
||||
trans.trans_crate(sess, crate, type_cache, output, shared, optimize);
|
||||
trans.trans_crate(sess, crate, type_cache, output, shared, optimize,
|
||||
ot);
|
||||
}
|
||||
|
||||
impure fn pretty_print_input(session.session sess,
|
||||
@ -137,7 +138,7 @@ impure fn main(vec[str] args) {
|
||||
let bool shared = false;
|
||||
let bool pretty = false;
|
||||
let bool ls = false;
|
||||
let bool parse_only = false;
|
||||
auto ot = trans.output_type_bitcode;
|
||||
let bool glue = false;
|
||||
|
||||
// FIXME: Maybe we should support -O0, -O1, -Os, etc
|
||||
@ -163,7 +164,9 @@ impure fn main(vec[str] args) {
|
||||
} else if (_str.eq(arg, "-ls")) {
|
||||
ls = true;
|
||||
} else if (_str.eq(arg, "-parse-only")) {
|
||||
parse_only = true;
|
||||
ot = trans.output_type_none;
|
||||
} else if (_str.eq(arg, "-S")) {
|
||||
ot = trans.output_type_assembly;
|
||||
} else if (_str.eq(arg, "-o")) {
|
||||
if (i+1u < len) {
|
||||
output_file = some(args.(i+1u));
|
||||
@ -207,10 +210,10 @@ impure fn main(vec[str] args) {
|
||||
if (glue) {
|
||||
alt (output_file) {
|
||||
case (none[str]) {
|
||||
middle.trans.make_common_glue("glue.bc", optimize);
|
||||
middle.trans.make_common_glue("glue.bc", optimize, ot);
|
||||
}
|
||||
case (some[str](?s)) {
|
||||
middle.trans.make_common_glue(s, optimize);
|
||||
middle.trans.make_common_glue(s, optimize, ot);
|
||||
}
|
||||
}
|
||||
ret;
|
||||
@ -236,12 +239,12 @@ impure fn main(vec[str] args) {
|
||||
parts += vec(".bc");
|
||||
auto ofile = _str.concat(parts);
|
||||
compile_input(sess, env, ifile, ofile, shared,
|
||||
optimize, parse_only,
|
||||
optimize, ot,
|
||||
library_search_paths);
|
||||
}
|
||||
case (some[str](?ofile)) {
|
||||
compile_input(sess, env, ifile, ofile, shared,
|
||||
optimize, parse_only,
|
||||
optimize, ot,
|
||||
library_search_paths);
|
||||
}
|
||||
}
|
||||
|
@ -815,6 +815,9 @@ native mod llvm = llvm_lib {
|
||||
fn LLVMRustCreateMemoryBufferWithContentsOfFile(sbuf Path) ->
|
||||
MemoryBufferRef;
|
||||
|
||||
fn LLVMRustWriteAssembly(PassManagerRef PM, ModuleRef M,
|
||||
sbuf Triple, sbuf Output);
|
||||
|
||||
/** Returns a string describing the last error caused by an LLVMRust*
|
||||
call. */
|
||||
fn LLVMRustGetLastError() -> sbuf;
|
||||
|
@ -6675,8 +6675,14 @@ fn trap(@block_ctxt bcx) {
|
||||
let vec[ValueRef] v = vec();
|
||||
bcx.build.Call(bcx.fcx.ccx.intrinsics.get("llvm.trap"), v);
|
||||
}
|
||||
tag output_type {
|
||||
output_type_none;
|
||||
output_type_bitcode;
|
||||
output_type_assembly;
|
||||
}
|
||||
|
||||
fn run_passes(ModuleRef llmod, bool opt) {
|
||||
fn run_passes(ModuleRef llmod, bool opt, str output,
|
||||
output_type ot) {
|
||||
auto pm = mk_pass_manager();
|
||||
|
||||
// TODO: run the linter here also, once there are llvm-c bindings for it.
|
||||
@ -6741,7 +6747,18 @@ fn run_passes(ModuleRef llmod, bool opt) {
|
||||
llvm.LLVMAddConstantMergePass(pm.llpm);
|
||||
}
|
||||
llvm.LLVMAddVerifierPass(pm.llpm);
|
||||
|
||||
if (ot == output_type_assembly) {
|
||||
llvm.LLVMRustWriteAssembly(pm.llpm, llmod,
|
||||
_str.buf(x86.get_target_triple()),
|
||||
_str.buf(output));
|
||||
ret;
|
||||
}
|
||||
|
||||
llvm.LLVMRunPassManager(pm.llpm, llmod);
|
||||
|
||||
llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output));
|
||||
llvm.LLVMDisposeModule(llmod);
|
||||
}
|
||||
|
||||
fn decl_no_op_type_glue(ModuleRef llmod, type_names tn) -> ValueRef {
|
||||
@ -7073,7 +7090,8 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns {
|
||||
vec_append_glue = make_vec_append_glue(llmod, tn));
|
||||
}
|
||||
|
||||
fn make_common_glue(str output, bool optimize) {
|
||||
fn make_common_glue(str output, bool optimize,
|
||||
output_type ot) {
|
||||
// FIXME: part of this is repetitive and is probably a good idea
|
||||
// to autogen it, but things like the memcpy implementation are not
|
||||
// and it might be better to just check in a .ll file.
|
||||
@ -7099,15 +7117,12 @@ fn make_common_glue(str output, bool optimize) {
|
||||
|
||||
trans_exit_task_glue(glues, new_str_hash[ValueRef](), tn, llmod);
|
||||
|
||||
run_passes(llmod, optimize);
|
||||
|
||||
llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output));
|
||||
llvm.LLVMDisposeModule(llmod);
|
||||
run_passes(llmod, optimize, output, ot);
|
||||
}
|
||||
|
||||
fn trans_crate(session.session sess, @ast.crate crate,
|
||||
&ty.type_cache type_cache, str output, bool shared,
|
||||
bool optimize) {
|
||||
bool optimize, output_type ot) {
|
||||
auto llmod =
|
||||
llvm.LLVMModuleCreateWithNameInContext(_str.buf("rust_out"),
|
||||
llvm.LLVMGetGlobalContext());
|
||||
@ -7170,10 +7185,7 @@ fn trans_crate(session.session sess, @ast.crate crate,
|
||||
// Translate the metadata.
|
||||
middle.metadata.write_metadata(cx, crate);
|
||||
|
||||
run_passes(llmod, optimize);
|
||||
|
||||
llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output));
|
||||
llvm.LLVMDisposeModule(llmod);
|
||||
run_passes(llmod, optimize, output, ot);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -12,10 +12,18 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Target/TargetRegistry.h"
|
||||
#include "llvm-c/Core.h"
|
||||
#include "llvm-c/Object.h"
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static char *LLVMRustError;
|
||||
|
||||
extern "C" LLVMMemoryBufferRef
|
||||
@ -33,3 +41,24 @@ extern "C" void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM);
|
||||
|
||||
void (*RustHackToFetchPassesO)(LLVMPassManagerRef PM) =
|
||||
LLVMAddBasicAliasAnalysisPass;
|
||||
|
||||
extern "C" void LLVMRustWriteAssembly(LLVMPassManagerRef PMR, LLVMModuleRef M,
|
||||
const char *triple, const char *path) {
|
||||
InitializeAllTargets();
|
||||
InitializeAllAsmPrinters();
|
||||
std::string Err;
|
||||
const Target *TheTarget = TargetRegistry::lookupTarget(triple, Err);
|
||||
std::string FeaturesStr;
|
||||
TargetMachine &Target = *TheTarget->createTargetMachine(triple, FeaturesStr);
|
||||
bool NoVerify = false;
|
||||
CodeGenOpt::Level OLvl = CodeGenOpt::Default;
|
||||
TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_AssemblyFile;
|
||||
PassManager *PM = unwrap<PassManager>(PMR);
|
||||
std::string ErrorInfo;
|
||||
raw_fd_ostream OS(path, ErrorInfo,
|
||||
raw_fd_ostream::F_Binary);
|
||||
formatted_raw_ostream FOS(OS);
|
||||
bool foo = Target.addPassesToEmitFile(*PM, FOS, FileType, OLvl, NoVerify);
|
||||
assert(!foo);
|
||||
PM->run(*unwrap(M));
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
LLVMRustCreateMemoryBufferWithContentsOfFile
|
||||
LLVMRustWriteAssembly
|
||||
LLVMRustGetLastError
|
||||
LLVMCreateObjectFile
|
||||
LLVMDisposeObjectFile
|
||||
|
Loading…
x
Reference in New Issue
Block a user