rustc: Remove LLVM unions and represent tags as (discriminant, byte blob) pairs
This commit is contained in:
parent
f371dc613a
commit
afd3af9bb5
2 changed files with 80 additions and 39 deletions
|
@ -14,6 +14,7 @@ import llvm.ModuleProviderRef;
|
||||||
import llvm.MemoryBufferRef;
|
import llvm.MemoryBufferRef;
|
||||||
import llvm.PassManagerRef;
|
import llvm.PassManagerRef;
|
||||||
import llvm.UseRef;
|
import llvm.UseRef;
|
||||||
|
import llvm.TargetDataRef;
|
||||||
import llvm.Linkage;
|
import llvm.Linkage;
|
||||||
import llvm.Attribute;
|
import llvm.Attribute;
|
||||||
import llvm.Visibility;
|
import llvm.Visibility;
|
||||||
|
@ -69,6 +70,7 @@ native mod llvm = llvm_lib {
|
||||||
type MemoryBufferRef;
|
type MemoryBufferRef;
|
||||||
type PassManagerRef;
|
type PassManagerRef;
|
||||||
type UseRef;
|
type UseRef;
|
||||||
|
type TargetDataRef;
|
||||||
|
|
||||||
/* FIXME: These are enums in the C header. Represent them how, in rust? */
|
/* FIXME: These are enums in the C header. Represent them how, in rust? */
|
||||||
type Linkage;
|
type Linkage;
|
||||||
|
@ -167,13 +169,6 @@ native mod llvm = llvm_lib {
|
||||||
fn LLVMGetStructElementTypes(TypeRef StructTy, vbuf Dest);
|
fn LLVMGetStructElementTypes(TypeRef StructTy, vbuf Dest);
|
||||||
fn LLVMIsPackedStruct(TypeRef StructTy) -> Bool;
|
fn LLVMIsPackedStruct(TypeRef StructTy) -> Bool;
|
||||||
|
|
||||||
/* Operations on union types */
|
|
||||||
fn LLVMUnionTypeInContext(ContextRef C, vbuf ElementTypes,
|
|
||||||
uint ElementCount) -> TypeRef;
|
|
||||||
fn LLVMUnionType(vbuf ElementTypes, uint ElementCount) -> TypeRef;
|
|
||||||
fn LLVMCountUnionElementTypes(TypeRef UnionTy) -> uint;
|
|
||||||
fn LLVMGetUnionElementTypes(TypeRef UnionTy, vbuf Dest);
|
|
||||||
|
|
||||||
/* Operations on array, pointer, and vector types (sequence types) */
|
/* Operations on array, pointer, and vector types (sequence types) */
|
||||||
fn LLVMArrayType(TypeRef ElementType, uint ElementCount) -> TypeRef;
|
fn LLVMArrayType(TypeRef ElementType, uint ElementCount) -> TypeRef;
|
||||||
fn LLVMPointerType(TypeRef ElementType, uint AddressSpace) -> TypeRef;
|
fn LLVMPointerType(TypeRef ElementType, uint AddressSpace) -> TypeRef;
|
||||||
|
@ -261,7 +256,6 @@ native mod llvm = llvm_lib {
|
||||||
fn LLVMConstStruct(vbuf ConstantVals, uint Count,
|
fn LLVMConstStruct(vbuf ConstantVals, uint Count,
|
||||||
Bool Packed) -> ValueRef;
|
Bool Packed) -> ValueRef;
|
||||||
fn LLVMConstVector(vbuf ScalarConstantVals, uint Size) -> ValueRef;
|
fn LLVMConstVector(vbuf ScalarConstantVals, uint Size) -> ValueRef;
|
||||||
fn LLVMConstUnion(TypeRef Ty, ValueRef Val) -> ValueRef;
|
|
||||||
|
|
||||||
/* Constant expressions */
|
/* Constant expressions */
|
||||||
fn LLVMAlignOf(TypeRef Ty) -> ValueRef;
|
fn LLVMAlignOf(TypeRef Ty) -> ValueRef;
|
||||||
|
@ -684,6 +678,15 @@ native mod llvm = llvm_lib {
|
||||||
|
|
||||||
/** Writes a module to the specified path. Returns 0 on success. */
|
/** Writes a module to the specified path. Returns 0 on success. */
|
||||||
fn LLVMWriteBitcodeToFile(ModuleRef M, sbuf Path) -> int;
|
fn LLVMWriteBitcodeToFile(ModuleRef M, sbuf Path) -> int;
|
||||||
|
|
||||||
|
/** Creates target data from a target layout string. */
|
||||||
|
fn LLVMCreateTargetData(sbuf StringRep) -> TargetDataRef;
|
||||||
|
/** Returns the size of a type. FIXME: rv is actually a ULongLong! */
|
||||||
|
fn LLVMStoreSizeOfType(TargetDataRef TD, TypeRef Ty) -> uint;
|
||||||
|
/** Returns the alignment of a type. */
|
||||||
|
fn LLVMPreferredAlignmentOfType(TargetDataRef TD, TypeRef Ty) -> uint;
|
||||||
|
/** Disposes target data. */
|
||||||
|
fn LLVMDisposeTargetData(TargetDataRef TD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Slightly more terse object-interface to LLVM's 'builder' functions. */
|
/* Slightly more terse object-interface to LLVM's 'builder' functions. */
|
||||||
|
@ -1186,7 +1189,6 @@ fn type_to_str(TypeRef ty) -> str {
|
||||||
case (12) { ret "Opaque"; }
|
case (12) { ret "Opaque"; }
|
||||||
case (13) { ret "Vector"; }
|
case (13) { ret "Vector"; }
|
||||||
case (14) { ret "Metadata"; }
|
case (14) { ret "Metadata"; }
|
||||||
case (15) { ret "Union"; }
|
|
||||||
case (_) {
|
case (_) {
|
||||||
log "unknown TypeKind" + util.common.istr(kind as int);
|
log "unknown TypeKind" + util.common.istr(kind as int);
|
||||||
fail;
|
fail;
|
||||||
|
@ -1194,6 +1196,19 @@ fn type_to_str(TypeRef ty) -> str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Memory-managed interface to target data. */
|
||||||
|
|
||||||
|
obj target_data_dtor(TargetDataRef TD) {
|
||||||
|
drop { llvm.LLVMDisposeTargetData(TD); }
|
||||||
|
}
|
||||||
|
|
||||||
|
type target_data = rec(TargetDataRef lltd, target_data_dtor dtor);
|
||||||
|
|
||||||
|
fn mk_target_data(str string_rep) -> target_data {
|
||||||
|
auto lltd = llvm.LLVMCreateTargetData(_str.buf(string_rep));
|
||||||
|
ret rec(lltd=lltd, dtor=target_data_dtor(lltd));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
|
|
|
@ -21,8 +21,10 @@ import util.common.new_str_hash;
|
||||||
|
|
||||||
import lib.llvm.llvm;
|
import lib.llvm.llvm;
|
||||||
import lib.llvm.builder;
|
import lib.llvm.builder;
|
||||||
|
import lib.llvm.target_data;
|
||||||
import lib.llvm.type_handle;
|
import lib.llvm.type_handle;
|
||||||
import lib.llvm.mk_type_handle;
|
import lib.llvm.mk_type_handle;
|
||||||
|
import lib.llvm.mk_target_data;
|
||||||
import lib.llvm.llvm.ModuleRef;
|
import lib.llvm.llvm.ModuleRef;
|
||||||
import lib.llvm.llvm.ValueRef;
|
import lib.llvm.llvm.ValueRef;
|
||||||
import lib.llvm.llvm.TypeRef;
|
import lib.llvm.llvm.TypeRef;
|
||||||
|
@ -47,10 +49,12 @@ type glue_fns = rec(ValueRef activate_glue,
|
||||||
|
|
||||||
tag arity { nullary; n_ary; }
|
tag arity { nullary; n_ary; }
|
||||||
type tag_info = rec(type_handle th,
|
type tag_info = rec(type_handle th,
|
||||||
mutable vec[tup(ast.def_id,arity)] variants);
|
mutable vec[tup(ast.def_id,arity)] variants,
|
||||||
|
mutable uint size);
|
||||||
|
|
||||||
state type crate_ctxt = rec(session.session sess,
|
state type crate_ctxt = rec(session.session sess,
|
||||||
ModuleRef llmod,
|
ModuleRef llmod,
|
||||||
|
target_data td,
|
||||||
hashmap[str, ValueRef] upcalls,
|
hashmap[str, ValueRef] upcalls,
|
||||||
hashmap[str, ValueRef] intrinsics,
|
hashmap[str, ValueRef] intrinsics,
|
||||||
hashmap[str, ValueRef] item_names,
|
hashmap[str, ValueRef] item_names,
|
||||||
|
@ -187,11 +191,6 @@ fn T_struct(vec[TypeRef] elts) -> TypeRef {
|
||||||
False);
|
False);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn T_union(vec[TypeRef] elts) -> TypeRef {
|
|
||||||
ret llvm.LLVMUnionType(_vec.buf[TypeRef](elts),
|
|
||||||
_vec.len[TypeRef](elts));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_opaque() -> TypeRef {
|
fn T_opaque() -> TypeRef {
|
||||||
ret llvm.LLVMOpaqueType();
|
ret llvm.LLVMOpaqueType();
|
||||||
}
|
}
|
||||||
|
@ -369,6 +368,17 @@ fn C_str(@crate_ctxt cx, str s) -> ValueRef {
|
||||||
ret g;
|
ret g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn C_zero_byte_arr(uint size) -> ValueRef {
|
||||||
|
auto i = 0u;
|
||||||
|
let vec[ValueRef] elts = vec();
|
||||||
|
while (i < size) {
|
||||||
|
elts += vec(C_integral(0, T_i8()));
|
||||||
|
i += 1u;
|
||||||
|
}
|
||||||
|
ret llvm.LLVMConstArray(T_i8(), _vec.buf[ValueRef](elts),
|
||||||
|
_vec.len[ValueRef](elts));
|
||||||
|
}
|
||||||
|
|
||||||
fn C_struct(vec[ValueRef] elts) -> ValueRef {
|
fn C_struct(vec[ValueRef] elts) -> ValueRef {
|
||||||
ret llvm.LLVMConstStruct(_vec.buf[ValueRef](elts),
|
ret llvm.LLVMConstStruct(_vec.buf[ValueRef](elts),
|
||||||
_vec.len[ValueRef](elts),
|
_vec.len[ValueRef](elts),
|
||||||
|
@ -388,10 +398,6 @@ fn C_tydesc(TypeRef t) -> ValueRef {
|
||||||
C_null(T_ptr(T_opaque())))); // is_stateful
|
C_null(T_ptr(T_opaque())))); // is_stateful
|
||||||
}
|
}
|
||||||
|
|
||||||
fn C_union(TypeRef ty, ValueRef val) -> ValueRef {
|
|
||||||
ret llvm.LLVMConstUnion(ty, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decl_fn(ModuleRef llmod, str name, uint cc, TypeRef llty) -> ValueRef {
|
fn decl_fn(ModuleRef llmod, str name, uint cc, TypeRef llty) -> ValueRef {
|
||||||
let ValueRef llfn =
|
let ValueRef llfn =
|
||||||
llvm.LLVMAddFunction(llmod, _str.buf(name), llty);
|
llvm.LLVMAddFunction(llmod, _str.buf(name), llty);
|
||||||
|
@ -538,6 +544,19 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx,
|
||||||
ret res(next_cx, phi);
|
ret res(next_cx, phi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef {
|
||||||
|
let vec[TypeRef] lltys = vec();
|
||||||
|
alt (typeck.ann_to_type(v.ann).struct) {
|
||||||
|
case (typeck.ty_fn(?args, _)) {
|
||||||
|
for (typeck.arg arg in args) {
|
||||||
|
lltys += vec(type_of(cx, arg.ty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case (_) { fail; }
|
||||||
|
}
|
||||||
|
ret T_struct(lltys);
|
||||||
|
}
|
||||||
|
|
||||||
type val_and_ty_fn =
|
type val_and_ty_fn =
|
||||||
fn(@block_ctxt cx, ValueRef v, @typeck.ty t) -> result;
|
fn(@block_ctxt cx, ValueRef v, @typeck.ty t) -> result;
|
||||||
|
|
||||||
|
@ -611,18 +630,23 @@ fn iter_structural_ty(@block_ctxt cx,
|
||||||
let vec[ValueRef] vals = vec(C_int(0), C_int(1),
|
let vec[ValueRef] vals = vec(C_int(0), C_int(1),
|
||||||
C_int(i as int));
|
C_int(i as int));
|
||||||
auto llvar = variant_cx.build.GEP(v, vals);
|
auto llvar = variant_cx.build.GEP(v, vals);
|
||||||
|
auto llvarty = type_of_variant(cx.fcx.ccx,
|
||||||
|
variants.(i));
|
||||||
|
|
||||||
auto fn_ty = typeck.ann_to_type(variants.(i).ann);
|
auto fn_ty = typeck.ann_to_type(variants.(i).ann);
|
||||||
alt (fn_ty.struct) {
|
alt (fn_ty.struct) {
|
||||||
case (typeck.ty_fn(?args, _)) {
|
case (typeck.ty_fn(?args, _)) {
|
||||||
|
auto llvarp = variant_cx.build.
|
||||||
|
TruncOrBitCast(llunion_ptr,
|
||||||
|
T_ptr(llvarty));
|
||||||
|
|
||||||
auto j = 0u;
|
auto j = 0u;
|
||||||
for (typeck.arg a in args) {
|
for (typeck.arg a in args) {
|
||||||
auto idx = vec(C_int(0), C_int(j as int));
|
auto llfldp = variant_cx.build.GEP(llvarp,
|
||||||
auto llfp = variant_cx.build.GEP(llvar,
|
vec(C_int(0), C_int(j as int)));
|
||||||
idx);
|
|
||||||
auto llfld =
|
auto llfld =
|
||||||
load_non_structural(variant_cx,
|
load_non_structural(variant_cx,
|
||||||
llfp, a.ty);
|
llfldp, a.ty);
|
||||||
|
|
||||||
auto res = f(variant_cx, llfld, a.ty);
|
auto res = f(variant_cx, llfld, a.ty);
|
||||||
variant_cx = res.bcx;
|
variant_cx = res.bcx;
|
||||||
|
@ -1891,7 +1915,8 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
|
||||||
auto navi = new_def_hash[uint]();
|
auto navi = new_def_hash[uint]();
|
||||||
let vec[tup(ast.def_id,arity)] variant_info = vec();
|
let vec[tup(ast.def_id,arity)] variant_info = vec();
|
||||||
cx.tags.insert(tag_id, @rec(th=mk_type_handle(),
|
cx.tags.insert(tag_id, @rec(th=mk_type_handle(),
|
||||||
mutable variants=variant_info));
|
mutable variants=variant_info,
|
||||||
|
mutable size=0u));
|
||||||
cx.items.insert(tag_id, i);
|
cx.items.insert(tag_id, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1918,7 +1943,8 @@ fn collect_items(@crate_ctxt cx, @ast.crate crate) {
|
||||||
fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
|
fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
|
||||||
alt (i.node) {
|
alt (i.node) {
|
||||||
case (ast.item_tag(_, ?variants, _, ?tag_id)) {
|
case (ast.item_tag(_, ?variants, _, ?tag_id)) {
|
||||||
let vec[TypeRef] variant_tys = vec();
|
auto max_align = 0u;
|
||||||
|
auto max_size = 0u;
|
||||||
|
|
||||||
auto info = cx.tags.get(tag_id);
|
auto info = cx.tags.get(tag_id);
|
||||||
let vec[tup(ast.def_id,arity)] variant_info = vec();
|
let vec[tup(ast.def_id,arity)] variant_info = vec();
|
||||||
|
@ -1926,21 +1952,16 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
|
||||||
for (ast.variant variant in variants) {
|
for (ast.variant variant in variants) {
|
||||||
auto arity_info;
|
auto arity_info;
|
||||||
if (_vec.len[@ast.ty](variant.args) > 0u) {
|
if (_vec.len[@ast.ty](variant.args) > 0u) {
|
||||||
let vec[TypeRef] lltys = vec();
|
auto llvariantty = type_of_variant(cx, variant);
|
||||||
|
auto align = llvm.LLVMPreferredAlignmentOfType(cx.td.lltd,
|
||||||
|
llvariantty);
|
||||||
|
auto size = llvm.LLVMStoreSizeOfType(cx.td.lltd,
|
||||||
|
llvariantty) as uint;
|
||||||
|
if (max_align < align) { max_align = align; }
|
||||||
|
if (max_size < size) { max_size = size; }
|
||||||
|
|
||||||
alt (typeck.ann_to_type(variant.ann).struct) {
|
|
||||||
case (typeck.ty_fn(?args, _)) {
|
|
||||||
for (typeck.arg arg in args) {
|
|
||||||
lltys += vec(type_of(cx, arg.ty));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case (_) { fail; }
|
|
||||||
}
|
|
||||||
|
|
||||||
variant_tys += vec(T_struct(lltys));
|
|
||||||
arity_info = n_ary;
|
arity_info = n_ary;
|
||||||
} else {
|
} else {
|
||||||
variant_tys += vec(T_nil());
|
|
||||||
arity_info = nullary;
|
arity_info = nullary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1948,8 +1969,11 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
|
||||||
}
|
}
|
||||||
|
|
||||||
info.variants = variant_info;
|
info.variants = variant_info;
|
||||||
|
info.size = max_size;
|
||||||
|
|
||||||
auto tag_ty = T_struct(vec(T_int(), T_union(variant_tys)));
|
// FIXME: alignment is wrong here, manually insert padding I
|
||||||
|
// guess :(
|
||||||
|
auto tag_ty = T_struct(vec(T_int(), T_array(T_i8(), max_size)));
|
||||||
auto th = cx.tags.get(tag_id).th.llth;
|
auto th = cx.tags.get(tag_id).th.llth;
|
||||||
llvm.LLVMRefineType(llvm.LLVMResolveTypeHandle(th), tag_ty);
|
llvm.LLVMRefineType(llvm.LLVMResolveTypeHandle(th), tag_ty);
|
||||||
}
|
}
|
||||||
|
@ -1990,7 +2014,7 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt {
|
||||||
alt (variant_info._1) {
|
alt (variant_info._1) {
|
||||||
case (nullary) {
|
case (nullary) {
|
||||||
// Nullary tags become constants.
|
// Nullary tags become constants.
|
||||||
auto union_val = C_union(union_ty, C_nil());
|
auto union_val = C_zero_byte_arr(info.size as uint);
|
||||||
auto val = C_struct(vec(C_int(i as int), union_val));
|
auto val = C_struct(vec(C_int(i as int), union_val));
|
||||||
|
|
||||||
// FIXME: better name
|
// FIXME: better name
|
||||||
|
@ -2153,6 +2177,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output) {
|
||||||
|
|
||||||
llvm.LLVMSetDataLayout(llmod, _str.buf(x86.get_data_layout()));
|
llvm.LLVMSetDataLayout(llmod, _str.buf(x86.get_data_layout()));
|
||||||
llvm.LLVMSetTarget(llmod, _str.buf(x86.get_target_triple()));
|
llvm.LLVMSetTarget(llmod, _str.buf(x86.get_target_triple()));
|
||||||
|
auto td = mk_target_data(x86.get_data_layout());
|
||||||
|
|
||||||
llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm()));
|
llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm()));
|
||||||
|
|
||||||
|
@ -2183,6 +2208,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output) {
|
||||||
|
|
||||||
auto cx = @rec(sess = sess,
|
auto cx = @rec(sess = sess,
|
||||||
llmod = llmod,
|
llmod = llmod,
|
||||||
|
td = td,
|
||||||
upcalls = new_str_hash[ValueRef](),
|
upcalls = new_str_hash[ValueRef](),
|
||||||
intrinsics = intrinsics,
|
intrinsics = intrinsics,
|
||||||
item_names = new_str_hash[ValueRef](),
|
item_names = new_str_hash[ValueRef](),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue