Add debug info for local vars, basic fundamental types, and lexical blocks, along with source line information generation for individual instructions.
This commit is contained in:
parent
10030a37d5
commit
e383004985
@ -234,9 +234,11 @@ native mod llvm {
|
||||
/* Operations on other types */
|
||||
fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef;
|
||||
fn LLVMLabelTypeInContext(C: ContextRef) -> TypeRef;
|
||||
fn LLVMMetadataTypeInContext(C: ContextRef) -> TypeRef;
|
||||
|
||||
fn LLVMVoidType() -> TypeRef;
|
||||
fn LLVMLabelType() -> TypeRef;
|
||||
fn LLVMMetadataType() -> TypeRef;
|
||||
|
||||
/* Operations on all values */
|
||||
fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
|
||||
|
@ -1,12 +1,13 @@
|
||||
import std::{vec, str, map, option, unsafe};
|
||||
import std::vec::to_ptr;
|
||||
import std::{vec, str, option, unsafe, fs};
|
||||
import std::map::hashmap;
|
||||
import lib::llvm::llvm;
|
||||
import lib::llvm::llvm::{ModuleRef, ValueRef};
|
||||
import lib::llvm::llvm::ValueRef;
|
||||
import middle::trans_common::*;
|
||||
import middle::ty;
|
||||
import ast::ty;
|
||||
import syntax::{ast, codemap};
|
||||
|
||||
const LLVMDebugVersion: int = 0x80000;
|
||||
const LLVMDebugVersion: int = (9 << 16); //& 0xffff0000; // 0x80000 ?
|
||||
|
||||
const DW_LANG_RUST: int = 0x9000;
|
||||
const DW_VIRTUALITY_none: int = 0;
|
||||
@ -14,6 +15,18 @@ const DW_VIRTUALITY_none: int = 0;
|
||||
const CompileUnitTag: int = 17;
|
||||
const FileDescriptorTag: int = 41;
|
||||
const SubprogramTag: int = 46;
|
||||
const BasicTypeDescriptorTag: int = 36;
|
||||
const AutoVariableTag: int = 256;
|
||||
const ArgVariableTag: int = 257;
|
||||
const ReturnVariableTag: int = 258;
|
||||
const LexicalBlockTag: int = 11;
|
||||
|
||||
const DW_ATE_boolean: int = 0x02;
|
||||
const DW_ATE_float: int = 0x04;
|
||||
const DW_ATE_signed: int = 0x05;
|
||||
const DW_ATE_signed_char: int = 0x06;
|
||||
const DW_ATE_unsigned: int = 0x07;
|
||||
const DW_ATE_unsigned_char: int = 0x08;
|
||||
|
||||
fn as_buf(s: str) -> str::sbuf {
|
||||
str::as_buf(s, {|sbuf| sbuf})
|
||||
@ -23,11 +36,14 @@ fn llstr(s: str) -> ValueRef {
|
||||
}
|
||||
|
||||
fn lltag(lltag: int) -> ValueRef {
|
||||
lli32(0x80000 + lltag)
|
||||
lli32(LLVMDebugVersion | lltag)
|
||||
}
|
||||
fn lli32(val: int) -> ValueRef {
|
||||
C_i32(val as i32)
|
||||
}
|
||||
fn lli64(val: int) -> ValueRef {
|
||||
C_i64(val as i64)
|
||||
}
|
||||
fn lli1(bval: bool) -> ValueRef {
|
||||
C_bool(bval)
|
||||
}
|
||||
@ -38,6 +54,9 @@ fn llmdnode(elems: [ValueRef]) -> ValueRef unsafe {
|
||||
fn llunused() -> ValueRef {
|
||||
lli32(0x0)
|
||||
}
|
||||
fn llnull() -> ValueRef {
|
||||
C_null(T_ptr(T_nil()))
|
||||
}
|
||||
|
||||
fn update_cache(cache: metadata_cache, mdtag: int, val: debug_metadata) {
|
||||
let existing = if cache.contains_key(mdtag) {
|
||||
@ -55,6 +74,9 @@ type metadata<T> = {node: ValueRef, data: T};
|
||||
type file_md = {path: str};
|
||||
type compile_unit_md = {path: str};
|
||||
type subprogram_md = {name: str, file: str};
|
||||
type local_var_md = {id: ast::node_id};
|
||||
type tydesc_md = {hash: uint};
|
||||
type block_md = {start: codemap::loc, end: codemap::loc};
|
||||
|
||||
type metadata_cache = hashmap<int, [debug_metadata]>;
|
||||
|
||||
@ -62,18 +84,31 @@ tag debug_metadata {
|
||||
file_metadata(@metadata<file_md>);
|
||||
compile_unit_metadata(@metadata<compile_unit_md>);
|
||||
subprogram_metadata(@metadata<subprogram_md>);
|
||||
local_var_metadata(@metadata<local_var_md>);
|
||||
tydesc_metadata(@metadata<tydesc_md>);
|
||||
block_metadata(@metadata<block_md>);
|
||||
}
|
||||
|
||||
fn cast_safely<T, U>(val: T) -> U unsafe {
|
||||
let val2 = val;
|
||||
let val3 = unsafe::reinterpret_cast(val2);
|
||||
unsafe::leak(val2);
|
||||
ret val3;
|
||||
}
|
||||
|
||||
fn md_from_metadata<T>(val: debug_metadata) -> T unsafe {
|
||||
alt val {
|
||||
file_metadata(md) { unsafe::reinterpret_cast(md) }
|
||||
compile_unit_metadata(md) { unsafe::reinterpret_cast(md) }
|
||||
subprogram_metadata(md) { unsafe::reinterpret_cast(md) }
|
||||
file_metadata(md) { cast_safely(md) }
|
||||
compile_unit_metadata(md) { cast_safely(md) }
|
||||
subprogram_metadata(md) { cast_safely(md) }
|
||||
local_var_metadata(md) { cast_safely(md) }
|
||||
tydesc_metadata(md) { cast_safely(md) }
|
||||
block_metadata(md) { cast_safely(md) }
|
||||
}
|
||||
}
|
||||
|
||||
fn cached_metadata<T>(cache: metadata_cache, mdtag: int,
|
||||
eq: block(md: T) -> bool) -> option::t<T> {
|
||||
eq: block(md: T) -> bool) -> option::t<T> unsafe {
|
||||
if cache.contains_key(mdtag) {
|
||||
let items = cache.get(mdtag);
|
||||
for item in items {
|
||||
@ -94,10 +129,8 @@ fn get_compile_unit_metadata(cx: @crate_ctxt, full_path: str)
|
||||
option::some(md) { ret md; }
|
||||
option::none. {}
|
||||
}
|
||||
let sep = str::rindex(full_path, '/' as u8) as uint;
|
||||
let fname = str::slice(full_path, sep + 1u,
|
||||
str::byte_len(full_path));
|
||||
let path = str::slice(full_path, 0u, sep + 1u);
|
||||
let fname = fs::basename(full_path);
|
||||
let path = fs::dirname(full_path);
|
||||
let unit_metadata = [lltag(CompileUnitTag),
|
||||
llunused(),
|
||||
lli32(DW_LANG_RUST),
|
||||
@ -122,22 +155,18 @@ fn get_compile_unit_metadata(cx: @crate_ctxt, full_path: str)
|
||||
ret mdval;
|
||||
}
|
||||
|
||||
// let kind_id = llvm::LLVMGetMDKindID(as_buf("dbg"),
|
||||
// str::byte_len("dbg"));
|
||||
|
||||
|
||||
fn get_file_metadata(cx: @crate_ctxt, full_path: str) -> @metadata<file_md> {
|
||||
let cache = cx.llmetadata;
|
||||
alt cached_metadata::<@metadata<file_md>>(
|
||||
cache, FileDescriptorTag, {|md| md.data.path == full_path}) {
|
||||
cache, FileDescriptorTag,
|
||||
{|md|
|
||||
md.data.path == full_path}) {
|
||||
option::some(md) { ret md; }
|
||||
option::none. {}
|
||||
}
|
||||
let sep = str::rindex(full_path, '/' as u8) as uint;
|
||||
let fname = str::slice(full_path, sep + 1u,
|
||||
str::byte_len(full_path));
|
||||
let path = str::slice(full_path, 0u, sep + 1u);
|
||||
let unit_node = get_compile_unit_metadata(cx, path).node;
|
||||
let fname = fs::basename(full_path);
|
||||
let path = fs::dirname(full_path);
|
||||
let unit_node = get_compile_unit_metadata(cx, full_path).node;
|
||||
let file_md = [lltag(FileDescriptorTag),
|
||||
llstr(fname),
|
||||
llstr(path),
|
||||
@ -148,6 +177,162 @@ fn get_file_metadata(cx: @crate_ctxt, full_path: str) -> @metadata<file_md> {
|
||||
ret mdval;
|
||||
}
|
||||
|
||||
fn get_block_metadata(cx: @block_ctxt) -> @metadata<block_md> {
|
||||
let cache = bcx_ccx(cx).llmetadata;
|
||||
let start = codemap::lookup_char_pos(bcx_ccx(cx).sess.get_codemap(),
|
||||
cx.sp.lo);
|
||||
let fname = start.filename;
|
||||
let end = codemap::lookup_char_pos(bcx_ccx(cx).sess.get_codemap(),
|
||||
cx.sp.hi);
|
||||
alt cached_metadata::<@metadata<block_md>>(
|
||||
cache, LexicalBlockTag,
|
||||
{|md| start == md.data.start && end == md.data.end}) {
|
||||
option::some(md) { ret md; }
|
||||
option::none. {}
|
||||
}
|
||||
let parent = alt cx.parent {
|
||||
trans_common::parent_none. { llnull() }
|
||||
trans_common::parent_some(bcx) {
|
||||
get_block_metadata(bcx).node
|
||||
}
|
||||
};
|
||||
let file_node = get_file_metadata(bcx_ccx(cx), fname);
|
||||
let unique_id = alt cache.find(LexicalBlockTag) {
|
||||
option::some(v) { vec::len(v) as int }
|
||||
option::none. { 0 }
|
||||
};
|
||||
let lldata = [lltag(LexicalBlockTag),
|
||||
parent,
|
||||
lli32(start.line as int),
|
||||
lli32(start.col as int),
|
||||
file_node.node,
|
||||
lli32(unique_id)
|
||||
];
|
||||
let val = llmdnode(lldata);
|
||||
let mdval = @{node: val, data: {start: start, end: end}};
|
||||
update_cache(cache, LexicalBlockTag, block_metadata(mdval));
|
||||
ret mdval;
|
||||
}
|
||||
|
||||
fn get_ty_metadata(cx: @crate_ctxt, t: ty::t, ty: @ast::ty) -> @metadata<tydesc_md> {
|
||||
let cache = cx.llmetadata;
|
||||
alt cached_metadata::<@metadata<tydesc_md>>(
|
||||
cache, BasicTypeDescriptorTag,
|
||||
{|md| ty::hash_ty(t) == ty::hash_ty(md.data.hash)}) {
|
||||
option::some(md) { ret md; }
|
||||
option::none. {}
|
||||
}
|
||||
let (name, size, flags) = alt ty.node {
|
||||
ast::ty_bool. { ("bool", 1, DW_ATE_boolean) }
|
||||
ast::ty_int. { ("int", 32, DW_ATE_signed) } //XXX machine-dependent?
|
||||
ast::ty_uint. { ("uint", 32, DW_ATE_unsigned) } //XXX machine-dependent?
|
||||
ast::ty_float. { ("float", 32, DW_ATE_float) } //XXX machine-dependent?
|
||||
ast::ty_machine(m) { alt m {
|
||||
ast::ty_i8. { ("i8", 1, DW_ATE_signed_char) }
|
||||
ast::ty_i16. { ("i16", 16, DW_ATE_signed) }
|
||||
ast::ty_i32. { ("i32", 32, DW_ATE_signed) }
|
||||
ast::ty_i64. { ("i64", 64, DW_ATE_signed) }
|
||||
ast::ty_u8. { ("u8", 8, DW_ATE_unsigned_char) }
|
||||
ast::ty_u16. { ("u16", 16, DW_ATE_unsigned) }
|
||||
ast::ty_u32. { ("u32", 32, DW_ATE_unsigned) }
|
||||
ast::ty_u64. { ("u64", 64, DW_ATE_unsigned) }
|
||||
ast::ty_f32. { ("f32", 32, DW_ATE_float) }
|
||||
ast::ty_f64. { ("f64", 64, DW_ATE_float) }
|
||||
} }
|
||||
ast::ty_char. { ("char", 32, DW_ATE_unsigned) }
|
||||
};
|
||||
let lldata = [lltag(BasicTypeDescriptorTag),
|
||||
llunused(), //XXX scope context
|
||||
llstr(name),
|
||||
llnull(), //XXX basic types only
|
||||
lli32(0), //XXX basic types only
|
||||
lli64(size),
|
||||
lli64(32), //XXX alignment?
|
||||
lli64(0), //XXX offset?
|
||||
lli32(flags)];
|
||||
let llnode = llmdnode(lldata);
|
||||
let mdval = @{node: llnode, data: {hash: ty::hash_ty(t)}};
|
||||
update_cache(cache, BasicTypeDescriptorTag, tydesc_metadata(mdval));
|
||||
ret mdval;
|
||||
}
|
||||
|
||||
fn get_local_var_metadata(bcx: @block_ctxt, local: @ast::local)
|
||||
-> @metadata<local_var_md> unsafe {
|
||||
let cx = bcx_ccx(bcx);
|
||||
let cache = cx.llmetadata;
|
||||
alt cached_metadata::<@metadata<local_var_md>>(
|
||||
cache, AutoVariableTag, {|md| md.data.id == local.node.id}) {
|
||||
option::some(md) { ret md; }
|
||||
option::none. {}
|
||||
}
|
||||
let name = alt local.node.pat.node {
|
||||
ast::pat_bind(ident) { ident }
|
||||
};
|
||||
let loc = codemap::lookup_char_pos(cx.sess.get_codemap(),
|
||||
local.span.lo);
|
||||
let ty = trans::node_id_type(cx, local.node.id);
|
||||
let tymd = get_ty_metadata(cx, ty, local.node.ty);
|
||||
let filemd = get_file_metadata(cx, loc.filename);
|
||||
let blockmd = get_block_metadata(bcx);
|
||||
let lldata = [lltag(AutoVariableTag),
|
||||
blockmd.node, //XXX block context (maybe subprogram if possible?)
|
||||
llstr(name), // name
|
||||
filemd.node,
|
||||
lli32(loc.line as int), // line
|
||||
tymd.node,
|
||||
lli32(0), //XXX flags
|
||||
llnull() // inline loc reference
|
||||
];
|
||||
let mdnode = llmdnode(lldata);
|
||||
let mdval = @{node: mdnode, data: {id: local.node.id}};
|
||||
update_cache(cache, AutoVariableTag, local_var_metadata(mdval));
|
||||
let llptr = alt bcx.fcx.lllocals.find(local.node.id) {
|
||||
option::some(local_mem(v)) { v }
|
||||
option::none. {
|
||||
alt bcx.fcx.lllocals.get(local.node.pat.id) {
|
||||
local_imm(v) { v }
|
||||
}
|
||||
}
|
||||
};
|
||||
let declargs = [llmdnode([llptr]), mdnode];
|
||||
let instr = trans_build::Call(bcx, cx.intrinsics.get("llvm.dbg.declare"),
|
||||
declargs);
|
||||
llvm::LLVMAddNamedMetadataOperand(cx.llmod, as_buf("llvm.dbg.vars"),
|
||||
str::byte_len("llvm.dbg.vars"),
|
||||
mdnode);
|
||||
ret mdval;
|
||||
}
|
||||
|
||||
fn update_source_pos<T>(cx: @block_ctxt, s: T) {
|
||||
if !bcx_ccx(cx).sess.get_opts().debuginfo {
|
||||
ret;
|
||||
}
|
||||
cx.source_pos = option::some(
|
||||
codemap::lookup_char_pos(bcx_ccx(cx).sess.get_codemap(),
|
||||
s.span.lo)); //XXX maybe hi
|
||||
|
||||
}
|
||||
|
||||
fn reset_source_pos(cx: @block_ctxt) {
|
||||
cx.source_pos = option::none;
|
||||
}
|
||||
|
||||
fn add_line_info(cx: @block_ctxt, llinstr: ValueRef) {
|
||||
if !bcx_ccx(cx).sess.get_opts().debuginfo ||
|
||||
option::is_none(cx.source_pos) {
|
||||
ret;
|
||||
}
|
||||
let loc = option::get(cx.source_pos);
|
||||
let blockmd = get_block_metadata(cx);
|
||||
let kind_id = llvm::LLVMGetMDKindID(as_buf("dbg"), str::byte_len("dbg"));
|
||||
let scopedata = [lli32(loc.line as int),
|
||||
lli32(loc.col as int),
|
||||
blockmd.node,
|
||||
llnull()];
|
||||
let dbgscope = llmdnode(scopedata);
|
||||
llvm::LLVMSetMetadata(llinstr, kind_id, dbgscope);
|
||||
}
|
||||
|
||||
fn get_function_metadata(cx: @crate_ctxt, item: @ast::item,
|
||||
llfndecl: ValueRef) -> @metadata<subprogram_md> {
|
||||
let cache = cx.llmetadata;
|
||||
@ -160,20 +345,29 @@ fn get_function_metadata(cx: @crate_ctxt, item: @ast::item,
|
||||
let loc = codemap::lookup_char_pos(cx.sess.get_codemap(),
|
||||
item.span.lo);
|
||||
let file_node = get_file_metadata(cx, loc.filename).node;
|
||||
let mangled = cx.item_symbols.get(item.id);
|
||||
let ret_ty = alt item.node {
|
||||
ast::item_fn(f, _) { f.decl.output }
|
||||
};
|
||||
let ty_node = alt ret_ty.node {
|
||||
ast::ty_nil. { llnull() }
|
||||
_ { get_ty_metadata(cx, ty::node_id_to_type(ccx_tcx(cx), item.id),
|
||||
ret_ty).node }
|
||||
};
|
||||
let fn_metadata = [lltag(SubprogramTag),
|
||||
llunused(),
|
||||
file_node,
|
||||
llstr(item.ident),
|
||||
llstr(item.ident), //XXX fully-qualified C++ name
|
||||
llstr(item.ident), //XXX MIPS name?????
|
||||
llstr(mangled), //XXX MIPS name?????
|
||||
file_node,
|
||||
lli32(loc.line as int),
|
||||
C_null(T_ptr(T_nil())), // XXX reference to tydesc
|
||||
lli1(false), //XXX static
|
||||
ty_node,
|
||||
lli1(false), //XXX static (check export)
|
||||
lli1(true), // not extern
|
||||
lli32(DW_VIRTUALITY_none), // virtual-ness
|
||||
lli32(0i), //index into virt func
|
||||
C_null(T_ptr(T_nil())), // base type with vtbl
|
||||
llnull(), // base type with vtbl
|
||||
lli1(false), // artificial
|
||||
lli1(cx.sess.get_opts().optimize != 0u),
|
||||
llfndecl
|
||||
|
@ -3519,6 +3519,8 @@ fn trans_temp_expr(bcx: @block_ctxt, e: @ast::expr) -> result {
|
||||
// - exprs with non-immediate type never get dest=by_val
|
||||
fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
||||
let tcx = bcx_tcx(bcx);
|
||||
debuginfo::update_source_pos(bcx, e);
|
||||
|
||||
if expr_is_lval(bcx, e) {
|
||||
ret lval_to_dps(bcx, e, dest);
|
||||
}
|
||||
@ -4012,6 +4014,8 @@ fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {
|
||||
}
|
||||
|
||||
let bcx = cx;
|
||||
debuginfo::update_source_pos(cx, s);
|
||||
|
||||
alt s.node {
|
||||
ast::stmt_expr(e, _) { bcx = trans_expr(cx, e, ignore); }
|
||||
ast::stmt_decl(d, _) {
|
||||
@ -4023,6 +4027,9 @@ fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {
|
||||
} else {
|
||||
bcx = init_ref_local(bcx, local);
|
||||
}
|
||||
if bcx_ccx(cx).sess.get_opts().debuginfo {
|
||||
debuginfo::get_local_var_metadata(bcx, local);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::decl_item(i) { trans_item(cx.fcx.lcx, *i); }
|
||||
@ -4030,6 +4037,8 @@ fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {
|
||||
}
|
||||
_ { bcx_ccx(cx).sess.unimpl("stmt variant"); }
|
||||
}
|
||||
|
||||
debuginfo::reset_source_pos(cx);
|
||||
ret bcx;
|
||||
}
|
||||
|
||||
@ -4053,7 +4062,8 @@ fn new_block_ctxt(cx: @fn_ctxt, parent: block_parent, kind: block_kind,
|
||||
mutable lpad_dirty: true,
|
||||
mutable lpad: option::none,
|
||||
sp: cx.sp,
|
||||
fcx: cx};
|
||||
fcx: cx,
|
||||
mutable source_pos: option::none};
|
||||
alt parent {
|
||||
parent_some(cx) {
|
||||
if cx.unreachable { Unreachable(bcx); }
|
||||
@ -4097,7 +4107,8 @@ fn new_raw_block_ctxt(fcx: @fn_ctxt, llbb: BasicBlockRef) -> @block_ctxt {
|
||||
mutable lpad_dirty: true,
|
||||
mutable lpad: option::none,
|
||||
sp: fcx.sp,
|
||||
fcx: fcx};
|
||||
fcx: fcx,
|
||||
mutable source_pos: option::none};
|
||||
}
|
||||
|
||||
|
||||
@ -4164,7 +4175,8 @@ fn llstaticallocas_block_ctxt(fcx: @fn_ctxt) -> @block_ctxt {
|
||||
mutable lpad_dirty: true,
|
||||
mutable lpad: option::none,
|
||||
sp: fcx.sp,
|
||||
fcx: fcx};
|
||||
fcx: fcx,
|
||||
mutable source_pos: option::none};
|
||||
}
|
||||
|
||||
fn llderivedtydescs_block_ctxt(fcx: @fn_ctxt) -> @block_ctxt {
|
||||
@ -4177,7 +4189,8 @@ fn llderivedtydescs_block_ctxt(fcx: @fn_ctxt) -> @block_ctxt {
|
||||
mutable lpad_dirty: true,
|
||||
mutable lpad: option::none,
|
||||
sp: fcx.sp,
|
||||
fcx: fcx};
|
||||
fcx: fcx,
|
||||
mutable source_pos: option::none};
|
||||
}
|
||||
|
||||
|
||||
@ -4250,6 +4263,7 @@ fn trans_block(bcx: @block_ctxt, b: ast::blk) -> @block_ctxt {
|
||||
fn trans_block_dps(bcx: @block_ctxt, b: ast::blk, dest: dest)
|
||||
-> @block_ctxt {
|
||||
let bcx = bcx;
|
||||
debuginfo::update_source_pos(bcx, b);
|
||||
block_locals(b) {|local| bcx = alloc_local(bcx, local); };
|
||||
for s: @ast::stmt in b.node.stmts {
|
||||
bcx = trans_stmt(bcx, *s);
|
||||
@ -4261,7 +4275,9 @@ fn trans_block_dps(bcx: @block_ctxt, b: ast::blk, dest: dest)
|
||||
}
|
||||
_ { assert dest == ignore || bcx.unreachable; }
|
||||
}
|
||||
ret trans_block_cleanups(bcx, find_scope_cx(bcx));
|
||||
let rv = trans_block_cleanups(bcx, find_scope_cx(bcx));
|
||||
debuginfo::reset_source_pos(bcx);
|
||||
ret rv;
|
||||
}
|
||||
|
||||
fn new_local_ctxt(ccx: @crate_ctxt) -> @local_ctxt {
|
||||
@ -5465,6 +5481,18 @@ fn declare_intrinsics(llmod: ModuleRef) -> hashmap<str, ValueRef> {
|
||||
ret intrinsics;
|
||||
}
|
||||
|
||||
fn declare_dbg_intrinsics(llmod: ModuleRef,
|
||||
intrinsics: hashmap<str, ValueRef>) {
|
||||
let declare =
|
||||
decl_cdecl_fn(llmod, "llvm.dbg.declare",
|
||||
T_fn([T_metadata(), T_metadata()], T_void()));
|
||||
let value =
|
||||
decl_cdecl_fn(llmod, "llvm.dbg.value",
|
||||
T_fn([T_metadata(), T_i64(), T_metadata()], T_void()));
|
||||
intrinsics.insert("llvm.dbg.declare", declare);
|
||||
intrinsics.insert("llvm.dbg.value", value);
|
||||
}
|
||||
|
||||
fn trap(bcx: @block_ctxt) {
|
||||
let v: [ValueRef] = [];
|
||||
alt bcx_ccx(bcx).intrinsics.find("llvm.trap") {
|
||||
@ -5601,6 +5629,9 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
|
||||
let td = mk_target_data(sess.get_targ_cfg().target_strs.data_layout);
|
||||
let tn = mk_type_names();
|
||||
let intrinsics = declare_intrinsics(llmod);
|
||||
if sess.get_opts().debuginfo {
|
||||
declare_dbg_intrinsics(llmod, intrinsics);
|
||||
}
|
||||
let int_type = T_int(targ_cfg);
|
||||
let float_type = T_float(targ_cfg);
|
||||
let task_type = T_task(targ_cfg);
|
||||
|
@ -25,14 +25,16 @@ fn RetVoid(cx: @block_ctxt) {
|
||||
if cx.unreachable { ret; }
|
||||
assert (!cx.terminated);
|
||||
cx.terminated = true;
|
||||
llvm::LLVMBuildRetVoid(B(cx));
|
||||
let instr = llvm::LLVMBuildRetVoid(B(cx));
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
|
||||
fn Ret(cx: @block_ctxt, V: ValueRef) {
|
||||
if cx.unreachable { ret; }
|
||||
assert (!cx.terminated);
|
||||
cx.terminated = true;
|
||||
llvm::LLVMBuildRet(B(cx), V);
|
||||
let instr = llvm::LLVMBuildRet(B(cx), V);
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
|
||||
fn AggregateRet(cx: @block_ctxt, RetVals: [ValueRef]) {
|
||||
@ -40,8 +42,9 @@ fn AggregateRet(cx: @block_ctxt, RetVals: [ValueRef]) {
|
||||
assert (!cx.terminated);
|
||||
cx.terminated = true;
|
||||
unsafe {
|
||||
llvm::LLVMBuildAggregateRet(B(cx), vec::to_ptr(RetVals),
|
||||
let instr = llvm::LLVMBuildAggregateRet(B(cx), vec::to_ptr(RetVals),
|
||||
vec::len(RetVals));
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +52,8 @@ fn Br(cx: @block_ctxt, Dest: BasicBlockRef) {
|
||||
if cx.unreachable { ret; }
|
||||
assert (!cx.terminated);
|
||||
cx.terminated = true;
|
||||
llvm::LLVMBuildBr(B(cx), Dest);
|
||||
let instr = llvm::LLVMBuildBr(B(cx), Dest);
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
|
||||
fn CondBr(cx: @block_ctxt, If: ValueRef, Then: BasicBlockRef,
|
||||
@ -57,7 +61,8 @@ fn CondBr(cx: @block_ctxt, If: ValueRef, Then: BasicBlockRef,
|
||||
if cx.unreachable { ret; }
|
||||
assert (!cx.terminated);
|
||||
cx.terminated = true;
|
||||
llvm::LLVMBuildCondBr(B(cx), If, Then, Else);
|
||||
let instr = llvm::LLVMBuildCondBr(B(cx), If, Then, Else);
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
|
||||
fn Switch(cx: @block_ctxt, V: ValueRef, Else: BasicBlockRef, NumCases: uint)
|
||||
@ -65,7 +70,9 @@ fn Switch(cx: @block_ctxt, V: ValueRef, Else: BasicBlockRef, NumCases: uint)
|
||||
if cx.unreachable { ret _Undef(V); }
|
||||
assert !cx.terminated;
|
||||
cx.terminated = true;
|
||||
ret llvm::LLVMBuildSwitch(B(cx), V, Else, NumCases);
|
||||
let instr = llvm::LLVMBuildSwitch(B(cx), V, Else, NumCases);
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn AddCase(S: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef) {
|
||||
@ -77,7 +84,8 @@ fn IndirectBr(cx: @block_ctxt, Addr: ValueRef, NumDests: uint) {
|
||||
if cx.unreachable { ret; }
|
||||
assert (!cx.terminated);
|
||||
cx.terminated = true;
|
||||
llvm::LLVMBuildIndirectBr(B(cx), Addr, NumDests);
|
||||
let instr = llvm::LLVMBuildIndirectBr(B(cx), Addr, NumDests);
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
|
||||
// This is a really awful way to get a zero-length c-string, but better (and a
|
||||
@ -93,8 +101,10 @@ fn Invoke(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef],
|
||||
assert (!cx.terminated);
|
||||
cx.terminated = true;
|
||||
unsafe {
|
||||
llvm::LLVMBuildInvoke(B(cx), Fn, vec::to_ptr(Args),
|
||||
vec::len(Args), Then, Catch, noname());
|
||||
let instr = llvm::LLVMBuildInvoke(B(cx), Fn, vec::to_ptr(Args),
|
||||
vec::len(Args), Then, Catch,
|
||||
noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,6 +117,7 @@ fn FastInvoke(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef],
|
||||
let v = llvm::LLVMBuildInvoke(B(cx), Fn, vec::to_ptr(Args),
|
||||
vec::len(Args), Then, Catch, noname());
|
||||
llvm::LLVMSetInstructionCallConv(v, lib::llvm::LLVMFastCallConv);
|
||||
debuginfo::add_line_info(cx, v);
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,183 +134,254 @@ fn _Undef(val: ValueRef) -> ValueRef {
|
||||
/* Arithmetic */
|
||||
fn Add(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildAdd(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildAdd(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn NSWAdd(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildNSWAdd(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildNSWAdd(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn NUWAdd(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildNUWAdd(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildNUWAdd(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn FAdd(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildFAdd(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildFAdd(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Sub(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildSub(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildSub(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn NSWSub(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildNSWSub(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildNSWSub(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn NUWSub(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildNUWSub(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildNUWSub(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn FSub(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildFSub(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildFSub(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Mul(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildMul(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildMul(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn NSWMul(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildNSWMul(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildNSWMul(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn NUWMul(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildNUWMul(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildNUWMul(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn FMul(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildFMul(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildFMul(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn UDiv(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildUDiv(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildUDiv(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn SDiv(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildSDiv(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildSDiv(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn ExactSDiv(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildExactSDiv(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildExactSDiv(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn FDiv(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildFDiv(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildFDiv(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn URem(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildURem(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildURem(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn SRem(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildSRem(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildSRem(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn FRem(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildFRem(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildFRem(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Shl(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildShl(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildShl(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn LShr(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildLShr(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildLShr(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn AShr(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildAShr(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildAShr(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn And(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildAnd(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildAnd(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Or(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildOr(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildOr(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Xor(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildXor(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildXor(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn BinOp(cx: @block_ctxt, Op: Opcode, LHS: ValueRef, RHS: ValueRef) ->
|
||||
ValueRef {
|
||||
if cx.unreachable { ret _Undef(LHS); }
|
||||
ret llvm::LLVMBuildBinOp(B(cx), Op, LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildBinOp(B(cx), Op, LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Neg(cx: @block_ctxt, V: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(V); }
|
||||
ret llvm::LLVMBuildNeg(B(cx), V, noname());
|
||||
let instr = llvm::LLVMBuildNeg(B(cx), V, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn NSWNeg(cx: @block_ctxt, V: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(V); }
|
||||
ret llvm::LLVMBuildNSWNeg(B(cx), V, noname());
|
||||
let instr = llvm::LLVMBuildNSWNeg(B(cx), V, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn NUWNeg(cx: @block_ctxt, V: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(V); }
|
||||
ret llvm::LLVMBuildNUWNeg(B(cx), V, noname());
|
||||
let instr = llvm::LLVMBuildNUWNeg(B(cx), V, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
fn FNeg(cx: @block_ctxt, V: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(V); }
|
||||
ret llvm::LLVMBuildFNeg(B(cx), V, noname());
|
||||
let instr = llvm::LLVMBuildFNeg(B(cx), V, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Not(cx: @block_ctxt, V: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret _Undef(V); }
|
||||
ret llvm::LLVMBuildNot(B(cx), V, noname());
|
||||
let instr = llvm::LLVMBuildNot(B(cx), V, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
/* Memory */
|
||||
fn Malloc(cx: @block_ctxt, Ty: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
||||
ret llvm::LLVMBuildMalloc(B(cx), Ty, noname());
|
||||
let instr = llvm::LLVMBuildMalloc(B(cx), Ty, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn ArrayMalloc(cx: @block_ctxt, Ty: TypeRef, Val: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
||||
ret llvm::LLVMBuildArrayMalloc(B(cx), Ty, Val, noname());
|
||||
let instr = llvm::LLVMBuildArrayMalloc(B(cx), Ty, Val, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Alloca(cx: @block_ctxt, Ty: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_ptr(Ty)); }
|
||||
ret llvm::LLVMBuildAlloca(B(cx), Ty, noname());
|
||||
let instr = llvm::LLVMBuildAlloca(B(cx), Ty, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn ArrayAlloca(cx: @block_ctxt, Ty: TypeRef, Val: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_ptr(Ty)); }
|
||||
ret llvm::LLVMBuildArrayAlloca(B(cx), Ty, Val, noname());
|
||||
let instr = llvm::LLVMBuildArrayAlloca(B(cx), Ty, Val, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Free(cx: @block_ctxt, PointerVal: ValueRef) {
|
||||
if cx.unreachable { ret; }
|
||||
llvm::LLVMBuildFree(B(cx), PointerVal);
|
||||
let instr = llvm::LLVMBuildFree(B(cx), PointerVal);
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
|
||||
fn Load(cx: @block_ctxt, PointerVal: ValueRef) -> ValueRef {
|
||||
@ -310,19 +392,24 @@ fn Load(cx: @block_ctxt, PointerVal: ValueRef) -> ValueRef {
|
||||
llvm::LLVMGetElementType(ty) } else { ccx.int_type };
|
||||
ret llvm::LLVMGetUndef(eltty);
|
||||
}
|
||||
ret llvm::LLVMBuildLoad(B(cx), PointerVal, noname());
|
||||
let instr = llvm::LLVMBuildLoad(B(cx), PointerVal, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Store(cx: @block_ctxt, Val: ValueRef, Ptr: ValueRef) {
|
||||
if cx.unreachable { ret; }
|
||||
llvm::LLVMBuildStore(B(cx), Val, Ptr);
|
||||
let instr = llvm::LLVMBuildStore(B(cx), Val, Ptr);
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
|
||||
fn GEP(cx: @block_ctxt, Pointer: ValueRef, Indices: [ValueRef]) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_ptr(T_nil())); }
|
||||
unsafe {
|
||||
ret llvm::LLVMBuildGEP(B(cx), Pointer, vec::to_ptr(Indices),
|
||||
let instr = llvm::LLVMBuildGEP(B(cx), Pointer, vec::to_ptr(Indices),
|
||||
vec::len(Indices), noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,142 +425,195 @@ fn InBoundsGEP(cx: @block_ctxt, Pointer: ValueRef, Indices: [ValueRef]) ->
|
||||
ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_ptr(T_nil())); }
|
||||
unsafe {
|
||||
ret llvm::LLVMBuildInBoundsGEP(B(cx), Pointer, vec::to_ptr(Indices),
|
||||
let v = llvm::LLVMBuildInBoundsGEP(B(cx), Pointer,
|
||||
vec::to_ptr(Indices),
|
||||
vec::len(Indices), noname());
|
||||
debuginfo::add_line_info(cx, v);
|
||||
ret v;
|
||||
}
|
||||
}
|
||||
|
||||
fn StructGEP(cx: @block_ctxt, Pointer: ValueRef, Idx: uint) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_ptr(T_nil())); }
|
||||
ret llvm::LLVMBuildStructGEP(B(cx), Pointer, Idx, noname());
|
||||
let instr = llvm::LLVMBuildStructGEP(B(cx), Pointer, Idx, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn GlobalString(cx: @block_ctxt, _Str: sbuf) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
||||
ret llvm::LLVMBuildGlobalString(B(cx), _Str, noname());
|
||||
let instr = llvm::LLVMBuildGlobalString(B(cx), _Str, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn GlobalStringPtr(cx: @block_ctxt, _Str: sbuf) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
||||
ret llvm::LLVMBuildGlobalStringPtr(B(cx), _Str, noname());
|
||||
let instr = llvm::LLVMBuildGlobalStringPtr(B(cx), _Str, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
/* Casts */
|
||||
fn Trunc(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildTrunc(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildTrunc(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn ZExt(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildZExt(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildZExt(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn SExt(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildSExt(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildSExt(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn FPToUI(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildFPToUI(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildFPToUI(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn FPToSI(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildFPToSI(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildFPToSI(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn UIToFP(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildUIToFP(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildUIToFP(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn SIToFP(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildSIToFP(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildSIToFP(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn FPTrunc(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildFPTrunc(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildFPTrunc(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn FPExt(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildFPExt(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildFPExt(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn PtrToInt(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildPtrToInt(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildPtrToInt(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn IntToPtr(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildIntToPtr(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildIntToPtr(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn BitCast(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildBitCast(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildBitCast(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn ZExtOrBitCast(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) ->
|
||||
ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildZExtOrBitCast(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildZExtOrBitCast(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn SExtOrBitCast(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) ->
|
||||
ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildSExtOrBitCast(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildSExtOrBitCast(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn TruncOrBitCast(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) ->
|
||||
ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildTruncOrBitCast(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildTruncOrBitCast(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Cast(cx: @block_ctxt, Op: Opcode, Val: ValueRef, DestTy: TypeRef,
|
||||
_Name: sbuf) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildCast(B(cx), Op, Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildCast(B(cx), Op, Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn PointerCast(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildPointerCast(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildPointerCast(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn IntCast(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildIntCast(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildIntCast(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn FPCast(cx: @block_ctxt, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(DestTy); }
|
||||
ret llvm::LLVMBuildFPCast(B(cx), Val, DestTy, noname());
|
||||
let instr = llvm::LLVMBuildFPCast(B(cx), Val, DestTy, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
|
||||
/* Comparisons */
|
||||
fn ICmp(cx: @block_ctxt, Op: uint, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_i1()); }
|
||||
ret llvm::LLVMBuildICmp(B(cx), Op, LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildICmp(B(cx), Op, LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn FCmp(cx: @block_ctxt, Op: uint, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_i1()); }
|
||||
ret llvm::LLVMBuildFCmp(B(cx), Op, LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildFCmp(B(cx), Op, LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
/* Miscellaneous instructions */
|
||||
fn EmptyPhi(cx: @block_ctxt, Ty: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(Ty); }
|
||||
ret llvm::LLVMBuildPhi(B(cx), Ty, noname());
|
||||
let instr = llvm::LLVMBuildPhi(B(cx), Ty, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Phi(cx: @block_ctxt, Ty: TypeRef, vals: [ValueRef], bbs: [BasicBlockRef])
|
||||
@ -528,8 +668,10 @@ fn add_comment(bcx: @block_ctxt, text: str) {
|
||||
fn Call(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef]) -> ValueRef {
|
||||
if cx.unreachable { ret _UndefReturn(cx, Fn); }
|
||||
unsafe {
|
||||
ret llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
|
||||
let instr = llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
|
||||
vec::len(Args), noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,6 +681,7 @@ fn FastCall(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef]) -> ValueRef {
|
||||
let v = llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
|
||||
vec::len(Args), noname());
|
||||
llvm::LLVMSetInstructionCallConv(v, lib::llvm::LLVMFastCallConv);
|
||||
debuginfo::add_line_info(cx, v);
|
||||
ret v;
|
||||
}
|
||||
}
|
||||
@ -550,6 +693,7 @@ fn CallWithConv(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef], Conv: uint)
|
||||
let v = llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
|
||||
vec::len(Args), noname());
|
||||
llvm::LLVMSetInstructionCallConv(v, Conv);
|
||||
debuginfo::add_line_info(cx, v);
|
||||
ret v;
|
||||
}
|
||||
}
|
||||
@ -557,57 +701,76 @@ fn CallWithConv(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef], Conv: uint)
|
||||
fn Select(cx: @block_ctxt, If: ValueRef, Then: ValueRef, Else: ValueRef) ->
|
||||
ValueRef {
|
||||
if cx.unreachable { ret _Undef(Then); }
|
||||
ret llvm::LLVMBuildSelect(B(cx), If, Then, Else, noname());
|
||||
let instr = llvm::LLVMBuildSelect(B(cx), If, Then, Else, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn VAArg(cx: @block_ctxt, list: ValueRef, Ty: TypeRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(Ty); }
|
||||
ret llvm::LLVMBuildVAArg(B(cx), list, Ty, noname());
|
||||
let instr = llvm::LLVMBuildVAArg(B(cx), list, Ty, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn ExtractElement(cx: @block_ctxt, VecVal: ValueRef, Index: ValueRef) ->
|
||||
ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_nil()); }
|
||||
ret llvm::LLVMBuildExtractElement(B(cx), VecVal, Index, noname());
|
||||
let instr = llvm::LLVMBuildExtractElement(B(cx), VecVal, Index, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn InsertElement(cx: @block_ctxt, VecVal: ValueRef, EltVal: ValueRef,
|
||||
Index: ValueRef) {
|
||||
if cx.unreachable { ret; }
|
||||
llvm::LLVMBuildInsertElement(B(cx), VecVal, EltVal, Index, noname());
|
||||
let instr = llvm::LLVMBuildInsertElement(B(cx), VecVal, EltVal, Index,
|
||||
noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
|
||||
fn ShuffleVector(cx: @block_ctxt, V1: ValueRef, V2: ValueRef,
|
||||
Mask: ValueRef) {
|
||||
if cx.unreachable { ret; }
|
||||
llvm::LLVMBuildShuffleVector(B(cx), V1, V2, Mask, noname());
|
||||
let instr = llvm::LLVMBuildShuffleVector(B(cx), V1, V2, Mask, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
|
||||
fn ExtractValue(cx: @block_ctxt, AggVal: ValueRef, Index: uint) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_nil()); }
|
||||
ret llvm::LLVMBuildExtractValue(B(cx), AggVal, Index, noname());
|
||||
let instr = llvm::LLVMBuildExtractValue(B(cx), AggVal, Index, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn InsertValue(cx: @block_ctxt, AggVal: ValueRef, EltVal: ValueRef,
|
||||
Index: uint) {
|
||||
if cx.unreachable { ret; }
|
||||
llvm::LLVMBuildInsertValue(B(cx), AggVal, EltVal, Index, noname());
|
||||
let instr = llvm::LLVMBuildInsertValue(B(cx), AggVal, EltVal, Index,
|
||||
noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
|
||||
fn IsNull(cx: @block_ctxt, Val: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_i1()); }
|
||||
ret llvm::LLVMBuildIsNull(B(cx), Val, noname());
|
||||
let instr = llvm::LLVMBuildIsNull(B(cx), Val, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn IsNotNull(cx: @block_ctxt, Val: ValueRef) -> ValueRef {
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(T_i1()); }
|
||||
ret llvm::LLVMBuildIsNotNull(B(cx), Val, noname());
|
||||
let instr = llvm::LLVMBuildIsNotNull(B(cx), Val, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn PtrDiff(cx: @block_ctxt, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
let ccx = cx.fcx.lcx.ccx;
|
||||
if cx.unreachable { ret llvm::LLVMGetUndef(ccx.int_type); }
|
||||
ret llvm::LLVMBuildPtrDiff(B(cx), LHS, RHS, noname());
|
||||
let instr = llvm::LLVMBuildPtrDiff(B(cx), LHS, RHS, noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn Trap(cx: @block_ctxt) {
|
||||
@ -622,15 +785,19 @@ fn Trap(cx: @block_ctxt) {
|
||||
assert (T as int != 0);
|
||||
let Args: [ValueRef] = [];
|
||||
unsafe {
|
||||
llvm::LLVMBuildCall(b, T, vec::to_ptr(Args),
|
||||
let instr = llvm::LLVMBuildCall(b, T, vec::to_ptr(Args),
|
||||
vec::len(Args), noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
}
|
||||
}
|
||||
|
||||
fn LandingPad(cx: @block_ctxt, Ty: TypeRef, PersFn: ValueRef,
|
||||
NumClauses: uint) -> ValueRef {
|
||||
assert !cx.terminated && !cx.unreachable;
|
||||
ret llvm::LLVMBuildLandingPad(B(cx), Ty, PersFn, NumClauses, noname());
|
||||
let instr = llvm::LLVMBuildLandingPad(B(cx), Ty, PersFn, NumClauses,
|
||||
noname());
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
fn SetCleanup(_cx: @block_ctxt, LandingPad: ValueRef) {
|
||||
@ -640,7 +807,9 @@ fn SetCleanup(_cx: @block_ctxt, LandingPad: ValueRef) {
|
||||
fn Resume(cx: @block_ctxt, Exn: ValueRef) -> ValueRef {
|
||||
assert (!cx.terminated);
|
||||
cx.terminated = true;
|
||||
ret llvm::LLVMBuildResume(B(cx), Exn);
|
||||
let instr = llvm::LLVMBuildResume(B(cx), Exn);
|
||||
debuginfo::add_line_info(cx, instr);
|
||||
ret instr;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -385,7 +385,8 @@ type block_ctxt =
|
||||
mutable lpad_dirty: bool,
|
||||
mutable lpad: option::t<BasicBlockRef>,
|
||||
sp: span,
|
||||
fcx: @fn_ctxt};
|
||||
fcx: @fn_ctxt,
|
||||
mutable source_pos: option::t<syntax::codemap::loc>};
|
||||
|
||||
// FIXME: we should be able to use option::t<@block_parent> here but
|
||||
// the infinite-tag check in rustboot gets upset.
|
||||
@ -464,6 +465,8 @@ fn T_nil() -> TypeRef {
|
||||
ret llvm::LLVMInt1Type();
|
||||
}
|
||||
|
||||
fn T_metadata() -> TypeRef { ret llvm::LLVMMetadataType(); }
|
||||
|
||||
fn T_i1() -> TypeRef { ret llvm::LLVMInt1Type(); }
|
||||
|
||||
fn T_i8() -> TypeRef { ret llvm::LLVMInt8Type(); }
|
||||
@ -801,6 +804,10 @@ fn C_i32(i: i32) -> ValueRef {
|
||||
ret C_integral(T_i32(), i as u64, True);
|
||||
}
|
||||
|
||||
fn C_i64(i: i64) -> ValueRef {
|
||||
ret C_integral(T_i64(), i as uint, True);
|
||||
}
|
||||
|
||||
fn C_int(cx: @crate_ctxt, i: int) -> ValueRef {
|
||||
ret C_integral(cx.int_type, i as u64, True);
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ LLVMAddLoopRotatePass
|
||||
LLVMAddLoopUnrollPass
|
||||
LLVMAddLoopUnswitchPass
|
||||
LLVMAddMemCpyOptPass
|
||||
LLVMAddNamedMetadataOperand
|
||||
LLVMAddPromoteMemoryToRegisterPass
|
||||
LLVMAddPruneEHPass
|
||||
LLVMAddReassociatePass
|
||||
@ -483,11 +484,15 @@ LLVMIsThreadLocal
|
||||
LLVMIsUndef
|
||||
LLVMLabelType
|
||||
LLVMLabelTypeInContext
|
||||
LLVMLinkInInterpreter
|
||||
LLVMLinkInJIT
|
||||
LLVMLinkInMCJIT
|
||||
LLVMMDNode
|
||||
LLVMMDNodeInContext
|
||||
LLVMMDString
|
||||
LLVMMDStringInContext
|
||||
LLVMAddNamedMetadataOperand
|
||||
LLVMMetadataType
|
||||
LLVMMetadataTypeInContext
|
||||
LLVMModuleCreateWithName
|
||||
LLVMModuleCreateWithNameInContext
|
||||
LLVMMoveBasicBlockAfter
|
||||
|
Loading…
Reference in New Issue
Block a user