a2cc5d68a7
This commit adds a new option to target specifictions to specify that symbols should be "hidden" visibility by default in LLVM. While there are no existing targets that take advantage of this the `wasm32-unknown-unknown` target will soon start to use this visibility. The LLD linker currently interprets `hidden` as "don't export this from the wasm module" which is what we want for 90% of our functions. While the LLD linker does have a "export this symbol" argument which is what we use for other linkers, it was also somewhat easier to do this change instead which'll involve less arguments flying around. Additionally there's no need for non-`hidden` visibility for most of our symbols! This change should not immediately impact the wasm targets as-is, but rather this is laying the foundations for soon integrating LLD as a linker for wasm code.
122 lines
4.8 KiB
Rust
122 lines
4.8 KiB
Rust
// Copyright 2017 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.
|
|
|
|
use std::ffi::CString;
|
|
use std::ptr;
|
|
|
|
use libc::c_uint;
|
|
use rustc::middle::allocator::AllocatorKind;
|
|
use rustc::ty::TyCtxt;
|
|
use rustc_allocator::{ALLOCATOR_METHODS, AllocatorTy};
|
|
|
|
use ModuleLlvm;
|
|
use llvm::{self, False, True};
|
|
|
|
pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
|
|
let llcx = mods.llcx;
|
|
let llmod = mods.llmod;
|
|
let usize = match &tcx.sess.target.target.target_pointer_width[..] {
|
|
"16" => llvm::LLVMInt16TypeInContext(llcx),
|
|
"32" => llvm::LLVMInt32TypeInContext(llcx),
|
|
"64" => llvm::LLVMInt64TypeInContext(llcx),
|
|
tws => bug!("Unsupported target word size for int: {}", tws),
|
|
};
|
|
let i8 = llvm::LLVMInt8TypeInContext(llcx);
|
|
let i8p = llvm::LLVMPointerType(i8, 0);
|
|
let usizep = llvm::LLVMPointerType(usize, 0);
|
|
let void = llvm::LLVMVoidTypeInContext(llcx);
|
|
|
|
for method in ALLOCATOR_METHODS {
|
|
let mut args = Vec::new();
|
|
for ty in method.inputs.iter() {
|
|
match *ty {
|
|
AllocatorTy::Layout => {
|
|
args.push(usize); // size
|
|
args.push(usize); // align
|
|
}
|
|
AllocatorTy::LayoutRef => args.push(i8p),
|
|
AllocatorTy::Ptr => args.push(i8p),
|
|
AllocatorTy::AllocErr => args.push(i8p),
|
|
|
|
AllocatorTy::Bang |
|
|
AllocatorTy::ResultExcess |
|
|
AllocatorTy::ResultPtr |
|
|
AllocatorTy::ResultUnit |
|
|
AllocatorTy::UsizePair |
|
|
AllocatorTy::Unit => panic!("invalid allocator arg"),
|
|
}
|
|
}
|
|
let output = match method.output {
|
|
AllocatorTy::UsizePair => {
|
|
args.push(usizep); // min
|
|
args.push(usizep); // max
|
|
None
|
|
}
|
|
AllocatorTy::Bang => None,
|
|
AllocatorTy::ResultExcess => {
|
|
args.push(i8p); // excess_ptr
|
|
args.push(i8p); // err_ptr
|
|
Some(i8p)
|
|
}
|
|
AllocatorTy::ResultPtr => {
|
|
args.push(i8p); // err_ptr
|
|
Some(i8p)
|
|
}
|
|
AllocatorTy::ResultUnit => Some(i8),
|
|
AllocatorTy::Unit => None,
|
|
|
|
AllocatorTy::AllocErr |
|
|
AllocatorTy::Layout |
|
|
AllocatorTy::LayoutRef |
|
|
AllocatorTy::Ptr => panic!("invalid allocator output"),
|
|
};
|
|
let ty = llvm::LLVMFunctionType(output.unwrap_or(void),
|
|
args.as_ptr(),
|
|
args.len() as c_uint,
|
|
False);
|
|
let name = CString::new(format!("__rust_{}", method.name)).unwrap();
|
|
let llfn = llvm::LLVMRustGetOrInsertFunction(llmod,
|
|
name.as_ptr(),
|
|
ty);
|
|
|
|
if tcx.sess.target.target.options.default_hidden_visibility {
|
|
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
|
|
}
|
|
|
|
let callee = CString::new(kind.fn_name(method.name)).unwrap();
|
|
let callee = llvm::LLVMRustGetOrInsertFunction(llmod,
|
|
callee.as_ptr(),
|
|
ty);
|
|
|
|
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx,
|
|
llfn,
|
|
"entry\0".as_ptr() as *const _);
|
|
|
|
let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
|
|
llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
|
|
let args = args.iter().enumerate().map(|(i, _)| {
|
|
llvm::LLVMGetParam(llfn, i as c_uint)
|
|
}).collect::<Vec<_>>();
|
|
let ret = llvm::LLVMRustBuildCall(llbuilder,
|
|
callee,
|
|
args.as_ptr(),
|
|
args.len() as c_uint,
|
|
ptr::null_mut(),
|
|
"\0".as_ptr() as *const _);
|
|
llvm::LLVMSetTailCall(ret, True);
|
|
if output.is_some() {
|
|
llvm::LLVMBuildRet(llbuilder, ret);
|
|
} else {
|
|
llvm::LLVMBuildRetVoid(llbuilder);
|
|
}
|
|
llvm::LLVMDisposeBuilder(llbuilder);
|
|
}
|
|
}
|