AlignInBits: c_ulonglong,
Elements: ValueRef,
ClassType: ValueRef) -> ValueRef;
-}}
+
+ #[fast_ffi]
+ pub unsafe fn LLVMDIBuilderCreateUnionType(
+ Builder: DIBuilderRef,
+ Scope: ValueRef,
+ Name: *c_char,
+ File: ValueRef,
+ LineNumber: c_uint,
+ SizeInBits: c_ulonglong,
+ AlignInBits: c_ulonglong,
+ Flags: c_uint ,
+ Elements: ValueRef,
+ RunTimeLang : c_uint) -> ValueRef;
+ }
+}
pub fn SetInstructionCallConv(Instr: ValueRef, CC: CallConv) {
unsafe {
fields: ~[ty::field],
span: span)
-> DICompositeType {
- debug!("create_struct: %?", ty::get(struct_type));
-
let struct_name = ty_to_str(cx.tcx, struct_type);
+ debug!("create_struct: %s", struct_name);
+
let struct_llvm_type = type_of::type_of(cx, struct_type);
let field_llvm_types = fields.map(|field| type_of::type_of(cx, field.mt.ty));
span: span)
-> DICompositeType {
- let tuple_name = "tuple"; // this should have a better name
+ let tuple_name = ty_to_str(cx.tcx, tuple_type);
let tuple_llvm_type = type_of::type_of(cx, tuple_type);
// Create a vec of empty strings. A vec::build_n() function would be nice for this.
let mut component_names : ~[~str] = vec::with_capacity(component_types.len());
fn create_enum_md(cx: &mut CrateContext,
enum_type: ty::t,
enum_def_id: ast::def_id,
- span: span) -> DIType {
+ substs: &ty::substs,
+ span: span)
+ -> DIType {
let enum_name = ty_to_str(cx.tcx, enum_type);
- let discriminator_llvm_type = Type::enum_discrim(cx);
- let discriminator_size = machine::llsize_of_alloc(cx, discriminator_llvm_type);
- let discriminator_align = machine::llalign_of_min(cx, discriminator_llvm_type);
-
- assert!(Type::enum_discrim(cx) == cx.int_type);
- let discriminator_type_md = get_or_create_type(cx, ty::mk_int(), span);
+ // For empty enums there is an early exit. Just describe it as an empty struct with the
+ // appropriate name
if ty::type_is_empty(cx.tcx, enum_type) {
- // XXX: This should not "rename" the type to nil
- return get_or_create_type(cx, ty::mk_nil(), span);
+ return create_composite_type(cx, Type::nil(), enum_name, &[], &[], &[], span);
}
- if ty::type_is_c_like_enum(cx.tcx, enum_type) {
+ // Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be
+ // needed in all of the following cases.
+ let discriminant_llvm_type = Type::enum_discrim(cx);
+ let discriminant_size = machine::llsize_of_alloc(cx, discriminant_llvm_type);
+ let discriminant_align = machine::llalign_of_min(cx, discriminant_llvm_type);
+ assert!(Type::enum_discrim(cx) == cx.int_type);
+ let discriminant_type_md = get_or_create_type(cx, ty::mk_int(), span);
+
+
+ let variants : &[ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id);
- let variants : &[ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id);
+ let enumerators : ~[(~str, int)] = variants
+ .iter()
+ .transform(|v| (cx.sess.str_of(v.name).to_owned(), v.disr_val))
+ .collect();
+
+ let enumerators_md : ~[DIDescriptor] =
+ do enumerators.iter().transform |&(name,value)| {
+ do name.as_c_str |name| { unsafe {
+ llvm::LLVMDIBuilderCreateEnumerator(
+ DIB(cx),
+ name,
+ value as c_ulonglong)
+ }}
+ }.collect();
- let enumerators : ~[(~str, int)] = variants
- .iter()
- .transform(|v| (cx.sess.str_of(v.name).to_owned(), v.disr_val))
- .collect();
+ let loc = span_start(cx, span);
+ let file_metadata = get_or_create_file(cx, loc.file.name);
- let enumerators_md : ~[DIDescriptor] =
- do enumerators.iter().transform |&(name,value)| {
- do name.as_c_str |name| { unsafe {
- llvm::LLVMDIBuilderCreateEnumerator(
- DIB(cx),
- name,
- value as c_ulonglong)
- }}
- }.collect();
+ let discriminant_type_md = do enum_name.as_c_str |enum_name| { unsafe {
+ llvm::LLVMDIBuilderCreateEnumerationType(
+ DIB(cx),
+ file_metadata,
+ enum_name,
+ file_metadata,
+ loc.line as c_uint,
+ bytes_to_bits(discriminant_size),
+ bytes_to_bits(discriminant_align),
+ create_DIArray(DIB(cx), enumerators_md),
+ discriminant_type_md)
+ }};
- let loc = span_start(cx, span);
- let file_metadata = get_or_create_file(cx, loc.file.name);
+ if ty::type_is_c_like_enum(cx.tcx, enum_type) {
+ return discriminant_type_md;
+ }
- return do enum_name.as_c_str |enum_name| { unsafe {
- llvm::LLVMDIBuilderCreateEnumerationType(
+ let variants_md = do variants.map |&vi| {
+
+ let raw_types : &[ty::t] = vi.args;
+ let arg_types = do raw_types.map |&raw_type| { ty::subst(cx.tcx, substs, raw_type) };
+ let arg_llvm_types = ~[discriminant_llvm_type] + do arg_types.map |&ty| { type_of::type_of(cx, ty) };
+ let arg_names = ~[~""] + arg_types.map(|_| ~"");
+ let arg_md = ~[discriminant_type_md] + do arg_types.map |&ty| { get_or_create_type(cx, ty, span) };
+
+ let variant_llvm_type = Type::struct_(arg_llvm_types, false);
+ let variant_type_size = machine::llsize_of_alloc(cx, variant_llvm_type);
+ let variant_type_align = machine::llalign_of_min(cx, variant_llvm_type);
+
+ let variant_type_md = create_composite_type(
+ cx,
+ variant_llvm_type,
+ &"",
+ arg_llvm_types,
+ arg_names,
+ arg_md,
+ span);
+
+ do "".as_c_str |name| { unsafe {
+ llvm::LLVMDIBuilderCreateMemberType(
DIB(cx),
file_metadata,
- enum_name,
+ name,
file_metadata,
loc.line as c_uint,
- bytes_to_bits(discriminator_size),
- bytes_to_bits(discriminator_align),
- create_DIArray(DIB(cx), enumerators_md),
- discriminator_type_md)
- }};
- }
-
- cx.sess.bug("");
-}
+ bytes_to_bits(variant_type_size),
+ bytes_to_bits(variant_type_align),
+ bytes_to_bits(0),
+ 0,
+ variant_type_md)
+ }}
+ };
+ let enum_llvm_type = type_of::type_of(cx, enum_type);
+ let enum_type_size = machine::llsize_of_alloc(cx, enum_llvm_type);
+ let enum_type_align = machine::llalign_of_min(cx, enum_llvm_type);
+ return do "".as_c_str |enum_name| { unsafe { llvm::LLVMDIBuilderCreateUnionType(
+ DIB(cx),
+ file_metadata,
+ enum_name,
+ file_metadata,
+ loc.line as c_uint,
+ bytes_to_bits(enum_type_size),
+ bytes_to_bits(enum_type_align),
+ 0, // Flags
+ create_DIArray(DIB(cx), variants_md),
+ 0) // RuntimeLang
+ }};
+}
/// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
}
}
},
- ty::ty_enum(def_id, ref _substs) => {
- //cx.sess.span_note(span, "debuginfo for enum NYI");
- //create_unimpl_ty(cx, t)
- create_enum_md(cx, t, def_id, span)
+ ty::ty_enum(def_id, ref substs) => {
+ create_enum_md(cx, t, def_id, substs, span)
},
ty::ty_box(ref mt) |
ty::ty_uniq(ref mt) => {
typedef DIBuilder* DIBuilderRef;
template<typename DIT>
-DIT unwrapDI(LLVMValueRef ref) {
- return DIT(ref ? unwrap<MDNode>(ref) : NULL);
+DIT unwrapDI(LLVMValueRef ref) {
+ return DIT(ref ? unwrap<MDNode>(ref) : NULL);
}
extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) {
extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType(
DIBuilderRef Builder,
- LLVMValueRef File,
+ LLVMValueRef File,
LLVMValueRef ParameterTypes) {
return wrap(Builder->createSubroutineType(
- unwrapDI<DIFile>(File),
+ unwrapDI<DIFile>(File),
unwrapDI<DIArray>(ParameterTypes)));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateFunction(
DIBuilderRef Builder,
- LLVMValueRef Scope,
+ LLVMValueRef Scope,
const char* Name,
const char* LinkageName,
- LLVMValueRef File,
+ LLVMValueRef File,
unsigned LineNo,
- LLVMValueRef Ty,
+ LLVMValueRef Ty,
bool isLocalToUnit,
bool isDefinition,
unsigned ScopeLine,
LLVMValueRef TParam,
LLVMValueRef Decl) {
return wrap(Builder->createFunction(
- unwrapDI<DIScope>(Scope), Name, LinkageName,
- unwrapDI<DIFile>(File), LineNo,
- unwrapDI<DIType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
+ unwrapDI<DIScope>(Scope), Name, LinkageName,
+ unwrapDI<DIFile>(File), LineNo,
+ unwrapDI<DIType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
Flags, isOptimized,
- unwrap<Function>(Fn),
+ unwrap<Function>(Fn),
unwrapDI<MDNode*>(TParam),
unwrapDI<MDNode*>(Decl)));
}
uint64_t AlignInBits,
unsigned Encoding) {
return wrap(Builder->createBasicType(
- Name, SizeInBits,
+ Name, SizeInBits,
AlignInBits, Encoding));
}
-
+
extern "C" LLVMValueRef LLVMDIBuilderCreatePointerType(
DIBuilderRef Builder,
LLVMValueRef PointeeTy,
unsigned RunTimeLang,
LLVMValueRef VTableHolder) {
return wrap(Builder->createStructType(
- unwrapDI<DIDescriptor>(Scope), Name,
- unwrapDI<DIFile>(File), LineNumber,
- SizeInBits, AlignInBits, Flags,
- unwrapDI<DIType>(DerivedFrom),
- unwrapDI<DIArray>(Elements), RunTimeLang,
+ unwrapDI<DIDescriptor>(Scope), Name,
+ unwrapDI<DIFile>(File), LineNumber,
+ SizeInBits, AlignInBits, Flags,
+ unwrapDI<DIType>(DerivedFrom),
+ unwrapDI<DIArray>(Elements), RunTimeLang,
unwrapDI<MDNode*>(VTableHolder)));
}
unsigned Flags,
LLVMValueRef Ty) {
return wrap(Builder->createMemberType(
- unwrapDI<DIDescriptor>(Scope), Name,
+ unwrapDI<DIDescriptor>(Scope), Name,
unwrapDI<DIFile>(File), LineNo,
- SizeInBits, AlignInBits, OffsetInBits, Flags,
+ SizeInBits, AlignInBits, OffsetInBits, Flags,
unwrapDI<DIType>(Ty)));
}
-
+
extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock(
DIBuilderRef Builder,
LLVMValueRef Scope,
unsigned Line,
unsigned Col) {
return wrap(Builder->createLexicalBlock(
- unwrapDI<DIDescriptor>(Scope),
+ unwrapDI<DIDescriptor>(Scope),
unwrapDI<DIFile>(File), Line, Col));
}
-
+
extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable(
DIBuilderRef Builder,
unsigned Tag,
bool AlwaysPreserve,
unsigned Flags,
unsigned ArgNo) {
- return wrap(Builder->createLocalVariable(Tag,
- unwrapDI<DIDescriptor>(Scope), Name,
- unwrapDI<DIFile>(File),
- LineNo,
+ return wrap(Builder->createLocalVariable(Tag,
+ unwrapDI<DIDescriptor>(Scope), Name,
+ unwrapDI<DIFile>(File),
+ LineNo,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateArrayType(
DIBuilderRef Builder,
- uint64_t Size,
- uint64_t AlignInBits,
- LLVMValueRef Ty,
+ uint64_t Size,
+ uint64_t AlignInBits,
+ LLVMValueRef Ty,
LLVMValueRef Subscripts) {
return wrap(Builder->createArrayType(Size, AlignInBits,
- unwrapDI<DIType>(Ty),
+ unwrapDI<DIType>(Ty),
unwrapDI<DIArray>(Subscripts)));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateVectorType(
DIBuilderRef Builder,
- uint64_t Size,
- uint64_t AlignInBits,
- LLVMValueRef Ty,
+ uint64_t Size,
+ uint64_t AlignInBits,
+ LLVMValueRef Ty,
LLVMValueRef Subscripts) {
return wrap(Builder->createVectorType(Size, AlignInBits,
- unwrapDI<DIType>(Ty),
+ unwrapDI<DIType>(Ty),
unwrapDI<DIArray>(Subscripts)));
}
extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateSubrange(
- DIBuilderRef Builder,
- int64_t Lo,
+ DIBuilderRef Builder,
+ int64_t Lo,
int64_t Count) {
return wrap(Builder->getOrCreateSubrange(Lo, Count));
}
extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateArray(
DIBuilderRef Builder,
- LLVMValueRef* Ptr,
+ LLVMValueRef* Ptr,
unsigned Count) {
return wrap(Builder->getOrCreateArray(
ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
LLVMValueRef VarInfo,
LLVMBasicBlockRef InsertAtEnd) {
return wrap(Builder->insertDeclare(
- unwrap(Val),
- unwrapDI<DIVariable>(VarInfo),
+ unwrap(Val),
+ unwrapDI<DIVariable>(VarInfo),
unwrap(InsertAtEnd)));
}
LLVMValueRef VarInfo,
LLVMValueRef InsertBefore) {
return wrap(Builder->insertDeclare(
- unwrap(Val),
- unwrapDI<DIVariable>(VarInfo),
+ unwrap(Val),
+ unwrapDI<DIVariable>(VarInfo),
unwrap<Instruction>(InsertBefore)));
}
AlignInBits,
unwrapDI<DIArray>(Elements),
unwrapDI<DIType>(ClassType)));
+}
+
+extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
+ DIBuilderRef Builder,
+ LLVMValueRef Scope,
+ const char* Name,
+ LLVMValueRef File,
+ unsigned LineNumber,
+ uint64_t SizeInBits,
+ uint64_t AlignInBits,
+ unsigned Flags,
+ LLVMValueRef Elements,
+ unsigned RunTimeLang)
+{
+ return wrap(Builder->createUnionType(
+ unwrapDI<DIDescriptor>(Scope),
+ Name,
+ unwrapDI<DIFile>(File),
+ LineNumber,
+ SizeInBits,
+ AlignInBits,
+ Flags,
+ unwrapDI<DIArray>(Elements),
+ RunTimeLang));
}
\ No newline at end of file
// debugger:print manual_one_million
// check:$6 = OneMillion
+// debugger:print single_variant
+// check:$7 = TheOnlyVariant
-enum AutoDiscriminator {
+enum AutoDiscriminant {
One,
Two,
Three
}
-enum ManualDiscriminator {
+enum ManualDiscriminant {
OneHundred = 100,
OneThousand = 1000,
OneMillion = 1000000
}
+enum SingleVariant {
+ TheOnlyVariant
+}
+
fn main() {
let auto_one = One;
let manual_one_thousand = OneThousand;
let manual_one_million = OneMillion;
+ let single_variant = TheOnlyVariant;
+
zzz();
}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print first
+// check:$1 = {<No data fields>}
+
+// debugger:print second
+// check:$2 = {<No data fields>}
+
+enum ANilEnum {}
+enum AnotherNilEnum {}
+
+// I (mw) am not sure this test case makes much sense...
+// Also, it relies on some implementation details:
+// 1. That empty enums as well as '()' are represented as empty structs
+// 2. That gdb prints the string "{<No data fields>}" for empty structs (which may change some time)
+fn main() {
+ unsafe {
+ let first : ANilEnum = std::cast::transmute(());
+ let second : AnotherNilEnum = std::cast::transmute(());
+
+ zzz();
+ }
+}
+
+fn zzz() {()}
\ No newline at end of file
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print union on
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print case2
+// check:$1 = {Case1, 0, 1}
+
+enum Test {
+ Case1(i32, i64),
+ Case2(bool, i16, i32)
+}
+
+fn main() {
+
+ let case1 = Case1(110, 220);
+ let case2 = Case2(false, 2, 3);
+
+ zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file