From 3a47103f1d2bbf144d3866abc9fe74a9143d2988 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 26 May 2016 13:04:35 -0400 Subject: [PATCH] Fix codegen tests by make sure items are translated in AST order. --- src/librustc_trans/base.rs | 4 +-- src/librustc_trans/partitioning.rs | 44 +++++++++++++++++++++++++++--- src/test/codegen/drop.rs | 14 +++++----- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 234ed800c47..e13eea6f8ce 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2626,7 +2626,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Instantiate translation items without filling out definitions yet... for ccx in crate_context_list.iter() { let trans_items = ccx.codegen_unit() - .items_in_deterministic_order(&symbol_map); + .items_in_deterministic_order(tcx, &symbol_map); for (trans_item, linkage) in trans_items { trans_item.predefine(&ccx, linkage); @@ -2636,7 +2636,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // ... and now that we have everything pre-defined, fill out those definitions. for ccx in crate_context_list.iter() { let trans_items = ccx.codegen_unit() - .items_in_deterministic_order(&symbol_map); + .items_in_deterministic_order(tcx, &symbol_map); for (trans_item, _) in trans_items { trans_item.define(&ccx); diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 0e06fd6235e..2f1961ac9f8 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -124,7 +124,9 @@ use rustc::hir::map::DefPathData; use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER; use rustc::ty::TyCtxt; use rustc::ty::item_path::characteristic_def_id_of_type; +use std::cmp::Ordering; use symbol_map::SymbolMap; +use syntax::ast::NodeId; use syntax::parse::token::{self, InternedString}; use trans_item::TransItem; use util::nodemap::{FnvHashMap, FnvHashSet, NodeSet}; @@ -144,18 +146,52 @@ pub struct CodegenUnit<'tcx> { impl<'tcx> CodegenUnit<'tcx> { pub fn items_in_deterministic_order(&self, + tcx: TyCtxt, symbol_map: &SymbolMap) -> Vec<(TransItem<'tcx>, llvm::Linkage)> { let mut items: Vec<(TransItem<'tcx>, llvm::Linkage)> = self.items.iter().map(|(item, linkage)| (*item, *linkage)).collect(); + // The codegen tests rely on items being process in the same order as + // they appear in the file, so for local items, we sort by node_id first items.as_mut_slice().sort_by(|&(trans_item1, _), &(trans_item2, _)| { - let symbol_name1 = symbol_map.get(trans_item1).unwrap(); - let symbol_name2 = symbol_map.get(trans_item2).unwrap(); - symbol_name1.cmp(symbol_name2) + + let node_id1 = local_node_id(tcx, trans_item1); + let node_id2 = local_node_id(tcx, trans_item2); + + match (node_id1, node_id2) { + (None, None) => { + let symbol_name1 = symbol_map.get(trans_item1).unwrap(); + let symbol_name2 = symbol_map.get(trans_item2).unwrap(); + symbol_name1.cmp(symbol_name2) + } + (None, Some(_)) => Ordering::Less, + (Some(_), None) => Ordering::Greater, + (Some(node_id1), Some(node_id2)) => { + let ordering = node_id1.cmp(&node_id2); + + if ordering != Ordering::Equal { + return ordering; + } + + let symbol_name1 = symbol_map.get(trans_item1).unwrap(); + let symbol_name2 = symbol_map.get(trans_item2).unwrap(); + symbol_name1.cmp(symbol_name2) + } + } }); - items + return items; + + fn local_node_id(tcx: TyCtxt, trans_item: TransItem) -> Option { + match trans_item { + TransItem::Fn(instance) => { + tcx.map.as_local_node_id(instance.def) + } + TransItem::Static(node_id) => Some(node_id), + TransItem::DropGlue(_) => None, + } + } } } diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs index 83dd6a3b002..25f8c130469 100644 --- a/src/test/codegen/drop.rs +++ b/src/test/codegen/drop.rs @@ -31,13 +31,13 @@ pub fn droppy() { // that's one new drop call per call to possibly_unwinding(), and finally 3 drop calls for the // regular function exit. We used to have problems with quadratic growths of drop calls in such // functions. -// CHECK: call{{.*}}SomeUniqueName{{.*}}drop -// CHECK: call{{.*}}SomeUniqueName{{.*}}drop -// CHECK: call{{.*}}SomeUniqueName{{.*}}drop -// CHECK: call{{.*}}SomeUniqueName{{.*}}drop -// CHECK: call{{.*}}SomeUniqueName{{.*}}drop -// CHECK: call{{.*}}SomeUniqueName{{.*}}drop -// CHECK-NOT: call{{.*}}SomeUniqueName{{.*}}drop +// CHECK: call{{.*}}drop{{.*}}SomeUniqueName +// CHECK: call{{.*}}drop{{.*}}SomeUniqueName +// CHECK: call{{.*}}drop{{.*}}SomeUniqueName +// CHECK: call{{.*}}drop{{.*}}SomeUniqueName +// CHECK: call{{.*}}drop{{.*}}SomeUniqueName +// CHECK: call{{.*}}drop{{.*}}SomeUniqueName +// CHECK-NOT: call{{.*}}drop{{.*}}SomeUniqueName // The next line checks for the } that ends the function definition // CHECK-LABEL: {{^[}]}} let _s = SomeUniqueName;