Upgrade to LLVM's master branch (LLVM 7)
This commit upgrades the main LLVM submodule to LLVM's current master branch. The LLD submodule is updated in tandem as well as compiler-builtins. Along the way support was also added for LLVM 7's new features. This primarily includes the support for custom section concatenation natively in LLD so we now add wasm custom sections in LLVM IR rather than having custom support in rustc itself for doing so. Some other miscellaneous changes are: * We now pass `--gc-sections` to `wasm-ld` * The optimization level is now passed to `wasm-ld` * A `--stack-first` option is passed to LLD to have stack overflow always cause a trap instead of corrupting static data * The wasm target for LLVM switched to `wasm32-unknown-unknown`. * The syntax for aligned pointers has changed in LLVM IR and tests are updated to reflect this. * The `thumbv6m-none-eabi` target is disabled due to an [LLVM bug][llbug] Nowadays we've been mostly only upgrading whenever there's a major release of LLVM but enough changes have been happening on the wasm target that there's been growing motivation for quite some time now to upgrade out version of LLD. To upgrade LLD, however, we need to upgrade LLVM to avoid needing to build yet another version of LLVM on the builders. The revision of LLVM in use here is arbitrarily chosen. We will likely need to continue to update it over time if and when we discover bugs. Once LLVM 7 is fully released we can switch to that channel as well. [llbug]: https://bugs.llvm.org/show_bug.cgi?id=37382
This commit is contained in:
parent
c30acc7187
commit
42eb85002a
|
@ -1 +1 @@
|
||||||
Subproject commit 4cfd7101eb549169cdaeda5313f7c39415b9d736
|
Subproject commit 86bf357a14cacb4a4169455e729d409b5ecc1da0
|
|
@ -665,8 +665,6 @@ define_dep_nodes!( <'tcx>
|
||||||
|
|
||||||
[] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> },
|
[] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> },
|
||||||
|
|
||||||
[] WasmCustomSections(CrateNum),
|
|
||||||
|
|
||||||
[input] Features,
|
[input] Features,
|
||||||
|
|
||||||
[] ProgramClausesFor(DefId),
|
[] ProgramClausesFor(DefId),
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct CheckAttrVisitor<'a, 'tcx: 'a> {
|
||||||
impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
|
||||||
/// Check any attribute.
|
/// Check any attribute.
|
||||||
fn check_attributes(&self, item: &hir::Item, target: Target) {
|
fn check_attributes(&self, item: &hir::Item, target: Target) {
|
||||||
if target == Target::Fn {
|
if target == Target::Fn || target == Target::Const {
|
||||||
self.tcx.codegen_fn_attrs(self.tcx.hir.local_def_id(item.id));
|
self.tcx.codegen_fn_attrs(self.tcx.hir.local_def_id(item.id));
|
||||||
} else if let Some(a) = item.attrs.iter().find(|a| a.check_name("target_feature")) {
|
} else if let Some(a) = item.attrs.iter().find(|a| a.check_name("target_feature")) {
|
||||||
self.tcx.sess.struct_span_err(a.span, "attribute should be applied to a function")
|
self.tcx.sess.struct_span_err(a.span, "attribute should be applied to a function")
|
||||||
|
@ -85,11 +85,6 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
|
||||||
if target != Target::Const {
|
if target != Target::Const {
|
||||||
self.tcx.sess.span_err(attr.span, "only allowed on consts");
|
self.tcx.sess.span_err(attr.span, "only allowed on consts");
|
||||||
}
|
}
|
||||||
|
|
||||||
if attr.value_str().is_none() {
|
|
||||||
self.tcx.sess.span_err(attr.span, "must be of the form \
|
|
||||||
#[wasm_custom_section = \"foo\"]");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2259,6 +2259,7 @@ pub struct CodegenFnAttrs {
|
||||||
pub export_name: Option<Symbol>,
|
pub export_name: Option<Symbol>,
|
||||||
pub target_features: Vec<Symbol>,
|
pub target_features: Vec<Symbol>,
|
||||||
pub linkage: Option<Linkage>,
|
pub linkage: Option<Linkage>,
|
||||||
|
pub wasm_custom_section: Option<Symbol>,
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
@ -2283,6 +2284,7 @@ impl CodegenFnAttrs {
|
||||||
export_name: None,
|
export_name: None,
|
||||||
target_features: vec![],
|
target_features: vec![],
|
||||||
linkage: None,
|
linkage: None,
|
||||||
|
wasm_custom_section: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1120,6 +1120,7 @@ impl_stable_hash_for!(struct hir::CodegenFnAttrs {
|
||||||
export_name,
|
export_name,
|
||||||
target_features,
|
target_features,
|
||||||
linkage,
|
linkage,
|
||||||
|
wasm_custom_section,
|
||||||
});
|
});
|
||||||
|
|
||||||
impl<'hir> HashStable<StableHashingContext<'hir>> for hir::CodegenFnAttrFlags
|
impl<'hir> HashStable<StableHashingContext<'hir>> for hir::CodegenFnAttrFlags
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub enum MonoItem<'tcx> {
|
||||||
Fn(Instance<'tcx>),
|
Fn(Instance<'tcx>),
|
||||||
Static(DefId),
|
Static(DefId),
|
||||||
GlobalAsm(NodeId),
|
GlobalAsm(NodeId),
|
||||||
|
CustomSection(DefId),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MonoItem<'tcx> {
|
impl<'tcx> MonoItem<'tcx> {
|
||||||
|
@ -36,7 +37,9 @@ impl<'tcx> MonoItem<'tcx> {
|
||||||
},
|
},
|
||||||
// Conservatively estimate the size of a static declaration
|
// Conservatively estimate the size of a static declaration
|
||||||
// or assembly to be 1.
|
// or assembly to be 1.
|
||||||
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1,
|
MonoItem::Static(_) |
|
||||||
|
MonoItem::GlobalAsm(_) |
|
||||||
|
MonoItem::CustomSection(_) => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +54,8 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for MonoItem<'tcx> {
|
||||||
MonoItem::Fn(ref instance) => {
|
MonoItem::Fn(ref instance) => {
|
||||||
instance.hash_stable(hcx, hasher);
|
instance.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
MonoItem::Static(def_id) => {
|
MonoItem::Static(def_id) |
|
||||||
|
MonoItem::CustomSection(def_id) => {
|
||||||
def_id.hash_stable(hcx, hasher);
|
def_id.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
MonoItem::GlobalAsm(node_id) => {
|
MonoItem::GlobalAsm(node_id) => {
|
||||||
|
|
|
@ -776,12 +776,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::instance_def_size_estimate<'tcx>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> QueryDescription<'tcx> for queries::wasm_custom_sections<'tcx> {
|
|
||||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
|
||||||
format!("custom wasm sections for a crate")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> QueryDescription<'tcx> for queries::generics_of<'tcx> {
|
impl<'tcx> QueryDescription<'tcx> for queries::generics_of<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cache_on_disk(def_id: Self::Key) -> bool {
|
fn cache_on_disk(def_id: Self::Key) -> bool {
|
||||||
|
|
|
@ -546,7 +546,6 @@ define_queries! { <'tcx>
|
||||||
ty::ParamEnv<'tcx>
|
ty::ParamEnv<'tcx>
|
||||||
) -> Clauses<'tcx>,
|
) -> Clauses<'tcx>,
|
||||||
|
|
||||||
[] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc<Vec<DefId>>,
|
|
||||||
[] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
|
[] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
|
||||||
-> Lrc<FxHashMap<DefId, String>>,
|
-> Lrc<FxHashMap<DefId, String>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1208,7 +1208,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
||||||
DepKind::Features => { force!(features_query, LOCAL_CRATE); }
|
DepKind::Features => { force!(features_query, LOCAL_CRATE); }
|
||||||
|
|
||||||
DepKind::ProgramClausesFor => { force!(program_clauses_for, def_id!()); }
|
DepKind::ProgramClausesFor => { force!(program_clauses_for, def_id!()); }
|
||||||
DepKind::WasmCustomSections => { force!(wasm_custom_sections, krate!()); }
|
|
||||||
DepKind::WasmImportModuleMap => { force!(wasm_import_module_map, krate!()); }
|
DepKind::WasmImportModuleMap => { force!(wasm_import_module_map, krate!()); }
|
||||||
DepKind::ForeignModules => { force!(foreign_modules, krate!()); }
|
DepKind::ForeignModules => { force!(foreign_modules, krate!()); }
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,8 @@
|
||||||
|
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
|
|
||||||
use rustc::hir::{self, CodegenFnAttrFlags};
|
use rustc::hir::CodegenFnAttrFlags;
|
||||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::session::config::Sanitizer;
|
use rustc::session::config::Sanitizer;
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
|
@ -222,37 +221,9 @@ pub fn provide(providers: &mut Providers) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
providers.wasm_custom_sections = |tcx, cnum| {
|
|
||||||
assert_eq!(cnum, LOCAL_CRATE);
|
|
||||||
let mut finder = WasmSectionFinder { tcx, list: Vec::new() };
|
|
||||||
tcx.hir.krate().visit_all_item_likes(&mut finder);
|
|
||||||
Lrc::new(finder.list)
|
|
||||||
};
|
|
||||||
|
|
||||||
provide_extern(providers);
|
provide_extern(providers);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WasmSectionFinder<'a, 'tcx: 'a> {
|
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|
||||||
list: Vec<DefId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for WasmSectionFinder<'a, 'tcx> {
|
|
||||||
fn visit_item(&mut self, i: &'tcx hir::Item) {
|
|
||||||
match i.node {
|
|
||||||
hir::ItemConst(..) => {}
|
|
||||||
_ => return,
|
|
||||||
}
|
|
||||||
if i.attrs.iter().any(|i| i.check_name("wasm_custom_section")) {
|
|
||||||
self.list.push(self.tcx.hir.local_def_id(i.id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {}
|
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn provide_extern(providers: &mut Providers) {
|
pub fn provide_extern(providers: &mut Providers) {
|
||||||
providers.wasm_import_module_map = |tcx, cnum| {
|
providers.wasm_import_module_map = |tcx, cnum| {
|
||||||
let mut ret = FxHashMap();
|
let mut ret = FxHashMap();
|
||||||
|
|
|
@ -29,7 +29,7 @@ use rustc::util::common::time;
|
||||||
use rustc::util::fs::fix_windows_verbatim_for_gcc;
|
use rustc::util::fs::fix_windows_verbatim_for_gcc;
|
||||||
use rustc::hir::def_id::CrateNum;
|
use rustc::hir::def_id::CrateNum;
|
||||||
use tempfile::{Builder as TempFileBuilder, TempDir};
|
use tempfile::{Builder as TempFileBuilder, TempDir};
|
||||||
use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor, TargetTriple};
|
use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor};
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use context::get_reloc_model;
|
use context::get_reloc_model;
|
||||||
use llvm;
|
use llvm;
|
||||||
|
@ -837,10 +837,8 @@ fn link_natively(sess: &Session,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sess.opts.target_triple == TargetTriple::from_triple("wasm32-unknown-unknown") {
|
if sess.opts.target_triple.triple() == "wasm32-unknown-unknown" {
|
||||||
wasm::rewrite_imports(&out_filename, &codegen_results.crate_info.wasm_imports);
|
wasm::rewrite_imports(&out_filename, &codegen_results.crate_info.wasm_imports);
|
||||||
wasm::add_custom_sections(&out_filename,
|
|
||||||
&codegen_results.crate_info.wasm_custom_sections);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,7 @@ impl LinkerInfo {
|
||||||
LinkerFlavor::Lld(LldFlavor::Wasm) => {
|
LinkerFlavor::Lld(LldFlavor::Wasm) => {
|
||||||
Box::new(WasmLd {
|
Box::new(WasmLd {
|
||||||
cmd,
|
cmd,
|
||||||
|
sess,
|
||||||
}) as Box<Linker>
|
}) as Box<Linker>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -919,11 +920,12 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
|
||||||
symbols
|
symbols
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WasmLd {
|
pub struct WasmLd<'a> {
|
||||||
cmd: Command,
|
cmd: Command,
|
||||||
|
sess: &'a Session,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Linker for WasmLd {
|
impl<'a> Linker for WasmLd<'a> {
|
||||||
fn link_dylib(&mut self, lib: &str) {
|
fn link_dylib(&mut self, lib: &str) {
|
||||||
self.cmd.arg("-l").arg(lib);
|
self.cmd.arg("-l").arg(lib);
|
||||||
}
|
}
|
||||||
|
@ -988,9 +990,20 @@ impl Linker for WasmLd {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gc_sections(&mut self, _keep_metadata: bool) {
|
fn gc_sections(&mut self, _keep_metadata: bool) {
|
||||||
|
self.cmd.arg("--gc-sections");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn optimize(&mut self) {
|
fn optimize(&mut self) {
|
||||||
|
self.cmd.arg(match self.sess.opts.optimize {
|
||||||
|
OptLevel::No => "-O0",
|
||||||
|
OptLevel::Less => "-O1",
|
||||||
|
OptLevel::Default => "-O2",
|
||||||
|
OptLevel::Aggressive => "-O3",
|
||||||
|
// Currently LLD doesn't support `Os` and `Oz`, so pass through `O2`
|
||||||
|
// instead.
|
||||||
|
OptLevel::Size => "-O2",
|
||||||
|
OptLevel::SizeMin => "-O2"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pgo_gen(&mut self) {
|
fn pgo_gen(&mut self) {
|
||||||
|
@ -1020,8 +1033,28 @@ impl Linker for WasmLd {
|
||||||
// this isn't yet the bottleneck of compilation at all anyway.
|
// this isn't yet the bottleneck of compilation at all anyway.
|
||||||
self.cmd.arg("--no-threads");
|
self.cmd.arg("--no-threads");
|
||||||
|
|
||||||
|
// By default LLD only gives us one page of stack (64k) which is a
|
||||||
|
// little small. Default to a larger stack closer to other PC platforms
|
||||||
|
// (1MB) and users can always inject their own link-args to override this.
|
||||||
self.cmd.arg("-z").arg("stack-size=1048576");
|
self.cmd.arg("-z").arg("stack-size=1048576");
|
||||||
|
|
||||||
|
// By default LLD's memory layout is:
|
||||||
|
//
|
||||||
|
// 1. First, a blank page
|
||||||
|
// 2. Next, all static data
|
||||||
|
// 3. Finally, the main stack (which grows down)
|
||||||
|
//
|
||||||
|
// This has the unfortunate consequence that on stack overflows you
|
||||||
|
// corrupt static data and can cause some exceedingly weird bugs. To
|
||||||
|
// help detect this a little sooner we instead request that the stack is
|
||||||
|
// placed before static data.
|
||||||
|
//
|
||||||
|
// This means that we'll generate slightly larger binaries as references
|
||||||
|
// to static data will take more bytes in the ULEB128 encoding, but
|
||||||
|
// stack overflow will be guaranteed to trap as it underflows instead of
|
||||||
|
// corrupting static data.
|
||||||
|
self.cmd.arg("--stack-first");
|
||||||
|
|
||||||
// FIXME we probably shouldn't pass this but instead pass an explicit
|
// FIXME we probably shouldn't pass this but instead pass an explicit
|
||||||
// whitelist of symbols we'll allow to be undefined. Unfortunately
|
// whitelist of symbols we'll allow to be undefined. Unfortunately
|
||||||
// though we can't handle symbols like `log10` that LLVM injects at a
|
// though we can't handle symbols like `log10` that LLVM injects at a
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
@ -24,45 +23,6 @@ const WASM_EXTERNAL_KIND_TABLE: u8 = 1;
|
||||||
const WASM_EXTERNAL_KIND_MEMORY: u8 = 2;
|
const WASM_EXTERNAL_KIND_MEMORY: u8 = 2;
|
||||||
const WASM_EXTERNAL_KIND_GLOBAL: u8 = 3;
|
const WASM_EXTERNAL_KIND_GLOBAL: u8 = 3;
|
||||||
|
|
||||||
/// Append all the custom sections listed in `sections` to the wasm binary
|
|
||||||
/// specified at `path`.
|
|
||||||
///
|
|
||||||
/// LLVM 6 which we're using right now doesn't have the ability to create custom
|
|
||||||
/// sections in wasm files nor does LLD have the ability to merge these sections
|
|
||||||
/// into one larger section when linking. It's expected that this will
|
|
||||||
/// eventually get implemented, however!
|
|
||||||
///
|
|
||||||
/// Until that time though this is a custom implementation in rustc to append
|
|
||||||
/// all sections to a wasm file to the finished product that LLD produces.
|
|
||||||
///
|
|
||||||
/// Support for this is landing in LLVM in https://reviews.llvm.org/D43097,
|
|
||||||
/// although after that support will need to be in LLD as well.
|
|
||||||
pub fn add_custom_sections(path: &Path, sections: &BTreeMap<String, Vec<u8>>) {
|
|
||||||
if sections.len() == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let wasm = fs::read(path).expect("failed to read wasm output");
|
|
||||||
|
|
||||||
// see https://webassembly.github.io/spec/core/binary/modules.html#custom-section
|
|
||||||
let mut wasm = WasmEncoder { data: wasm };
|
|
||||||
for (section, bytes) in sections {
|
|
||||||
// write the `id` identifier, 0 for a custom section
|
|
||||||
wasm.byte(0);
|
|
||||||
|
|
||||||
// figure out how long our name descriptor will be
|
|
||||||
let mut name = WasmEncoder::new();
|
|
||||||
name.str(section);
|
|
||||||
|
|
||||||
// write the length of the payload followed by all its contents
|
|
||||||
wasm.u32((bytes.len() + name.data.len()) as u32);
|
|
||||||
wasm.data.extend_from_slice(&name.data);
|
|
||||||
wasm.data.extend_from_slice(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs::write(path, &wasm.data).expect("failed to write wasm output");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Rewrite the module imports are listed from in a wasm module given the field
|
/// Rewrite the module imports are listed from in a wasm module given the field
|
||||||
/// name to module name mapping in `import_map`.
|
/// name to module name mapping in `import_map`.
|
||||||
///
|
///
|
||||||
|
@ -80,7 +40,7 @@ pub fn add_custom_sections(path: &Path, sections: &BTreeMap<String, Vec<u8>>) {
|
||||||
///
|
///
|
||||||
/// Support for this was added to LLVM in
|
/// Support for this was added to LLVM in
|
||||||
/// https://github.com/llvm-mirror/llvm/commit/0f32e1365, although support still
|
/// https://github.com/llvm-mirror/llvm/commit/0f32e1365, although support still
|
||||||
/// needs to be added (AFAIK at the time of this writing) to LLD
|
/// needs to be added, tracked at https://bugs.llvm.org/show_bug.cgi?id=37168
|
||||||
pub fn rewrite_imports(path: &Path, import_map: &FxHashMap<String, String>) {
|
pub fn rewrite_imports(path: &Path, import_map: &FxHashMap<String, String>) {
|
||||||
if import_map.len() == 0 {
|
if import_map.len() == 0 {
|
||||||
return
|
return
|
||||||
|
|
|
@ -33,6 +33,7 @@ use back::link;
|
||||||
use back::write::{self, OngoingCodegen, create_target_machine};
|
use back::write::{self, OngoingCodegen, create_target_machine};
|
||||||
use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
|
use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
|
||||||
use llvm;
|
use llvm;
|
||||||
|
use libc::c_uint;
|
||||||
use metadata;
|
use metadata;
|
||||||
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||||
use rustc::middle::lang_items::StartFnLangItem;
|
use rustc::middle::lang_items::StartFnLangItem;
|
||||||
|
@ -74,10 +75,8 @@ use type_of::LayoutLlvmExt;
|
||||||
use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
|
use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
|
||||||
use CrateInfo;
|
use CrateInfo;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_target::spec::TargetTriple;
|
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -1095,7 +1094,6 @@ impl CrateInfo {
|
||||||
used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
|
used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
|
||||||
used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
|
used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
|
||||||
used_crate_source: FxHashMap(),
|
used_crate_source: FxHashMap(),
|
||||||
wasm_custom_sections: BTreeMap::new(),
|
|
||||||
wasm_imports: FxHashMap(),
|
wasm_imports: FxHashMap(),
|
||||||
lang_item_to_crate: FxHashMap(),
|
lang_item_to_crate: FxHashMap(),
|
||||||
missing_lang_items: FxHashMap(),
|
missing_lang_items: FxHashMap(),
|
||||||
|
@ -1105,16 +1103,9 @@ impl CrateInfo {
|
||||||
let load_wasm_items = tcx.sess.crate_types.borrow()
|
let load_wasm_items = tcx.sess.crate_types.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
.any(|c| *c != config::CrateTypeRlib) &&
|
.any(|c| *c != config::CrateTypeRlib) &&
|
||||||
tcx.sess.opts.target_triple == TargetTriple::from_triple("wasm32-unknown-unknown");
|
tcx.sess.opts.target_triple.triple() == "wasm32-unknown-unknown";
|
||||||
|
|
||||||
if load_wasm_items {
|
if load_wasm_items {
|
||||||
info!("attempting to load all wasm sections");
|
|
||||||
for &id in tcx.wasm_custom_sections(LOCAL_CRATE).iter() {
|
|
||||||
let (name, contents) = fetch_wasm_section(tcx, id);
|
|
||||||
info.wasm_custom_sections.entry(name)
|
|
||||||
.or_insert(Vec::new())
|
|
||||||
.extend(contents);
|
|
||||||
}
|
|
||||||
info.load_wasm_imports(tcx, LOCAL_CRATE);
|
info.load_wasm_imports(tcx, LOCAL_CRATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1138,12 +1129,6 @@ impl CrateInfo {
|
||||||
info.is_no_builtins.insert(cnum);
|
info.is_no_builtins.insert(cnum);
|
||||||
}
|
}
|
||||||
if load_wasm_items {
|
if load_wasm_items {
|
||||||
for &id in tcx.wasm_custom_sections(cnum).iter() {
|
|
||||||
let (name, contents) = fetch_wasm_section(tcx, id);
|
|
||||||
info.wasm_custom_sections.entry(name)
|
|
||||||
.or_insert(Vec::new())
|
|
||||||
.extend(contents);
|
|
||||||
}
|
|
||||||
info.load_wasm_imports(tcx, cnum);
|
info.load_wasm_imports(tcx, cnum);
|
||||||
}
|
}
|
||||||
let missing = tcx.missing_lang_items(cnum);
|
let missing = tcx.missing_lang_items(cnum);
|
||||||
|
@ -1380,25 +1365,41 @@ mod temp_stable_hash_impls {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
|
pub fn define_custom_section(cx: &CodegenCx, def_id: DefId) {
|
||||||
use rustc::mir::interpret::GlobalId;
|
use rustc::mir::interpret::GlobalId;
|
||||||
|
|
||||||
info!("loading wasm section {:?}", id);
|
assert!(cx.tcx.sess.opts.target_triple.triple().starts_with("wasm32"));
|
||||||
|
|
||||||
let section = tcx.get_attrs(id)
|
info!("loading wasm section {:?}", def_id);
|
||||||
.iter()
|
|
||||||
.find(|a| a.check_name("wasm_custom_section"))
|
|
||||||
.expect("missing #[wasm_custom_section] attribute")
|
|
||||||
.value_str()
|
|
||||||
.expect("malformed #[wasm_custom_section] attribute");
|
|
||||||
|
|
||||||
let instance = ty::Instance::mono(tcx, id);
|
let section = cx.tcx.codegen_fn_attrs(def_id).wasm_custom_section.unwrap();
|
||||||
|
|
||||||
|
let instance = ty::Instance::mono(cx.tcx, def_id);
|
||||||
let cid = GlobalId {
|
let cid = GlobalId {
|
||||||
instance,
|
instance,
|
||||||
promoted: None
|
promoted: None
|
||||||
};
|
};
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let val = tcx.const_eval(param_env.and(cid)).unwrap();
|
let val = cx.tcx.const_eval(param_env.and(cid)).unwrap();
|
||||||
let alloc = tcx.const_value_to_allocation(val);
|
let alloc = cx.tcx.const_value_to_allocation(val);
|
||||||
(section.to_string(), alloc.bytes.clone())
|
|
||||||
|
unsafe {
|
||||||
|
let section = llvm::LLVMMDStringInContext(
|
||||||
|
cx.llcx,
|
||||||
|
section.as_str().as_ptr() as *const _,
|
||||||
|
section.as_str().len() as c_uint,
|
||||||
|
);
|
||||||
|
let alloc = llvm::LLVMMDStringInContext(
|
||||||
|
cx.llcx,
|
||||||
|
alloc.bytes.as_ptr() as *const _,
|
||||||
|
alloc.bytes.len() as c_uint,
|
||||||
|
);
|
||||||
|
let data = [section, alloc];
|
||||||
|
let meta = llvm::LLVMMDNodeInContext(cx.llcx, data.as_ptr(), 2);
|
||||||
|
llvm::LLVMAddNamedMetadataOperand(
|
||||||
|
cx.llmod,
|
||||||
|
"wasm.custom_sections\0".as_ptr() as *const _,
|
||||||
|
meta,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,6 @@ pub use llvm_util::target_features;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
|
||||||
use rustc::dep_graph::DepGraph;
|
use rustc::dep_graph::DepGraph;
|
||||||
|
@ -94,7 +93,7 @@ mod back {
|
||||||
pub mod symbol_export;
|
pub mod symbol_export;
|
||||||
pub mod write;
|
pub mod write;
|
||||||
mod rpath;
|
mod rpath;
|
||||||
mod wasm;
|
pub mod wasm;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod abi;
|
mod abi;
|
||||||
|
@ -382,7 +381,6 @@ struct CrateInfo {
|
||||||
used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
|
used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
|
||||||
used_crates_static: Vec<(CrateNum, LibSource)>,
|
used_crates_static: Vec<(CrateNum, LibSource)>,
|
||||||
used_crates_dynamic: Vec<(CrateNum, LibSource)>,
|
used_crates_dynamic: Vec<(CrateNum, LibSource)>,
|
||||||
wasm_custom_sections: BTreeMap<String, Vec<u8>>,
|
|
||||||
wasm_imports: FxHashMap<String, String>,
|
wasm_imports: FxHashMap<String, String>,
|
||||||
lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
|
lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
|
||||||
missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
|
missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
|
||||||
|
|
|
@ -66,6 +66,9 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
||||||
span_bug!(item.span, "Mismatch between hir::Item type and MonoItem type")
|
span_bug!(item.span, "Mismatch between hir::Item type and MonoItem type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MonoItem::CustomSection(def_id) => {
|
||||||
|
base::define_custom_section(cx, def_id);
|
||||||
|
}
|
||||||
MonoItem::Fn(instance) => {
|
MonoItem::Fn(instance) => {
|
||||||
base::codegen_instance(&cx, instance);
|
base::codegen_instance(&cx, instance);
|
||||||
}
|
}
|
||||||
|
@ -97,6 +100,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
||||||
MonoItem::Fn(instance) => {
|
MonoItem::Fn(instance) => {
|
||||||
predefine_fn(cx, instance, linkage, visibility, &symbol_name);
|
predefine_fn(cx, instance, linkage, visibility, &symbol_name);
|
||||||
}
|
}
|
||||||
|
MonoItem::CustomSection(..) => {}
|
||||||
MonoItem::GlobalAsm(..) => {}
|
MonoItem::GlobalAsm(..) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +120,9 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
||||||
MonoItem::Static(id) => {
|
MonoItem::Static(id) => {
|
||||||
format!("Static({:?})", id)
|
format!("Static({:?})", id)
|
||||||
}
|
}
|
||||||
|
MonoItem::CustomSection(id) => {
|
||||||
|
format!("CustomSection({:?})", id)
|
||||||
|
}
|
||||||
MonoItem::GlobalAsm(id) => {
|
MonoItem::GlobalAsm(id) => {
|
||||||
format!("GlobalAsm({:?})", id)
|
format!("GlobalAsm({:?})", id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,6 @@ impl CodegenBackend for MetadataOnlyCodegenBackend {
|
||||||
};
|
};
|
||||||
providers.is_reachable_non_generic = |_tcx, _defid| true;
|
providers.is_reachable_non_generic = |_tcx, _defid| true;
|
||||||
providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new());
|
providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new());
|
||||||
providers.wasm_custom_sections = |_tcx, _crate| Lrc::new(Vec::new());
|
|
||||||
}
|
}
|
||||||
fn provide_extern(&self, providers: &mut Providers) {
|
fn provide_extern(&self, providers: &mut Providers) {
|
||||||
providers.is_reachable_non_generic = |_tcx, _defid| true;
|
providers.is_reachable_non_generic = |_tcx, _defid| true;
|
||||||
|
|
|
@ -266,8 +266,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||||
|
|
||||||
Arc::new(cdata.exported_symbols(tcx))
|
Arc::new(cdata.exported_symbols(tcx))
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_custom_sections => { Lrc::new(cdata.wasm_custom_sections()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
|
pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
|
||||||
|
|
|
@ -1011,16 +1011,6 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wasm_custom_sections(&self) -> Vec<DefId> {
|
|
||||||
let sections = self.root
|
|
||||||
.wasm_custom_sections
|
|
||||||
.decode(self)
|
|
||||||
.map(|def_index| self.local_def_id(def_index))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
info!("loaded wasm sections {:?}", sections);
|
|
||||||
return sections
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_macro(&self, id: DefIndex) -> (InternedString, MacroDef) {
|
pub fn get_macro(&self, id: DefIndex) -> (InternedString, MacroDef) {
|
||||||
let entry = self.entry(id);
|
let entry = self.entry(id);
|
||||||
match entry.kind {
|
match entry.kind {
|
||||||
|
|
|
@ -436,12 +436,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
&exported_symbols);
|
&exported_symbols);
|
||||||
let exported_symbols_bytes = self.position() - i;
|
let exported_symbols_bytes = self.position() - i;
|
||||||
|
|
||||||
// encode wasm custom sections
|
|
||||||
let wasm_custom_sections = self.tcx.wasm_custom_sections(LOCAL_CRATE);
|
|
||||||
let wasm_custom_sections = self.tracked(
|
|
||||||
IsolatedEncoder::encode_wasm_custom_sections,
|
|
||||||
&wasm_custom_sections);
|
|
||||||
|
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
||||||
// Encode the items.
|
// Encode the items.
|
||||||
|
@ -527,7 +521,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
def_path_table,
|
def_path_table,
|
||||||
impls,
|
impls,
|
||||||
exported_symbols,
|
exported_symbols,
|
||||||
wasm_custom_sections,
|
|
||||||
interpret_alloc_index,
|
interpret_alloc_index,
|
||||||
index,
|
index,
|
||||||
});
|
});
|
||||||
|
@ -1543,11 +1536,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_wasm_custom_sections(&mut self, statics: &[DefId]) -> LazySeq<DefIndex> {
|
|
||||||
info!("encoding custom wasm section constants {:?}", statics);
|
|
||||||
self.lazy_seq(statics.iter().map(|id| id.index))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
|
fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
|
||||||
match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
|
match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
|
||||||
Some(arr) => {
|
Some(arr) => {
|
||||||
|
|
|
@ -206,7 +206,6 @@ pub struct CrateRoot {
|
||||||
pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
|
pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
|
||||||
pub impls: LazySeq<TraitImpls>,
|
pub impls: LazySeq<TraitImpls>,
|
||||||
pub exported_symbols: EncodedExportedSymbols,
|
pub exported_symbols: EncodedExportedSymbols,
|
||||||
pub wasm_custom_sections: LazySeq<DefIndex>,
|
|
||||||
pub interpret_alloc_index: LazySeq<u32>,
|
pub interpret_alloc_index: LazySeq<u32>,
|
||||||
|
|
||||||
pub index: LazySeq<index::Index>,
|
pub index: LazySeq<index::Index>,
|
||||||
|
|
|
@ -414,6 +414,9 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
MonoItem::GlobalAsm(..) => {
|
MonoItem::GlobalAsm(..) => {
|
||||||
recursion_depth_reset = None;
|
recursion_depth_reset = None;
|
||||||
}
|
}
|
||||||
|
MonoItem::CustomSection(..) => {
|
||||||
|
recursion_depth_reset = None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record_accesses(tcx, starting_point, &neighbors[..], inlining_map);
|
record_accesses(tcx, starting_point, &neighbors[..], inlining_map);
|
||||||
|
@ -990,6 +993,13 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||||
hir::ItemConst(..) => {
|
hir::ItemConst(..) => {
|
||||||
// const items only generate mono items if they are
|
// const items only generate mono items if they are
|
||||||
// actually used somewhere. Just declaring them is insufficient.
|
// actually used somewhere. Just declaring them is insufficient.
|
||||||
|
|
||||||
|
let def_id = self.tcx.hir.local_def_id(item.id);
|
||||||
|
if self.tcx.sess.opts.target_triple.triple().starts_with("wasm32") &&
|
||||||
|
self.tcx.codegen_fn_attrs(def_id).wasm_custom_section.is_some()
|
||||||
|
{
|
||||||
|
self.output.push(MonoItem::CustomSection(def_id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
hir::ItemFn(..) => {
|
hir::ItemFn(..) => {
|
||||||
let def_id = self.tcx.hir.local_def_id(item.id);
|
let def_id = self.tcx.hir.local_def_id(item.id);
|
||||||
|
|
|
@ -63,6 +63,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
||||||
instance.substs.types().next().is_some()
|
instance.substs.types().next().is_some()
|
||||||
}
|
}
|
||||||
MonoItem::Static(..) |
|
MonoItem::Static(..) |
|
||||||
|
MonoItem::CustomSection(..) |
|
||||||
MonoItem::GlobalAsm(..) => false,
|
MonoItem::GlobalAsm(..) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +74,9 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
||||||
MonoItem::Static(def_id) => {
|
MonoItem::Static(def_id) => {
|
||||||
tcx.symbol_name(Instance::mono(tcx, def_id))
|
tcx.symbol_name(Instance::mono(tcx, def_id))
|
||||||
}
|
}
|
||||||
|
MonoItem::CustomSection(def_id) => {
|
||||||
|
tcx.symbol_name(Instance::mono(tcx, def_id))
|
||||||
|
}
|
||||||
MonoItem::GlobalAsm(node_id) => {
|
MonoItem::GlobalAsm(node_id) => {
|
||||||
let def_id = tcx.hir.local_def_id(node_id);
|
let def_id = tcx.hir.local_def_id(node_id);
|
||||||
ty::SymbolName {
|
ty::SymbolName {
|
||||||
|
@ -121,9 +125,8 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MonoItem::Static(..) => {
|
MonoItem::Static(..) |
|
||||||
InstantiationMode::GloballyShared { may_conflict: false }
|
MonoItem::CustomSection(..) |
|
||||||
}
|
|
||||||
MonoItem::GlobalAsm(..) => {
|
MonoItem::GlobalAsm(..) => {
|
||||||
InstantiationMode::GloballyShared { may_conflict: false }
|
InstantiationMode::GloballyShared { may_conflict: false }
|
||||||
}
|
}
|
||||||
|
@ -134,6 +137,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
||||||
let def_id = match *self.as_mono_item() {
|
let def_id = match *self.as_mono_item() {
|
||||||
MonoItem::Fn(ref instance) => instance.def_id(),
|
MonoItem::Fn(ref instance) => instance.def_id(),
|
||||||
MonoItem::Static(def_id) => def_id,
|
MonoItem::Static(def_id) => def_id,
|
||||||
|
MonoItem::CustomSection(..) => return None,
|
||||||
MonoItem::GlobalAsm(..) => return None,
|
MonoItem::GlobalAsm(..) => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -171,6 +175,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
||||||
let (def_id, substs) = match *self.as_mono_item() {
|
let (def_id, substs) = match *self.as_mono_item() {
|
||||||
MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs),
|
MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs),
|
||||||
MonoItem::Static(def_id) => (def_id, Substs::empty()),
|
MonoItem::Static(def_id) => (def_id, Substs::empty()),
|
||||||
|
MonoItem::CustomSection(..) => return true,
|
||||||
// global asm never has predicates
|
// global asm never has predicates
|
||||||
MonoItem::GlobalAsm(..) => return true
|
MonoItem::GlobalAsm(..) => return true
|
||||||
};
|
};
|
||||||
|
@ -187,6 +192,10 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
||||||
let instance = Instance::new(def_id, tcx.intern_substs(&[]));
|
let instance = Instance::new(def_id, tcx.intern_substs(&[]));
|
||||||
to_string_internal(tcx, "static ", instance)
|
to_string_internal(tcx, "static ", instance)
|
||||||
},
|
},
|
||||||
|
MonoItem::CustomSection(def_id) => {
|
||||||
|
let instance = Instance::new(def_id, tcx.intern_substs(&[]));
|
||||||
|
to_string_internal(tcx, "custom-section ", instance)
|
||||||
|
},
|
||||||
MonoItem::GlobalAsm(..) => {
|
MonoItem::GlobalAsm(..) => {
|
||||||
"global_asm".to_string()
|
"global_asm".to_string()
|
||||||
}
|
}
|
||||||
|
@ -212,6 +221,9 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
||||||
MonoItem::Static(def_id) => {
|
MonoItem::Static(def_id) => {
|
||||||
tcx.hir.as_local_node_id(def_id)
|
tcx.hir.as_local_node_id(def_id)
|
||||||
}
|
}
|
||||||
|
MonoItem::CustomSection(def_id) => {
|
||||||
|
tcx.hir.as_local_node_id(def_id)
|
||||||
|
}
|
||||||
MonoItem::GlobalAsm(node_id) => {
|
MonoItem::GlobalAsm(node_id) => {
|
||||||
Some(node_id)
|
Some(node_id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,7 +180,8 @@ pub trait CodegenUnitExt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MonoItem::Static(def_id) => {
|
MonoItem::Static(def_id) |
|
||||||
|
MonoItem::CustomSection(def_id) => {
|
||||||
tcx.hir.as_local_node_id(def_id)
|
tcx.hir.as_local_node_id(def_id)
|
||||||
}
|
}
|
||||||
MonoItem::GlobalAsm(node_id) => {
|
MonoItem::GlobalAsm(node_id) => {
|
||||||
|
@ -449,6 +450,9 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
};
|
};
|
||||||
(Linkage::External, visibility)
|
(Linkage::External, visibility)
|
||||||
}
|
}
|
||||||
|
MonoItem::CustomSection(..) => {
|
||||||
|
(Linkage::External, Visibility::Hidden)
|
||||||
|
}
|
||||||
MonoItem::GlobalAsm(node_id) => {
|
MonoItem::GlobalAsm(node_id) => {
|
||||||
let def_id = tcx.hir.local_def_id(node_id);
|
let def_id = tcx.hir.local_def_id(node_id);
|
||||||
let visibility = if tcx.is_reachable_non_generic(def_id) {
|
let visibility = if tcx.is_reachable_non_generic(def_id) {
|
||||||
|
@ -714,6 +718,7 @@ fn characteristic_def_id_of_mono_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
Some(def_id)
|
Some(def_id)
|
||||||
}
|
}
|
||||||
MonoItem::Static(def_id) => Some(def_id),
|
MonoItem::Static(def_id) => Some(def_id),
|
||||||
|
MonoItem::CustomSection(def_id) => Some(def_id),
|
||||||
MonoItem::GlobalAsm(node_id) => Some(tcx.hir.local_def_id(node_id)),
|
MonoItem::GlobalAsm(node_id) => Some(tcx.hir.local_def_id(node_id)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ pub fn target() -> Result<Target, String> {
|
||||||
.. Default::default()
|
.. Default::default()
|
||||||
};
|
};
|
||||||
Ok(Target {
|
Ok(Target {
|
||||||
llvm_target: "wasm32-unknown-unknown-wasm".to_string(),
|
llvm_target: "wasm32-unknown-unknown".to_string(),
|
||||||
target_endian: "little".to_string(),
|
target_endian: "little".to_string(),
|
||||||
target_pointer_width: "32".to_string(),
|
target_pointer_width: "32".to_string(),
|
||||||
target_c_int_width: "32".to_string(),
|
target_c_int_width: "32".to_string(),
|
||||||
|
|
|
@ -1925,6 +1925,14 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
|
||||||
if let Some(val) = attr.value_str() {
|
if let Some(val) = attr.value_str() {
|
||||||
codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str()));
|
codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str()));
|
||||||
}
|
}
|
||||||
|
} else if attr.check_name("wasm_custom_section") {
|
||||||
|
match attr.value_str() {
|
||||||
|
Some(name) => codegen_fn_attrs.wasm_custom_section = Some(name),
|
||||||
|
None => {
|
||||||
|
tcx.sess.span_err(attr.span, "must be of the form \
|
||||||
|
#[wasm_custom_section = \"foo\"]");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use clean::*;
|
use clean::*;
|
||||||
|
|
||||||
pub enum FoldItem {
|
pub enum FoldItem {
|
||||||
|
@ -109,12 +111,13 @@ pub trait DocFolder : Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_crate(&mut self, mut c: Crate) -> Crate {
|
fn fold_crate(&mut self, mut c: Crate) -> Crate {
|
||||||
c.module = c.module.and_then(|module| self.fold_item(module));
|
c.module = c.module.take().and_then(|module| self.fold_item(module));
|
||||||
|
|
||||||
c.external_traits = c.external_traits.into_iter().map(|(k, mut v)| {
|
let traits = mem::replace(&mut c.external_traits, Default::default());
|
||||||
|
c.external_traits.extend(traits.into_iter().map(|(k, mut v)| {
|
||||||
v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
|
v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
|
||||||
(k, v)
|
(k, v)
|
||||||
}).collect();
|
}));
|
||||||
c
|
c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
src/llvm
2
src/llvm
|
@ -1 +1 @@
|
||||||
Subproject commit 509f29ac17874394acf4d49d6bae3cd93c652aa1
|
Subproject commit 03684905101f0b7e49dfe530e54dc1aeac6ef0fb
|
|
@ -545,7 +545,11 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
|
||||||
return LLVMRustResult::Failure;
|
return LLVMRustResult::Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LLVM_VERSION_GE(7, 0)
|
||||||
|
unwrap(Target)->addPassesToEmitFile(*PM, OS, nullptr, FileType, false);
|
||||||
|
#else
|
||||||
unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
|
unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
|
||||||
|
#endif
|
||||||
PM->run(*unwrap(M));
|
PM->run(*unwrap(M));
|
||||||
|
|
||||||
// Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
|
// Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
// compile-flags: -C no-prepopulate-passes
|
// compile-flags: -C no-prepopulate-passes
|
||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
|
// min-llvm-version 7.0
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ pub enum Enum64 {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn align64(i : i32) -> Align64 {
|
pub fn align64(i : i32) -> Align64 {
|
||||||
// CHECK: %a64 = alloca %Align64, align 64
|
// CHECK: %a64 = alloca %Align64, align 64
|
||||||
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 64, i32 64, i1 false)
|
// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 64 %{{.*}}, i8* align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
|
||||||
let a64 = Align64(i);
|
let a64 = Align64(i);
|
||||||
a64
|
a64
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
// compile-flags: -C no-prepopulate-passes
|
// compile-flags: -C no-prepopulate-passes
|
||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
|
// min-llvm-version 7.0
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ pub fn inline_enum_const() -> E<i8, i16> {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn low_align_const() -> E<i16, [i16; 3]> {
|
pub fn low_align_const() -> E<i16, [i16; 3]> {
|
||||||
// Check that low_align_const and high_align_const use the same constant
|
// Check that low_align_const and high_align_const use the same constant
|
||||||
// CHECK: i8* getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
|
// CHECK: i8* align 2 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
|
||||||
*&E::A(0)
|
*&E::A(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +63,6 @@ pub fn low_align_const() -> E<i16, [i16; 3]> {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn high_align_const() -> E<i16, i32> {
|
pub fn high_align_const() -> E<i16, i32> {
|
||||||
// Check that low_align_const and high_align_const use the same constant
|
// Check that low_align_const and high_align_const use the same constant
|
||||||
// CHECK: i8* getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
|
// CHECK: i8* align 4 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
|
||||||
*&E::A(0)
|
*&E::A(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// ignore-tidy-linelength
|
||||||
// compile-flags: -C no-prepopulate-passes
|
// compile-flags: -C no-prepopulate-passes
|
||||||
|
// min-llvm-version 7.0
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(repr_packed)]
|
#![feature(repr_packed)]
|
||||||
|
@ -63,7 +65,7 @@ pub struct BigPacked2 {
|
||||||
pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
|
pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
|
||||||
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
|
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
|
||||||
// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
|
// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
|
||||||
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 1, i1 false)
|
// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 %{{.*}}, i8* align 1 %{{.*}}, i{{[0-9]+}} 32, i1 false)
|
||||||
// check that calls whose destination is a field of a packed struct
|
// check that calls whose destination is a field of a packed struct
|
||||||
// go through an alloca rather than calling the function with an
|
// go through an alloca rather than calling the function with an
|
||||||
// unaligned destination.
|
// unaligned destination.
|
||||||
|
@ -75,7 +77,7 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
|
||||||
pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
|
pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
|
||||||
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
|
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
|
||||||
// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
|
// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
|
||||||
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 2, i1 false)
|
// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 2 %{{.*}}, i8* align 2 %{{.*}}, i{{[0-9]+}} 32, i1 false)
|
||||||
// check that calls whose destination is a field of a packed struct
|
// check that calls whose destination is a field of a packed struct
|
||||||
// go through an alloca rather than calling the function with an
|
// go through an alloca rather than calling the function with an
|
||||||
// unaligned destination.
|
// unaligned destination.
|
||||||
|
@ -93,14 +95,14 @@ pub struct Packed2Pair(u8, u32);
|
||||||
// CHECK-LABEL: @pkd1_pair
|
// CHECK-LABEL: @pkd1_pair
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn pkd1_pair(pair1: &mut Packed1Pair, pair2: &mut Packed1Pair) {
|
pub fn pkd1_pair(pair1: &mut Packed1Pair, pair2: &mut Packed1Pair) {
|
||||||
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 5, i32 1, i1 false)
|
// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 %{{.*}}, i8* align 1 %{{.*}}, i{{[0-9]+}} 5, i1 false)
|
||||||
*pair2 = *pair1;
|
*pair2 = *pair1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @pkd2_pair
|
// CHECK-LABEL: @pkd2_pair
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn pkd2_pair(pair1: &mut Packed2Pair, pair2: &mut Packed2Pair) {
|
pub fn pkd2_pair(pair1: &mut Packed2Pair, pair2: &mut Packed2Pair) {
|
||||||
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 6, i32 2, i1 false)
|
// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 2 %{{.*}}, i8* align 2 %{{.*}}, i{{[0-9]+}} 6, i1 false)
|
||||||
*pair2 = *pair1;
|
*pair2 = *pair1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,14 +117,14 @@ pub struct Packed2NestedPair((u32, u32));
|
||||||
// CHECK-LABEL: @pkd1_nested_pair
|
// CHECK-LABEL: @pkd1_nested_pair
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn pkd1_nested_pair(pair1: &mut Packed1NestedPair, pair2: &mut Packed1NestedPair) {
|
pub fn pkd1_nested_pair(pair1: &mut Packed1NestedPair, pair2: &mut Packed1NestedPair) {
|
||||||
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 8, i32 1, i1 false)
|
// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 %{{.*}}, i8* align 1 %{{.*}}, i{{[0-9]+}} 8, i1 false)
|
||||||
*pair2 = *pair1;
|
*pair2 = *pair1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @pkd2_nested_pair
|
// CHECK-LABEL: @pkd2_nested_pair
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn pkd2_nested_pair(pair1: &mut Packed2NestedPair, pair2: &mut Packed2NestedPair) {
|
pub fn pkd2_nested_pair(pair1: &mut Packed2NestedPair, pair2: &mut Packed2NestedPair) {
|
||||||
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 8, i32 2, i1 false)
|
// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 2 %{{.*}}, i8* align 2 %{{.*}}, i{{[0-9]+}} 8, i1 false)
|
||||||
*pair2 = *pair1;
|
*pair2 = *pair1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
// compile-flags: -O
|
// compile-flags: -O
|
||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
|
// min-llvm-version 7.0
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
@ -23,6 +24,6 @@ pub fn helper(_: usize) {
|
||||||
// CHECK-LABEL: @repeat_take_collect
|
// CHECK-LABEL: @repeat_take_collect
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn repeat_take_collect() -> Vec<u8> {
|
pub fn repeat_take_collect() -> Vec<u8> {
|
||||||
// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}%{{[0-9]+}}, i8 42, [[USIZE]] 100000, i32 1, i1 false)
|
// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false)
|
||||||
iter::repeat(42).take(100000).collect()
|
iter::repeat(42).take(100000).collect()
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// ignore-emscripten
|
// ignore-emscripten
|
||||||
// min-llvm-version 6.0
|
// min-llvm-version 7.0
|
||||||
|
|
||||||
// compile-flags: -C no-prepopulate-passes
|
// compile-flags: -C no-prepopulate-passes
|
||||||
|
|
||||||
|
@ -34,10 +34,9 @@ pub unsafe fn fmin(a: f32x4, b: f32x4) -> f32x4 {
|
||||||
simd_fmin(a, b)
|
simd_fmin(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(49261)
|
// CHECK-LABEL: @fmax
|
||||||
// // C_HECK-LABEL: @fmax
|
#[no_mangle]
|
||||||
// #[no_mangle]
|
pub unsafe fn fmax(a: f32x4, b: f32x4) -> f32x4 {
|
||||||
// pub unsafe fn fmax(a: f32x4, b: f32x4) -> f32x4 {
|
// CHECK: call <4 x float> @llvm.maxnum.v4f32
|
||||||
// // C_HECK: call <4 x float> @llvm.maxnum.v4f32
|
simd_fmax(a, b)
|
||||||
// simd_fmax(a, b)
|
}
|
||||||
// }
|
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// compile-flags: -C no-prepopulate-passes
|
// compile-flags: -C no-prepopulate-passes
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
// min-llvm-version 7.0
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
@ -29,7 +31,7 @@ pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) {
|
||||||
// CHECK: store i32 %0, i32* [[TMP]]
|
// CHECK: store i32 %0, i32* [[TMP]]
|
||||||
// CHECK: [[Y8:%[0-9]+]] = bitcast [4 x i8]* %y to i8*
|
// CHECK: [[Y8:%[0-9]+]] = bitcast [4 x i8]* %y to i8*
|
||||||
// CHECK: [[TMP8:%[0-9]+]] = bitcast i32* [[TMP]] to i8*
|
// CHECK: [[TMP8:%[0-9]+]] = bitcast i32* [[TMP]] to i8*
|
||||||
// CHECK: call void @llvm.memcpy.{{.*}}(i8* [[Y8]], i8* [[TMP8]], i{{[0-9]+}} 4, i32 1, i1 false)
|
// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 1 [[TMP8]], i{{[0-9]+}} 4, i1 false)
|
||||||
*x = y;
|
*x = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +45,6 @@ pub fn small_struct_alignment(x: &mut Bytes, y: Bytes) {
|
||||||
// CHECK: store i32 %0, i32* [[TMP]]
|
// CHECK: store i32 %0, i32* [[TMP]]
|
||||||
// CHECK: [[Y8:%[0-9]+]] = bitcast %Bytes* %y to i8*
|
// CHECK: [[Y8:%[0-9]+]] = bitcast %Bytes* %y to i8*
|
||||||
// CHECK: [[TMP8:%[0-9]+]] = bitcast i32* [[TMP]] to i8*
|
// CHECK: [[TMP8:%[0-9]+]] = bitcast i32* [[TMP]] to i8*
|
||||||
// CHECK: call void @llvm.memcpy.{{.*}}(i8* [[Y8]], i8* [[TMP8]], i{{[0-9]+}} 4, i32 1, i1 false)
|
// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 1 [[TMP8]], i{{[0-9]+}} 4, i1 false)
|
||||||
*x = y;
|
*x = y;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
all:
|
all:
|
||||||
ifeq ($(PROFILER_SUPPORT),1)
|
ifeq ($(PROFILER_SUPPORT),1)
|
||||||
|
ifndef IS_WINDOWS
|
||||||
$(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs
|
$(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs
|
||||||
$(call RUN,test) || exit 1
|
$(call RUN,test) || exit 1
|
||||||
[ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1)
|
[ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1)
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
all:
|
all:
|
||||||
ifeq ($(PROFILER_SUPPORT),1)
|
ifeq ($(PROFILER_SUPPORT),1)
|
||||||
|
ifndef IS_WINDOWS
|
||||||
$(RUSTC) -g -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs
|
$(RUSTC) -g -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs
|
||||||
$(call RUN,test) || exit 1
|
$(call RUN,test) || exit 1
|
||||||
[ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1)
|
[ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1)
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
|
@ -41,6 +41,24 @@ extern "platform-intrinsic" {
|
||||||
fn simd_fpowi<T>(x: T, y: i32) -> T;
|
fn simd_fpowi<T>(x: T, y: i32) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! assert_approx_eq_f32 {
|
||||||
|
($a:expr, $b:expr) => ({
|
||||||
|
let (a, b) = (&$a, &$b);
|
||||||
|
assert!((*a - *b).abs() < 1.0e-6,
|
||||||
|
"{} is not approximately equal to {}", *a, *b);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
macro_rules! assert_approx_eq {
|
||||||
|
($a:expr, $b:expr) => ({
|
||||||
|
let a = $a;
|
||||||
|
let b = $b;
|
||||||
|
assert_approx_eq_f32!(a.0, b.0);
|
||||||
|
assert_approx_eq_f32!(a.1, b.1);
|
||||||
|
assert_approx_eq_f32!(a.2, b.2);
|
||||||
|
assert_approx_eq_f32!(a.3, b.3);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = f32x4(1.0, 1.0, 1.0, 1.0);
|
let x = f32x4(1.0, 1.0, 1.0, 1.0);
|
||||||
let y = f32x4(-1.0, -1.0, -1.0, -1.0);
|
let y = f32x4(-1.0, -1.0, -1.0, -1.0);
|
||||||
|
@ -50,45 +68,45 @@ fn main() {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let r = simd_fabs(y);
|
let r = simd_fabs(y);
|
||||||
assert_eq!(x, r);
|
assert_approx_eq!(x, r);
|
||||||
|
|
||||||
let r = simd_fcos(z);
|
let r = simd_fcos(z);
|
||||||
assert_eq!(x, r);
|
assert_approx_eq!(x, r);
|
||||||
|
|
||||||
let r = simd_ceil(h);
|
let r = simd_ceil(h);
|
||||||
assert_eq!(x, r);
|
assert_approx_eq!(x, r);
|
||||||
|
|
||||||
let r = simd_fexp(z);
|
let r = simd_fexp(z);
|
||||||
assert_eq!(x, r);
|
assert_approx_eq!(x, r);
|
||||||
|
|
||||||
let r = simd_fexp2(z);
|
let r = simd_fexp2(z);
|
||||||
assert_eq!(x, r);
|
assert_approx_eq!(x, r);
|
||||||
|
|
||||||
let r = simd_floor(h);
|
let r = simd_floor(h);
|
||||||
assert_eq!(z, r);
|
assert_approx_eq!(z, r);
|
||||||
|
|
||||||
let r = simd_fma(x, h, h);
|
let r = simd_fma(x, h, h);
|
||||||
assert_eq!(x, r);
|
assert_approx_eq!(x, r);
|
||||||
|
|
||||||
let r = simd_fsqrt(x);
|
let r = simd_fsqrt(x);
|
||||||
assert_eq!(x, r);
|
assert_approx_eq!(x, r);
|
||||||
|
|
||||||
let r = simd_flog(x);
|
let r = simd_flog(x);
|
||||||
assert_eq!(z, r);
|
assert_approx_eq!(z, r);
|
||||||
|
|
||||||
let r = simd_flog2(x);
|
let r = simd_flog2(x);
|
||||||
assert_eq!(z, r);
|
assert_approx_eq!(z, r);
|
||||||
|
|
||||||
let r = simd_flog10(x);
|
let r = simd_flog10(x);
|
||||||
assert_eq!(z, r);
|
assert_approx_eq!(z, r);
|
||||||
|
|
||||||
let r = simd_fpow(h, x);
|
let r = simd_fpow(h, x);
|
||||||
assert_eq!(h, r);
|
assert_approx_eq!(h, r);
|
||||||
|
|
||||||
let r = simd_fpowi(h, 1);
|
let r = simd_fpowi(h, 1);
|
||||||
assert_eq!(h, r);
|
assert_approx_eq!(h, r);
|
||||||
|
|
||||||
let r = simd_fsin(z);
|
let r = simd_fsin(z);
|
||||||
assert_eq!(z, r);
|
assert_approx_eq!(z, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit b87873eaceb75cf9342d5273f01ba2c020f61ca8
|
Subproject commit 8214ccf861d538671b0a1436dbf4538dc4a64d09
|
Loading…
Reference in New Issue