Move linkage type check to HIR analysis and fix semantics issues.
This ensures that the error is printed even for unused variables, as well as unifying the handling between the LLVM and GCC backends. This also fixes unusual behavior around exported Rust-defined variables with linkage attributes. With the previous behavior, it appears to be impossible to define such a variable such that it can actually be imported and used by another crate. This is because on the importing side, the variable is required to be a pointer, but on the exporting side, the type checker rejects static variables of pointer type because they do not implement `Sync`. Even if it were possible to import such a type, it appears that code generation on the importing side would add an unexpected additional level of pointer indirection, which would break type safety. This highlighted that the semantics of linkage on Rust-defined variables is different to linkage on foreign items. As such, we now model the difference with two different codegen attributes: linkage for Rust-defined variables, and import_linkage for foreign items. This change gives semantics to the test src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs which was previously expected to fail to compile. Therefore, convert it into a test that is expected to successfully compile. The update to the GCC backend is speculative and untested.
This commit is contained in:
parent
e1d819583f
commit
5873ebeef3
19 changed files with 56 additions and 85 deletions
|
@ -1,7 +1,7 @@
|
|||
use crate::base;
|
||||
use crate::common::{self, CodegenCx};
|
||||
use crate::debuginfo;
|
||||
use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined};
|
||||
use crate::errors::{InvalidMinimumAlignment, SymbolAlreadyDefined};
|
||||
use crate::llvm::{self, True};
|
||||
use crate::llvm_util;
|
||||
use crate::type_::Type;
|
||||
|
@ -162,22 +162,12 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
|||
def_id: DefId,
|
||||
) -> &'ll Value {
|
||||
let llty = cx.layout_of(ty).llvm_type(cx);
|
||||
if let Some(linkage) = attrs.linkage {
|
||||
if let Some(linkage) = attrs.import_linkage {
|
||||
debug!("get_static: sym={} linkage={:?}", sym, linkage);
|
||||
|
||||
// If this is a static with a linkage specified, then we need to handle
|
||||
// it a little specially. The typesystem prevents things like &T and
|
||||
// extern "C" fn() from being non-null, so we can't just declare a
|
||||
// static and call it a day. Some linkages (like weak) will make it such
|
||||
// that the static actually has a null value.
|
||||
let llty2 = if let ty::RawPtr(ref mt) = ty.kind() {
|
||||
cx.layout_of(mt.ty).llvm_type(cx)
|
||||
} else {
|
||||
cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) })
|
||||
};
|
||||
unsafe {
|
||||
// Declare a symbol `foo` with the desired linkage.
|
||||
let g1 = cx.declare_global(sym, llty2);
|
||||
let g1 = cx.declare_global(sym, cx.type_i8());
|
||||
llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage));
|
||||
|
||||
// Declare an internal global `extern_with_linkage_foo` which
|
||||
|
@ -195,7 +185,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
|||
})
|
||||
});
|
||||
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
|
||||
llvm::LLVMSetInitializer(g2, g1);
|
||||
llvm::LLVMSetInitializer(g2, cx.const_ptrcast(g1, llty));
|
||||
g2
|
||||
}
|
||||
} else if cx.tcx.sess.target.arch == "x86" &&
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue