From 6ed5db8d351038622b180be917ef2e2e3f0727b2 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Wed, 13 Jul 2016 00:42:20 +0200 Subject: [LLVM-3.9] Specify that we are using the legacy interface LLVM pass manager infrastructure is currently getting rewritten to be more flexible, but the rewrite isn't complete yet. --- src/rustllvm/PassWrapper.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/rustllvm/PassWrapper.cpp') diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 3564f338a02..95ad686161f 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -267,7 +267,7 @@ LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB, // similar code in clang's BackendUtil.cpp file. extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { - FunctionPassManager *P = unwrap(PM); + llvm::legacy::FunctionPassManager *P = unwrap(PM); P->doInitialization(); for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E; ++I) @@ -294,7 +294,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMModuleRef M, const char *path, TargetMachine::CodeGenFileType FileType) { - PassManager *PM = unwrap(PMR); + llvm::legacy::PassManager *PM = unwrap(PMR); std::string ErrorInfo; std::error_code EC; @@ -320,7 +320,7 @@ extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M, const char* path) { - PassManager *PM = unwrap(PMR); + llvm::legacy::PassManager *PM = unwrap(PMR); std::string ErrorInfo; std::error_code EC; -- cgit 1.4.1-3-g733a5 From 5b44e10fb7e9d1226af11df26ee5fa78b8d54cc3 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Wed, 13 Jul 2016 00:42:44 +0200 Subject: [LLVM-3.9] Preserve certain functions when internalizing This makes sure to still use the old way for older LLVM versions. --- src/rustllvm/PassWrapper.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/rustllvm/PassWrapper.cpp') diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 95ad686161f..64edc79a86a 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -358,9 +358,24 @@ LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMB, bool AddLifetimes) { extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **symbols, size_t len) { - PassManager passes; + llvm::legacy::PassManager passes; + +#if LLVM_VERSION_MINOR <= 8 ArrayRef ref(symbols, len); passes.add(llvm::createInternalizePass(ref)); +#else + auto PreserveFunctions = [=](const GlobalValue &GV) { + for (size_t i=0; i Date: Wed, 13 Jul 2016 00:41:40 +0200 Subject: [LLVM-3.9] Configure PIE at the module level instead of compilation unit level This was deleted here[1] which appears to be replaced by this[2] which is a new setPIELevel function on the LLVM module itself. [1]: http://reviews.llvm.org/D19753 [2]: http://reviews.llvm.org/D19671 --- src/librustc_llvm/lib.rs | 1 + src/librustc_trans/context.rs | 1 + src/rustllvm/PassWrapper.cpp | 10 ++++++++++ 3 files changed, 12 insertions(+) (limited to 'src/rustllvm/PassWrapper.cpp') diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index f14df2a7b48..4fc866752eb 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -2155,6 +2155,7 @@ extern { pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char); pub fn LLVMRustUnsetComdat(V: ValueRef); + pub fn LLVMRustSetModulePIELevel(M: ModuleRef); } // LLVM requires symbols from this library, but apparently they're not printed diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index aa60110fab3..2437fa954d1 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -352,6 +352,7 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR let llvm_target = sess.target.target.llvm_target.as_bytes(); let llvm_target = CString::new(llvm_target).unwrap(); llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); + llvm::LLVMRustSetModulePIELevel(llmod); (llcx, llmod) } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 64edc79a86a..edf83bf80d6 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -188,7 +188,10 @@ LLVMRustCreateTargetMachine(const char *triple, } TargetOptions Options; +#if LLVM_VERSION_MINOR <= 8 Options.PositionIndependentExecutable = PositionIndependentExecutable; +#endif + Options.FloatABIType = FloatABI::Default; if (UseSoftFloat) { Options.FloatABIType = FloatABI::Soft; @@ -411,3 +414,10 @@ extern "C" LLVMTargetDataRef LLVMRustGetModuleDataLayout(LLVMModuleRef M) { return wrap(&unwrap(M)->getDataLayout()); } + +extern "C" void +LLVMRustSetModulePIELevel(LLVMModuleRef M) { +#if LLVM_VERSION_MINOR >= 9 + unwrap(M)->setPIELevel(PIELevel::Level::Default); +#endif +} -- cgit 1.4.1-3-g733a5 From deafab19be13e8cd33e55b211ba8835488747a05 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Thu, 14 Jul 2016 21:26:09 +0200 Subject: [LLVM-3.9] Increase PIELevel Previously, we had a PositionIndependentExecutable, now we simply choose the highest level. This should be equivalent. :cake: --- src/rustllvm/PassWrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rustllvm/PassWrapper.cpp') diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index edf83bf80d6..d4ef4e807f5 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -418,6 +418,6 @@ LLVMRustGetModuleDataLayout(LLVMModuleRef M) { extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) { #if LLVM_VERSION_MINOR >= 9 - unwrap(M)->setPIELevel(PIELevel::Level::Default); + unwrap(M)->setPIELevel(PIELevel::Level::Large); #endif } -- cgit 1.4.1-3-g733a5 From 2c16e24643976523e6858fd41a1ded0429a96ef1 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Sun, 24 Jul 2016 22:31:16 +0200 Subject: Use C type when passing value to LLVM pass Previously the C type LLVMRelocMode (available as RelocMode in Rust) was passed as is to the function. However createTargetMachine expects a Reloc::Model, which is an enum just one value short. Additionally, the function was marked as requiring Reloc::Model in the C code, but RelocMode on the Rust-side. We now use the correct C type LLVMRelocMode and convert it to an Optional as expected by the createTargetMachine call the same the original LLVMCreateTargetMachine function does. See https://github.com/llvm-mirror/llvm/blob/c9b262bfbd5b9fb6f10749dba1465569f39bd625/lib/Target/TargetMachineC.cpp#L104-L121 This was found by @eddyb. --- src/rustllvm/PassWrapper.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'src/rustllvm/PassWrapper.cpp') diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index d4ef4e807f5..a1276060271 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -167,12 +167,35 @@ LLVMRustCreateTargetMachine(const char *triple, const char *cpu, const char *feature, CodeModel::Model CM, - Reloc::Model RM, + LLVMRelocMode Reloc, CodeGenOpt::Level OptLevel, bool UseSoftFloat, bool PositionIndependentExecutable, bool FunctionSections, bool DataSections) { + +#if LLVM_VERSION_MINOR <= 8 + Reloc::Model RM; +#else + Optional RM; +#endif + switch (Reloc){ + case LLVMRelocStatic: + RM = Reloc::Static; + break; + case LLVMRelocPIC: + RM = Reloc::PIC_; + break; + case LLVMRelocDynamicNoPic: + RM = Reloc::DynamicNoPIC; + break; + default: +#if LLVM_VERSION_MINOR <= 8 + RM = Reloc::Default; +#endif + break; + } + std::string Error; Triple Trip(Triple::normalize(triple)); const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(), -- cgit 1.4.1-3-g733a5 From 696691e3c4f2b3aa02fbd1cc76dc2f7e8a401db8 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 2 Aug 2016 00:16:16 +0300 Subject: audit LLVM C++ types in ArchiveWrapper and PassWrapper --- src/librustc_llvm/lib.rs | 76 ++++++++++++-------- src/librustc_trans/back/archive.rs | 2 +- src/librustc_trans/back/write.rs | 46 +++++++------ src/librustc_trans/context.rs | 10 +-- src/rustllvm/ArchiveWrapper.cpp | 98 +++++++++++++++++--------- src/rustllvm/PassWrapper.cpp | 138 ++++++++++++++++++++++++++++++------- src/rustllvm/README | 14 ++++ src/rustllvm/rustllvm.h | 5 ++ 8 files changed, 275 insertions(+), 114 deletions(-) (limited to 'src/rustllvm/PassWrapper.cpp') diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index de82778bc5e..4019732221f 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -40,13 +40,9 @@ pub use self::TypeKind::*; pub use self::AtomicBinOp::*; pub use self::AtomicOrdering::*; pub use self::SynchronizationScope::*; -pub use self::FileType::*; pub use self::MetadataType::*; pub use self::AsmDialect::*; -pub use self::CodeGenOptLevel::*; pub use self::CodeGenOptSize::*; -pub use self::RelocMode::*; -pub use self::CodeGenModel::*; pub use self::DiagnosticKind::*; pub use self::CallConv::*; pub use self::Visibility::*; @@ -75,9 +71,26 @@ pub type Bool = c_uint; pub const True: Bool = 1 as Bool; pub const False: Bool = 0 as Bool; +#[repr(C)] +#[derive(Copy, Clone, PartialEq)] +pub enum LLVMRustResult { + Success = 0, + Failure = 1 +} + +impl LLVMRustResult { + pub fn into_result(self) -> Result<(), ()> { + match self { + LLVMRustResult::Success => Ok(()), + LLVMRustResult::Failure => Err(()), + } + } +} + // Consts for the LLVM CallConv type, pre-cast to usize. #[derive(Copy, Clone, PartialEq)] +#[repr(C)] pub enum CallConv { CCallConv = 0, FastCallConv = 8, @@ -89,6 +102,7 @@ pub enum CallConv { } #[derive(Copy, Clone)] +#[repr(C)] pub enum Visibility { LLVMDefaultVisibility = 0, HiddenVisibility = 1, @@ -100,6 +114,7 @@ pub enum Visibility { // LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either; // they've been removed in upstream LLVM commit r203866. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[repr(C)] pub enum Linkage { ExternalLinkage = 0, AvailableExternallyLinkage = 1, @@ -337,12 +352,12 @@ pub enum SynchronizationScope { CrossThread = 1 } -// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h) #[repr(C)] #[derive(Copy, Clone)] pub enum FileType { - AssemblyFileType = 0, - ObjectFileType = 1 + Other, + AssemblyFile, + ObjectFile, } #[derive(Copy, Clone)] @@ -371,10 +386,11 @@ pub enum AsmDialect { #[derive(Copy, Clone, PartialEq)] #[repr(C)] pub enum CodeGenOptLevel { - CodeGenLevelNone = 0, - CodeGenLevelLess = 1, - CodeGenLevelDefault = 2, - CodeGenLevelAggressive = 3, + Other, + None, + Less, + Default, + Aggressive, } #[derive(Copy, Clone, PartialEq)] @@ -388,21 +404,22 @@ pub enum CodeGenOptSize { #[derive(Copy, Clone, PartialEq)] #[repr(C)] pub enum RelocMode { - RelocDefault = 0, - RelocStatic = 1, - RelocPIC = 2, - RelocDynamicNoPic = 3, + Default = 0, + Static = 1, + PIC = 2, + DynamicNoPic = 3, } #[repr(C)] #[derive(Copy, Clone)] -pub enum CodeGenModel { - CodeModelDefault = 0, - CodeModelJITDefault = 1, - CodeModelSmall = 2, - CodeModelKernel = 3, - CodeModelMedium = 4, - CodeModelLarge = 5, +pub enum CodeModel { + Other, + Default, + JITDefault, + Small, + Kernel, + Medium, + Large, } #[repr(C)] @@ -421,6 +438,7 @@ pub enum DiagnosticKind { #[repr(C)] #[derive(Copy, Clone)] pub enum ArchiveKind { + Other, K_GNU, K_MIPS64, K_BSD, @@ -444,10 +462,10 @@ impl FromStr for ArchiveKind { /// Represents the different LLVM passes Rust supports #[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] -pub enum SupportedPassKind { +pub enum PassKind { + Other, Function, Module, - Unsupported, } // Opaque pointer types @@ -2021,7 +2039,7 @@ extern { pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef; pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef; - pub fn LLVMRustPassKind(Pass: PassRef) -> SupportedPassKind; + pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind; pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef; pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef); @@ -2031,7 +2049,7 @@ extern { pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, CPU: *const c_char, Features: *const c_char, - Model: CodeGenModel, + Model: CodeModel, Reloc: RelocMode, Level: CodeGenOptLevel, UseSoftFP: bool, @@ -2057,7 +2075,8 @@ extern { PM: PassManagerRef, M: ModuleRef, Output: *const c_char, - FileType: FileType) -> bool; + FileType: FileType) + -> LLVMRustResult; pub fn LLVMRustPrintModule(PM: PassManagerRef, M: ModuleRef, Output: *const c_char); @@ -2123,7 +2142,8 @@ extern { NumMembers: size_t, Members: *const RustArchiveMemberRef, WriteSymbtab: bool, - Kind: ArchiveKind) -> c_int; + Kind: ArchiveKind) -> + LLVMRustResult; pub fn LLVMRustArchiveMemberNew(Filename: *const c_char, Name: *const c_char, Child: ArchiveChildRef) -> RustArchiveMemberRef; diff --git a/src/librustc_trans/back/archive.rs b/src/librustc_trans/back/archive.rs index 29019f3683d..e063209799f 100644 --- a/src/librustc_trans/back/archive.rs +++ b/src/librustc_trans/back/archive.rs @@ -293,7 +293,7 @@ impl<'a> ArchiveBuilder<'a> { members.as_ptr(), self.should_update_symbols, kind); - let ret = if r != 0 { + let ret = if r.into_result().is_err() { let err = llvm::LLVMRustGetLastError(); let msg = if err.is_null() { "failed to write archive".to_string() diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 87815c63f79..0f3a45a7cff 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -54,7 +54,7 @@ pub fn write_output_file( let output_c = path2cstr(output); let result = llvm::LLVMRustWriteOutputFile( target, pm, m, output_c.as_ptr(), file_type); - if !result { + if result.into_result().is_err() { llvm_err(handler, format!("could not write output to {}", output.display())); } } @@ -138,11 +138,11 @@ fn target_feature(sess: &Session) -> String { fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel { match optimize { - config::OptLevel::No => llvm::CodeGenLevelNone, - config::OptLevel::Less => llvm::CodeGenLevelLess, - config::OptLevel::Default => llvm::CodeGenLevelDefault, - config::OptLevel::Aggressive => llvm::CodeGenLevelAggressive, - _ => llvm::CodeGenLevelDefault, + config::OptLevel::No => llvm::CodeGenOptLevel::None, + config::OptLevel::Less => llvm::CodeGenOptLevel::Less, + config::OptLevel::Default => llvm::CodeGenOptLevel::Default, + config::OptLevel::Aggressive => llvm::CodeGenOptLevel::Aggressive, + _ => llvm::CodeGenOptLevel::Default, } } @@ -169,11 +169,11 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef { }; let code_model = match code_model_arg { - "default" => llvm::CodeModelDefault, - "small" => llvm::CodeModelSmall, - "kernel" => llvm::CodeModelKernel, - "medium" => llvm::CodeModelMedium, - "large" => llvm::CodeModelLarge, + "default" => llvm::CodeModel::Default, + "small" => llvm::CodeModel::Small, + "kernel" => llvm::CodeModel::Kernel, + "medium" => llvm::CodeModel::Medium, + "large" => llvm::CodeModel::Large, _ => { sess.err(&format!("{:?} is not a valid code model", sess.opts @@ -449,9 +449,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, return false; } let pass_manager = match llvm::LLVMRustPassKind(pass) { - llvm::SupportedPassKind::Function => fpm, - llvm::SupportedPassKind::Module => mpm, - llvm::SupportedPassKind::Unsupported => { + llvm::PassKind::Function => fpm, + llvm::PassKind::Module => mpm, + llvm::PassKind::Other => { cgcx.handler.err("Encountered LLVM pass kind we can't handle"); return true }, @@ -579,7 +579,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, }; with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(cgcx.handler, tm, cpm, llmod, &path, - llvm::AssemblyFileType); + llvm::FileType::AssemblyFile); }); if config.emit_obj { llvm::LLVMDisposeModule(llmod); @@ -588,7 +588,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if write_obj { with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out, llvm::ObjectFileType); + write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out, + llvm::FileType::ObjectFile); }); } }); @@ -1078,7 +1079,7 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef, // reasonable defaults and prepare it to actually populate the pass // manager. let builder = llvm::LLVMPassManagerBuilderCreate(); - let opt_level = config.opt_level.unwrap_or(llvm::CodeGenLevelNone); + let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone); let inline_threshold = config.inline_threshold; @@ -1102,7 +1103,7 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef, (_, _, Some(t)) => { llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32); } - (llvm::CodeGenLevelAggressive, _, _) => { + (llvm::CodeGenOptLevel::Aggressive, _, _) => { llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275); } (_, llvm::CodeGenOptSizeDefault, _) => { @@ -1111,15 +1112,18 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef, (_, llvm::CodeGenOptSizeAggressive, _) => { llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25); } - (llvm::CodeGenLevelNone, _, _) => { + (llvm::CodeGenOptLevel::None, _, _) => { llvm::LLVMRustAddAlwaysInlinePass(builder, false); } - (llvm::CodeGenLevelLess, _, _) => { + (llvm::CodeGenOptLevel::Less, _, _) => { llvm::LLVMRustAddAlwaysInlinePass(builder, true); } - (llvm::CodeGenLevelDefault, _, _) => { + (llvm::CodeGenOptLevel::Default, _, _) => { llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225); } + (llvm::CodeGenOptLevel::Other, _, _) => { + bug!("CodeGenOptLevel::Other selected") + } } f(builder); diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 5a3c1c8512a..166ce990fdd 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -325,10 +325,10 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode { }; match reloc_model_arg { - "pic" => llvm::RelocPIC, - "static" => llvm::RelocStatic, - "default" => llvm::RelocDefault, - "dynamic-no-pic" => llvm::RelocDynamicNoPic, + "pic" => llvm::RelocMode::PIC, + "static" => llvm::RelocMode::Static, + "default" => llvm::RelocMode::Default, + "dynamic-no-pic" => llvm::RelocMode::DynamicNoPic, _ => { sess.err(&format!("{:?} is not a valid relocation mode", sess.opts @@ -347,7 +347,7 @@ fn is_any_library(sess: &Session) -> bool { } pub fn is_pie_binary(sess: &Session) -> bool { - !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocPIC + !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC } unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) { diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp index 3d48024c879..059cc40d511 100644 --- a/src/rustllvm/ArchiveWrapper.cpp +++ b/src/rustllvm/ArchiveWrapper.cpp @@ -16,24 +16,62 @@ using namespace llvm; using namespace llvm::object; -struct LLVMRustArchiveMember { +struct RustArchiveMember { const char *filename; const char *name; Archive::Child child; - LLVMRustArchiveMember(): filename(NULL), name(NULL), + RustArchiveMember(): filename(NULL), name(NULL), #if LLVM_VERSION_MINOR >= 8 child(NULL, NULL, NULL) #else child(NULL, NULL) #endif {} - ~LLVMRustArchiveMember() {} + ~RustArchiveMember() {} }; -typedef OwningBinary RustArchive; -extern "C" void* +struct RustArchiveIterator { + Archive::child_iterator cur; + Archive::child_iterator end; +#if LLVM_VERSION_MINOR >= 9 + Error err; +#endif +}; + +enum class LLVMRustArchiveKind { + Other, + GNU, + MIPS64, + BSD, + COFF, +}; + +static Archive::Kind +from_rust(LLVMRustArchiveKind kind) +{ + switch (kind) { + case LLVMRustArchiveKind::GNU: + return Archive::K_GNU; + case LLVMRustArchiveKind::MIPS64: + return Archive::K_MIPS64; + case LLVMRustArchiveKind::BSD: + return Archive::K_BSD; + case LLVMRustArchiveKind::COFF: + return Archive::K_COFF; + default: + abort(); + } +} + +typedef OwningBinary *LLVMRustArchiveRef; +typedef RustArchiveMember *LLVMRustArchiveMemberRef; +typedef Archive::Child *LLVMRustArchiveChildRef; +typedef Archive::Child const *LLVMRustArchiveChildConstRef; +typedef RustArchiveIterator *LLVMRustArchiveIteratorRef; + +extern "C" LLVMRustArchiveRef LLVMRustOpenArchive(char *path) { ErrorOr> buf_or = MemoryBuffer::getFile(path, -1, @@ -66,20 +104,12 @@ LLVMRustOpenArchive(char *path) { } extern "C" void -LLVMRustDestroyArchive(RustArchive *ar) { +LLVMRustDestroyArchive(LLVMRustArchiveRef ar) { delete ar; } -struct RustArchiveIterator { - Archive::child_iterator cur; - Archive::child_iterator end; -#if LLVM_VERSION_MINOR >= 9 - Error err; -#endif -}; - -extern "C" RustArchiveIterator* -LLVMRustArchiveIteratorNew(RustArchive *ra) { +extern "C" LLVMRustArchiveIteratorRef +LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) { Archive *ar = ra->getBinary(); RustArchiveIterator *rai = new RustArchiveIterator(); #if LLVM_VERSION_MINOR <= 8 @@ -95,8 +125,8 @@ LLVMRustArchiveIteratorNew(RustArchive *ra) { return rai; } -extern "C" const Archive::Child* -LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) { +extern "C" LLVMRustArchiveChildConstRef +LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) { #if LLVM_VERSION_MINOR >= 9 if (rai->err) { LLVMRustSetLastError(toString(std::move(rai->err)).c_str()); @@ -122,17 +152,17 @@ LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) { } extern "C" void -LLVMRustArchiveChildFree(Archive::Child *child) { +LLVMRustArchiveChildFree(LLVMRustArchiveChildRef child) { delete child; } extern "C" void -LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) { +LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef rai) { delete rai; } extern "C" const char* -LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) { +LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef child, size_t *size) { ErrorOr name_or_err = child->getName(); if (name_or_err.getError()) return NULL; @@ -142,7 +172,7 @@ LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) { } extern "C" const char* -LLVMRustArchiveChildData(Archive::Child *child, size_t *size) { +LLVMRustArchiveChildData(LLVMRustArchiveChildRef child, size_t *size) { StringRef buf; ErrorOr buf_or_err = child->getBuffer(); if (buf_or_err.getError()) { @@ -154,9 +184,10 @@ LLVMRustArchiveChildData(Archive::Child *child, size_t *size) { return buf.data(); } -extern "C" LLVMRustArchiveMember* -LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) { - LLVMRustArchiveMember *Member = new LLVMRustArchiveMember; +extern "C" LLVMRustArchiveMemberRef +LLVMRustArchiveMemberNew(char *Filename, char *Name, + LLVMRustArchiveChildRef child) { + RustArchiveMember *Member = new RustArchiveMember; Member->filename = Filename; Member->name = Name; if (child) @@ -165,22 +196,23 @@ LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) { } extern "C" void -LLVMRustArchiveMemberFree(LLVMRustArchiveMember *Member) { +LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) { delete Member; } -extern "C" int +extern "C" LLVMRustResult LLVMRustWriteArchive(char *Dst, size_t NumMembers, - const LLVMRustArchiveMember **NewMembers, + const LLVMRustArchiveMemberRef *NewMembers, bool WriteSymbtab, - Archive::Kind Kind) { + LLVMRustArchiveKind rust_kind) { #if LLVM_VERSION_MINOR <= 8 std::vector Members; #else std::vector Members; #endif + auto Kind = from_rust(rust_kind); for (size_t i = 0; i < NumMembers; i++) { auto Member = NewMembers[i]; @@ -190,7 +222,7 @@ LLVMRustWriteArchive(char *Dst, Expected MOrErr = NewArchiveMember::getFile(Member->filename, true); if (!MOrErr) { LLVMRustSetLastError(toString(MOrErr.takeError()).c_str()); - return -1; + return LLVMRustResult::Failure; } Members.push_back(std::move(*MOrErr)); #elif LLVM_VERSION_MINOR == 8 @@ -205,7 +237,7 @@ LLVMRustWriteArchive(char *Dst, Expected MOrErr = NewArchiveMember::getOldMember(Member->child, true); if (!MOrErr) { LLVMRustSetLastError(toString(MOrErr.takeError()).c_str()); - return -1; + return LLVMRustResult::Failure; } Members.push_back(std::move(*MOrErr)); #endif @@ -217,7 +249,7 @@ LLVMRustWriteArchive(char *Dst, auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true); #endif if (!pair.second) - return 0; + return LLVMRustResult::Success; LLVMRustSetLastError(pair.second.message().c_str()); - return -1; + return LLVMRustResult::Failure; } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index a1276060271..9e72724d8ab 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -54,41 +54,48 @@ LLVMInitializePasses() { initializeTarget(Registry); } - -enum class SupportedPassKind { +enum class LLVMRustPassKind { + Other, Function, Module, - Unsupported }; -extern "C" Pass* +static LLVMRustPassKind +to_rust(PassKind kind) +{ + switch (kind) { + case PT_Function: + return LLVMRustPassKind::Function; + case PT_Module: + return LLVMRustPassKind::Module; + default: + return LLVMRustPassKind::Other; + } +} + +extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) { StringRef SR(PassName); PassRegistry *PR = PassRegistry::getPassRegistry(); const PassInfo *PI = PR->getPassInfo(SR); if (PI) { - return PI->createPass(); + return wrap(PI->createPass()); } return NULL; } -extern "C" SupportedPassKind -LLVMRustPassKind(Pass *pass) { - assert(pass); - PassKind passKind = pass->getPassKind(); - if (passKind == PT_Module) { - return SupportedPassKind::Module; - } else if (passKind == PT_Function) { - return SupportedPassKind::Function; - } else { - return SupportedPassKind::Unsupported; - } +extern "C" LLVMRustPassKind +LLVMRustPassKind(LLVMPassRef rust_pass) { + assert(rust_pass); + Pass *pass = unwrap(rust_pass); + return to_rust(pass->getPassKind()); } extern "C" void -LLVMRustAddPass(LLVMPassManagerRef PM, Pass *pass) { - assert(pass); +LLVMRustAddPass(LLVMPassManagerRef PM, LLVMPassRef rust_pass) { + assert(rust_pass); + Pass *pass = unwrap(rust_pass); PassManagerBase *pm = unwrap(PM); pm->add(pass); } @@ -162,13 +169,69 @@ LLVMRustHasFeature(LLVMTargetMachineRef TM, return (Bits & FeatureEntry->Value) == FeatureEntry->Value; } +enum class LLVMRustCodeModel { + Other, + Default, + JITDefault, + Small, + Kernel, + Medium, + Large, +}; + +static CodeModel::Model +from_rust(LLVMRustCodeModel model) +{ + switch (model) { + case LLVMRustCodeModel::Default: + return CodeModel::Default; + case LLVMRustCodeModel::JITDefault: + return CodeModel::JITDefault; + case LLVMRustCodeModel::Small: + return CodeModel::Small; + case LLVMRustCodeModel::Kernel: + return CodeModel::Kernel; + case LLVMRustCodeModel::Medium: + return CodeModel::Medium; + case LLVMRustCodeModel::Large: + return CodeModel::Large; + default: + abort(); + } +} + +enum class LLVMRustCodeGenOptLevel { + Other, + None, + Less, + Default, + Aggressive, +}; + +static CodeGenOpt::Level +from_rust(LLVMRustCodeGenOptLevel level) +{ + switch (level) { + case LLVMRustCodeGenOptLevel::None: + return CodeGenOpt::None; + case LLVMRustCodeGenOptLevel::Less: + return CodeGenOpt::Less; + case LLVMRustCodeGenOptLevel::Default: + return CodeGenOpt::Default; + case LLVMRustCodeGenOptLevel::Aggressive: + return CodeGenOpt::Aggressive; + default: + abort(); + } +} + extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(const char *triple, const char *cpu, const char *feature, - CodeModel::Model CM, + LLVMRustCodeModel rust_CM, LLVMRelocMode Reloc, - CodeGenOpt::Level OptLevel, + LLVMRustCodeGenOptLevel rust_OptLevel, bool UseSoftFloat, bool PositionIndependentExecutable, bool FunctionSections, @@ -179,6 +242,9 @@ LLVMRustCreateTargetMachine(const char *triple, #else Optional RM; #endif + auto CM = from_rust(rust_CM); + auto OptLevel = from_rust(rust_OptLevel); + switch (Reloc){ case LLVMRelocStatic: RM = Reloc::Static; @@ -251,14 +317,14 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM, extern "C" void LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB, - CodeGenOpt::Level OptLevel, + LLVMRustCodeGenOptLevel OptLevel, bool MergeFunctions, bool SLPVectorize, bool LoopVectorize) { // Ignore mergefunc for now as enabling it causes crashes. //unwrap(PMB)->MergeFunctions = MergeFunctions; unwrap(PMB)->SLPVectorize = SLPVectorize; - unwrap(PMB)->OptLevel = OptLevel; + unwrap(PMB)->OptLevel = from_rust(OptLevel); unwrap(PMB)->LoopVectorize = LoopVectorize; } @@ -314,13 +380,33 @@ LLVMRustSetLLVMOptions(int Argc, char **Argv) { cl::ParseCommandLineOptions(Argc, Argv); } -extern "C" bool +enum class LLVMRustFileType { + Other, + AssemblyFile, + ObjectFile, +}; + +static TargetMachine::CodeGenFileType +from_rust(LLVMRustFileType type) +{ + switch (type) { + case LLVMRustFileType::AssemblyFile: + return TargetMachine::CGFT_AssemblyFile; + case LLVMRustFileType::ObjectFile: + return TargetMachine::CGFT_ObjectFile; + default: + abort(); + } +} + +extern "C" LLVMRustResult LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, LLVMModuleRef M, const char *path, - TargetMachine::CodeGenFileType FileType) { + LLVMRustFileType rust_FileType) { llvm::legacy::PassManager *PM = unwrap(PMR); + auto FileType = from_rust(rust_FileType); std::string ErrorInfo; std::error_code EC; @@ -329,7 +415,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, ErrorInfo = EC.message(); if (ErrorInfo != "") { LLVMRustSetLastError(ErrorInfo.c_str()); - return false; + return LLVMRustResult::Failure; } unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false); @@ -339,7 +425,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, // stream (OS), so the only real safe place to delete this is here? Don't we // wish this was written in Rust? delete PM; - return true; + return LLVMRustResult::Success; } extern "C" void diff --git a/src/rustllvm/README b/src/rustllvm/README index c0db3f68a76..e1c6dd07d2b 100644 --- a/src/rustllvm/README +++ b/src/rustllvm/README @@ -1,2 +1,16 @@ This directory currently contains some LLVM support code. This will generally be sent upstream to LLVM in time; for now it lives here. + +NOTE: the LLVM C++ ABI is subject to between-version breakage and must *never* +be exposed to Rust. To allow for easy auditing of that, all Rust-exposed types +must be typedef-ed as "LLVMXyz", or "LLVMRustXyz" if they were defined here. + +Functions that return a failure status and leave the error in +the LLVM last error should return an LLVMRustResult rather than an +int or anything to avoid confusion. + +When translating enums, add a single `Other` variant as the first +one to allow for new variants to be added. It should abort when used +as an input. + +All other types must not be typedef-ed as such. diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h index 2a47e8b0895..5aae11fb456 100644 --- a/src/rustllvm/rustllvm.h +++ b/src/rustllvm/rustllvm.h @@ -58,6 +58,11 @@ void LLVMRustSetLastError(const char*); +enum class LLVMRustResult { + Success, + Failure +}; + typedef struct OpaqueRustString *RustStringRef; typedef struct LLVMOpaqueTwine *LLVMTwineRef; typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef; -- cgit 1.4.1-3-g733a5 From 3041a97b1acef4f8549d9e297db8deaf571341f2 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 3 Aug 2016 00:25:19 +0300 Subject: finish type-auditing rustllvm --- src/librustc_llvm/ffi.rs | 71 +++++++++++----------- src/librustc_llvm/lib.rs | 114 +++++++++++++++++++++++------------- src/librustc_trans/abi.rs | 8 +-- src/librustc_trans/asm.rs | 4 +- src/librustc_trans/attributes.rs | 62 +++++++------------- src/librustc_trans/base.rs | 8 +-- src/librustc_trans/builder.rs | 2 +- src/librustc_trans/closure.rs | 12 ++-- src/librustc_trans/common.rs | 2 +- src/librustc_trans/consts.rs | 16 ++--- src/librustc_trans/debuginfo/gdb.rs | 2 +- src/librustc_trans/declare.rs | 13 ++-- src/librustc_trans/mir/constant.rs | 4 +- src/librustc_trans/monomorphize.rs | 4 +- src/librustc_trans/trans_item.rs | 6 +- src/librustc_trans/type_.rs | 2 +- src/rustllvm/ArchiveWrapper.cpp | 2 +- src/rustllvm/PassWrapper.cpp | 6 +- src/rustllvm/RustWrapper.cpp | 102 ++++++++++++++++++++------------ 19 files changed, 246 insertions(+), 194 deletions(-) (limited to 'src/rustllvm/PassWrapper.cpp') diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 53a287ea8ec..6301c57c555 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -13,19 +13,20 @@ use debuginfo::{DIBuilderRef, DIDescriptor, DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable, DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator, DINameSpace}; -use RustStringRef; -use libc::{c_uint, c_ushort, c_int, size_t, c_char}; +use libc::{c_uint, c_int, size_t, c_char}; use libc::{c_longlong, c_ulonglong, c_void}; +use RustStringRef; + pub type Opcode = u32; pub type Bool = c_uint; pub const True: Bool = 1 as Bool; pub const False: Bool = 0 as Bool; -#[repr(C)] #[derive(Copy, Clone, PartialEq)] +#[repr(C)] pub enum LLVMRustResult { Success, Failure, @@ -68,8 +69,8 @@ pub enum Linkage { } /// LLVMDiagnosticSeverity -#[repr(C)] #[derive(Copy, Clone, Debug)] +#[repr(C)] pub enum DiagnosticSeverity { Error = 0, Warning = 1, @@ -77,14 +78,13 @@ pub enum DiagnosticSeverity { Note = 3, } -/// LLVMRustDLLStorageClassTypes -#[repr(C)] +/// LLVMDLLStorageClass #[derive(Copy, Clone)] -pub enum DLLStorageClassTypes { - Other, - Default, - DllImport, - DllExport, +#[repr(C)] +pub enum DLLStorageClass { + Default = 0, + DllImport = 1, /* Function to be imported from DLL. */ + DllExport = 2, /* Function to be accessible from DLL. */ } bitflags! { @@ -144,6 +144,7 @@ bitflags! { /// LLVMIntPredicate #[derive(Copy, Clone)] +#[repr(C)] pub enum IntPredicate { IntEQ = 32, IntNE = 33, @@ -159,6 +160,7 @@ pub enum IntPredicate { /// LLVMRealPredicate #[derive(Copy, Clone)] +#[repr(C)] pub enum RealPredicate { RealPredicateFalse = 0, RealOEQ = 1, @@ -178,7 +180,7 @@ pub enum RealPredicate { RealPredicateTrue = 15, } -/// LLVMTypeKind; FIXME: wrap +/// LLVMTypeKind #[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] pub enum TypeKind { @@ -198,11 +200,12 @@ pub enum TypeKind { Vector = 13, Metadata = 14, X86_MMX = 15, + Token = 16, } /// LLVMAtomicRmwBinOp -#[repr(C)] #[derive(Copy, Clone)] +#[repr(C)] pub enum AtomicRmwBinOp { AtomicXchg = 0, AtomicAdd = 1, @@ -218,8 +221,8 @@ pub enum AtomicRmwBinOp { } /// LLVMAtomicOrdering -#[repr(C)] #[derive(Copy, Clone)] +#[repr(C)] pub enum AtomicOrdering { NotAtomic = 0, Unordered = 1, @@ -232,8 +235,8 @@ pub enum AtomicOrdering { } /// LLVMRustSynchronizationScope -#[repr(C)] #[derive(Copy, Clone)] +#[repr(C)] pub enum SynchronizationScope { Other, SingleThread, @@ -241,16 +244,18 @@ pub enum SynchronizationScope { } /// LLVMRustFileType -#[repr(C)] #[derive(Copy, Clone)] +#[repr(C)] pub enum FileType { Other, AssemblyFile, ObjectFile, } -/// FIXME: ? +/// Enum pinned in LLVMContext, used in +/// LLVMSetMetadata so ABI-stable. #[derive(Copy, Clone)] +#[repr(C)] pub enum MetadataType { MD_dbg = 0, MD_tbaa = 1, @@ -266,11 +271,13 @@ pub enum MetadataType { MD_nonnull = 11, } -/// FIXME: ? +/// LLVMRustAsmDialect #[derive(Copy, Clone)] +#[repr(C)] pub enum AsmDialect { - AD_ATT = 0, - AD_Intel = 1 + Other, + Att, + Intel, } /// LLVMRustCodeGenOptLevel @@ -295,8 +302,8 @@ pub enum RelocMode { } /// LLVMRustCodeModel -#[repr(C)] #[derive(Copy, Clone)] +#[repr(C)] pub enum CodeModel { Other, Default, @@ -308,8 +315,8 @@ pub enum CodeModel { } /// LLVMRustDiagnosticKind -#[repr(C)] #[derive(Copy, Clone)] +#[repr(C)] pub enum DiagnosticKind { Other, InlineAsm, @@ -326,8 +333,8 @@ pub enum DiagnosticKind { } /// LLVMRustArchiveKind -#[repr(C)] #[derive(Copy, Clone)] +#[repr(C)] pub enum ArchiveKind { Other, K_GNU, @@ -335,6 +342,7 @@ pub enum ArchiveKind { K_BSD, K_COFF, } + /// LLVMRustPassKind #[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] @@ -519,7 +527,7 @@ extern { pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char); /// See llvm::LLVMTypeKind::getTypeID. - pub fn LLVMGetTypeKind(Ty: TypeRef) -> TypeKind; + pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind; /// See llvm::LLVMType::getContext. pub fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef; @@ -589,8 +597,6 @@ extern { pub fn LLVMSetValueName(Val: ValueRef, Name: *const c_char); pub fn LLVMDumpValue(Val: ValueRef); pub fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef); - pub fn LLVMHasMetadata(Val: ValueRef) -> c_int; - pub fn LLVMGetMetadata(Val: ValueRef, KindID: c_uint) -> ValueRef; pub fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef); /* Operations on Uses */ @@ -608,9 +614,9 @@ extern { pub fn LLVMConstNull(Ty: TypeRef) -> ValueRef; /* all zeroes */ pub fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef; - pub fn LLVMConstICmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) + pub fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; - pub fn LLVMConstFCmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) + pub fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; /* only for isize/vector */ pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; @@ -815,13 +821,15 @@ extern { pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef; pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool; pub fn LLVMGetLinkage(Global: ValueRef) -> c_uint; - pub fn LLVMSetLinkage(Global: ValueRef, Link: c_uint); + pub fn LLVMSetLinkage(Global: ValueRef, Link: Linkage); pub fn LLVMGetSection(Global: ValueRef) -> *const c_char; pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char); pub fn LLVMGetVisibility(Global: ValueRef) -> c_uint; pub fn LLVMSetVisibility(Global: ValueRef, Viz: c_uint); pub fn LLVMGetAlignment(Global: ValueRef) -> c_uint; pub fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint); + pub fn LLVMSetDLLStorageClass(V: ValueRef, + C: DLLStorageClass); /* Operations on global variables */ @@ -1685,7 +1693,7 @@ extern { Constraints: *const c_char, SideEffects: Bool, AlignStack: Bool, - Dialect: c_uint) + Dialect: AsmDialect) -> ValueRef; pub fn LLVMRustDebugMetadataVersion() -> u32; @@ -1990,9 +1998,6 @@ extern { pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef); pub fn LLVMRustDestroyArchive(AR: ArchiveRef); - pub fn LLVMRustSetDLLStorageClass(V: ValueRef, - C: DLLStorageClassTypes); - pub fn LLVMRustGetSectionName(SI: SectionIteratorRef, data: *mut *const c_char) -> size_t; diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index f451b167196..6c4e1a54ea7 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -33,13 +33,11 @@ extern crate libc; #[macro_use] #[no_link] extern crate rustc_bitflags; -pub use self::AttributeSet::*; pub use self::IntPredicate::*; pub use self::RealPredicate::*; pub use self::TypeKind::*; pub use self::AtomicRmwBinOp::*; pub use self::MetadataType::*; -pub use self::AsmDialect::*; pub use self::CodeGenOptSize::*; pub use self::DiagnosticKind::*; pub use self::CallConv::*; @@ -50,7 +48,7 @@ use std::str::FromStr; use std::slice; use std::ffi::{CString, CStr}; use std::cell::RefCell; -use libc::{c_uint, c_ushort, c_char, size_t}; +use libc::{c_uint, c_char, size_t}; pub mod archive_ro; pub mod diagnostic; @@ -94,32 +92,64 @@ impl Attributes { self } - pub fn apply_llfn(&self, idx: usize, llfn: ValueRef) { + pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { unsafe { - LLVMRustAddFunctionAttribute(llfn, idx as c_uint, self.regular.bits()); + self.regular.apply_llfn(idx, llfn); if self.dereferenceable_bytes != 0 { - LLVMRustAddDereferenceableAttr(llfn, idx as c_uint, - self.dereferenceable_bytes); + LLVMRustAddDereferenceableAttr( + llfn, + idx.as_uint(), + self.dereferenceable_bytes); } } } - pub fn apply_callsite(&self, idx: usize, callsite: ValueRef) { + pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) { unsafe { - LLVMRustAddCallSiteAttribute(callsite, idx as c_uint, self.regular.bits()); + self.regular.apply_callsite(idx, callsite); if self.dereferenceable_bytes != 0 { - LLVMRustAddDereferenceableCallSiteAttr(callsite, idx as c_uint, - self.dereferenceable_bytes); + LLVMRustAddDereferenceableCallSiteAttr( + callsite, + idx.as_uint(), + self.dereferenceable_bytes); } } } } +pub fn AddFunctionAttrStringValue( + llfn: ValueRef, + idx: AttributePlace, + attr: &'static str, + value: &'static str +) { + unsafe { + LLVMRustAddFunctionAttrStringValue( + llfn, + idx.as_uint(), + attr.as_ptr() as *const _, + value.as_ptr() as *const _) + } +} + #[repr(C)] #[derive(Copy, Clone)] -pub enum AttributeSet { - ReturnIndex = 0, - FunctionIndex = !0 +pub enum AttributePlace { + Argument(u32), + Function, +} + +impl AttributePlace { + pub fn ReturnValue() -> Self { + AttributePlace::Argument(0) + } + + fn as_uint(self) -> c_uint { + match self { + AttributePlace::Function => !0, + AttributePlace::Argument(i) => i, + } + } } #[derive(Copy, Clone, PartialEq)] @@ -170,11 +200,6 @@ pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) { LLVMSetFunctionCallConv(fn_, cc as c_uint); } } -pub fn SetLinkage(global: ValueRef, link: Linkage) { - unsafe { - LLVMSetLinkage(global, link as c_uint); - } -} // Externally visible symbols that might appear in multiple translation units need to appear in // their own comdat section so that the duplicates can be discarded at link time. This can for @@ -194,12 +219,6 @@ pub fn UnsetComdat(val: ValueRef) { } } -pub fn SetDLLStorageClass(global: ValueRef, class: DLLStorageClassTypes) { - unsafe { - LLVMRustSetDLLStorageClass(global, class); - } -} - pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) { unsafe { LLVMSetUnnamedAddr(global, unnamed as Bool); @@ -212,29 +231,40 @@ pub fn set_thread_local(global: ValueRef, is_thread_local: bool) { } } -pub fn ConstICmp(pred: IntPredicate, v1: ValueRef, v2: ValueRef) -> ValueRef { - unsafe { - LLVMConstICmp(pred as c_ushort, v1, v2) +impl Attribute { + pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { + unsafe { + LLVMRustAddFunctionAttribute( + llfn, idx.as_uint(), self.bits()) + } } -} -pub fn ConstFCmp(pred: RealPredicate, v1: ValueRef, v2: ValueRef) -> ValueRef { - unsafe { - LLVMConstFCmp(pred as c_ushort, v1, v2) + + pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) { + unsafe { + LLVMRustAddCallSiteAttribute( + callsite, idx.as_uint(), self.bits()) + } } -} -pub fn SetFunctionAttribute(fn_: ValueRef, attr: Attribute) { - unsafe { - LLVMRustAddFunctionAttribute(fn_, FunctionIndex as c_uint, - attr.bits() as u64) + pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { + unsafe { + LLVMRustRemoveFunctionAttributes( + llfn, idx.as_uint(), self.bits()) + } } -} -pub fn RemoveFunctionAttributes(fn_: ValueRef, attr: Attribute) { - unsafe { - LLVMRustRemoveFunctionAttributes(fn_, FunctionIndex as c_uint, - attr.bits() as u64) + pub fn toggle_llfn(&self, + idx: AttributePlace, + llfn: ValueRef, + set: bool) + { + if set { + self.apply_llfn(idx, llfn); + } else { + self.unapply_llfn(idx, llfn); + } } + } /* Memory-managed interface to target data. */ diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 6c2a09f8060..587c03af3ab 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -552,13 +552,13 @@ impl FnType { pub fn apply_attrs_llfn(&self, llfn: ValueRef) { let mut i = if self.ret.is_indirect() { 1 } else { 0 }; if !self.ret.is_ignore() { - self.ret.attrs.apply_llfn(i, llfn); + self.ret.attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn); } i += 1; for arg in &self.args { if !arg.is_ignore() { if arg.pad.is_some() { i += 1; } - arg.attrs.apply_llfn(i, llfn); + arg.attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn); i += 1; } } @@ -567,13 +567,13 @@ impl FnType { pub fn apply_attrs_callsite(&self, callsite: ValueRef) { let mut i = if self.ret.is_indirect() { 1 } else { 0 }; if !self.ret.is_ignore() { - self.ret.attrs.apply_callsite(i, callsite); + self.ret.attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite); } i += 1; for arg in &self.args { if !arg.is_ignore() { if arg.pad.is_some() { i += 1; } - arg.attrs.apply_callsite(i, callsite); + arg.attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite); i += 1; } } diff --git a/src/librustc_trans/asm.rs b/src/librustc_trans/asm.rs index e27bec68375..5514fb0f4ef 100644 --- a/src/librustc_trans/asm.rs +++ b/src/librustc_trans/asm.rs @@ -83,8 +83,8 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }; let dialect = match ia.dialect { - AsmDialect::Att => llvm::AD_ATT, - AsmDialect::Intel => llvm::AD_Intel + AsmDialect::Att => llvm::AsmDialect::Att, + AsmDialect::Intel => llvm::AsmDialect::Intel, }; let asm = CString::new(ia.asm.as_bytes()).unwrap(); diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index 9c121ae9bfc..62eac35e0ab 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -9,8 +9,8 @@ // except according to those terms. //! Set and unset common attributes on LLVM values. -use libc::c_uint; -use llvm::{self, ValueRef}; +use llvm::{self, Attribute, ValueRef}; +use llvm::AttributePlace::Function; pub use syntax::attr::InlineAttr; use syntax::ast; use context::CrateContext; @@ -20,14 +20,14 @@ use context::CrateContext; pub fn inline(val: ValueRef, inline: InlineAttr) { use self::InlineAttr::*; match inline { - Hint => llvm::SetFunctionAttribute(val, llvm::Attribute::InlineHint), - Always => llvm::SetFunctionAttribute(val, llvm::Attribute::AlwaysInline), - Never => llvm::SetFunctionAttribute(val, llvm::Attribute::NoInline), + Hint => Attribute::InlineHint.apply_llfn(Function, val), + Always => Attribute::AlwaysInline.apply_llfn(Function, val), + Never => Attribute::NoInline.apply_llfn(Function, val), None => { - let attr = llvm::Attribute::InlineHint | - llvm::Attribute::AlwaysInline | - llvm::Attribute::NoInline; - llvm::RemoveFunctionAttributes(val, attr) + let attr = Attribute::InlineHint | + Attribute::AlwaysInline | + Attribute::NoInline; + attr.unapply_llfn(Function, val) }, }; } @@ -35,56 +35,37 @@ pub fn inline(val: ValueRef, inline: InlineAttr) { /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function. #[inline] pub fn emit_uwtable(val: ValueRef, emit: bool) { - if emit { - llvm::SetFunctionAttribute(val, llvm::Attribute::UWTable); - } else { - llvm::RemoveFunctionAttributes(val, llvm::Attribute::UWTable); - } + Attribute::UWTable.toggle_llfn(Function, val, emit); } /// Tell LLVM whether the function can or cannot unwind. #[inline] pub fn unwind(val: ValueRef, can_unwind: bool) { - if can_unwind { - llvm::RemoveFunctionAttributes(val, llvm::Attribute::NoUnwind); - } else { - llvm::SetFunctionAttribute(val, llvm::Attribute::NoUnwind); - } + Attribute::NoUnwind.toggle_llfn(Function, val, !can_unwind); } /// Tell LLVM whether it should optimise function for size. #[inline] #[allow(dead_code)] // possibly useful function pub fn set_optimize_for_size(val: ValueRef, optimize: bool) { - if optimize { - llvm::SetFunctionAttribute(val, llvm::Attribute::OptimizeForSize); - } else { - llvm::RemoveFunctionAttributes(val, llvm::Attribute::OptimizeForSize); - } + Attribute::OptimizeForSize.toggle_llfn(Function, val, optimize); } /// Tell LLVM if this function should be 'naked', i.e. skip the epilogue and prologue. #[inline] pub fn naked(val: ValueRef, is_naked: bool) { - if is_naked { - llvm::SetFunctionAttribute(val, llvm::Attribute::Naked); - } else { - llvm::RemoveFunctionAttributes(val, llvm::Attribute::Naked); - } + Attribute::Naked.toggle_llfn(Function, val, is_naked); } pub fn set_frame_pointer_elimination(ccx: &CrateContext, llfn: ValueRef) { // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a // parameter. if ccx.sess().must_not_eliminate_frame_pointers() { - unsafe { - let attr = "no-frame-pointer-elim\0".as_ptr() as *const _; - let val = "true\0".as_ptr() as *const _; - llvm::LLVMRustAddFunctionAttrStringValue(llfn, - llvm::FunctionIndex as c_uint, - attr, - val); - } + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + "no-frame-pointer-elim\0", + "true\0") } } @@ -98,13 +79,12 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe for attr in attrs { if attr.check_name("cold") { - llvm::Attributes::default().set(llvm::Attribute::Cold) - .apply_llfn(llvm::FunctionIndex as usize, llfn) + Attribute::Cold.apply_llfn(Function, llfn); } else if attr.check_name("naked") { naked(llfn, true); } else if attr.check_name("allocator") { - llvm::Attributes::default().set(llvm::Attribute::NoAlias) - .apply_llfn(llvm::ReturnIndex as usize, llfn) + Attribute::NoAlias.apply_llfn( + llvm::AttributePlace::ReturnValue(), llfn); } else if attr.check_name("unwind") { unwind(llfn, true); } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 3e66f6de242..7fb19fefee2 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -2347,9 +2347,9 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session, let has_fixed_linkage = linkage_fixed_explicitly.contains(&name_cow); if !is_referenced_somewhere && !is_reachable && !has_fixed_linkage { - llvm::SetLinkage(val, llvm::InternalLinkage); - llvm::SetDLLStorageClass(val, - llvm::DLLStorageClassTypes::Default); + llvm::LLVMSetLinkage(val, llvm::InternalLinkage); + llvm::LLVMSetDLLStorageClass(val, + llvm::DLLStorageClass::Default); llvm::UnsetComdat(val); } } @@ -2394,7 +2394,7 @@ fn create_imps(cx: &CrateContextList) { imp_name.as_ptr() as *const _); let init = llvm::LLVMConstBitCast(val, i8p_ty.to_ref()); llvm::LLVMSetInitializer(imp, init); - llvm::SetLinkage(imp, llvm::ExternalLinkage); + llvm::LLVMSetLinkage(imp, llvm::ExternalLinkage); } } } diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index 28d69d4815f..90f96af5496 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -841,7 +841,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let fty = Type::func(&argtys[..], &output); unsafe { let v = llvm::LLVMRustInlineAsm( - fty.to_ref(), asm, cons, volatile, alignstack, dia as c_uint); + fty.to_ref(), asm, cons, volatile, alignstack, dia); self.call(v, inputs, None) } } diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 6b9de4a4878..e53a5edfc66 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -249,11 +249,13 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, if !ccx.instances().borrow().contains_key(&instance) { let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs); - if ccx.sess().target.target.options.allows_weak_linkage { - llvm::SetLinkage(llfn, llvm::WeakODRLinkage); - llvm::SetUniqueComdat(ccx.llmod(), llfn); - } else { - llvm::SetLinkage(llfn, llvm::InternalLinkage); + unsafe { + if ccx.sess().target.target.options.allows_weak_linkage { + llvm::LLVMSetLinkage(llfn, llvm::WeakODRLinkage); + llvm::SetUniqueComdat(ccx.llmod(), llfn); + } else { + llvm::LLVMSetLinkage(llfn, llvm::InternalLinkage); + } } // set an inline hint for all closures diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 61d8a0837c1..a1783e9c0a3 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -980,7 +980,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va }); llvm::LLVMSetInitializer(g, sc); llvm::LLVMSetGlobalConstant(g, True); - llvm::SetLinkage(g, llvm::InternalLinkage); + llvm::LLVMSetLinkage(g, llvm::InternalLinkage); cx.const_cstr_cache().borrow_mut().insert(s, g); g diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 996efc9c113..7afb5257258 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -10,7 +10,7 @@ use llvm; -use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr}; +use llvm::{SetUnnamedAddr}; use llvm::{InternalLinkage, ValueRef, Bool, True}; use middle::const_qualif::ConstQualif; use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, lookup_const_by_id, ErrKind}; @@ -125,7 +125,7 @@ pub fn addr_of_mut(ccx: &CrateContext, }); llvm::LLVMSetInitializer(gv, cv); llvm::LLVMSetAlignment(gv, align); - SetLinkage(gv, InternalLinkage); + llvm::LLVMSetLinkage(gv, InternalLinkage); SetUnnamedAddr(gv, true); gv } @@ -637,10 +637,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, hir::BiEq | hir::BiNe | hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe => { if is_float { let cmp = base::bin_op_to_fcmp_predicate(b.node); - ConstFCmp(cmp, te1, te2) + llvm::LLVMConstFCmp(cmp, te1, te2) } else { let cmp = base::bin_op_to_icmp_predicate(b.node, signed); - ConstICmp(cmp, te1, te2) + llvm::LLVMConstICmp(cmp, te1, te2) } }, } } // unsafe { match b.node { @@ -1072,7 +1072,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) unsafe { // Declare a symbol `foo` with the desired linkage. let g1 = declare::declare_global(ccx, &sym, llty2); - llvm::SetLinkage(g1, linkage); + llvm::LLVMSetLinkage(g1, linkage); // Declare an internal global `extern_with_linkage_foo` which // is initialized with the address of `foo`. If `foo` is @@ -1086,7 +1086,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) ccx.sess().span_fatal(span, &format!("symbol `{}` is already defined", &sym)) }); - llvm::SetLinkage(g2, llvm::InternalLinkage); + llvm::LLVMSetLinkage(g2, llvm::InternalLinkage); llvm::LLVMSetInitializer(g2, g1); g2 } @@ -1126,7 +1126,9 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) } } if ccx.use_dll_storage_attrs() { - llvm::SetDLLStorageClass(g, llvm::DLLStorageClassTypes::DllImport); + unsafe { + llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport); + } } g }; diff --git a/src/librustc_trans/debuginfo/gdb.rs b/src/librustc_trans/debuginfo/gdb.rs index cf312855d75..0a8d490dcd2 100644 --- a/src/librustc_trans/debuginfo/gdb.rs +++ b/src/librustc_trans/debuginfo/gdb.rs @@ -77,7 +77,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext) llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); llvm::LLVMSetUnnamedAddr(section_var, llvm::True); - llvm::SetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage); + llvm::LLVMSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage); // This should make sure that the whole section is not larger than // the string it contains. Otherwise we get a warning from GDB. llvm::LLVMSetAlignment(section_var, 1); diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs index 15d90504ee7..324e8697eca 100644 --- a/src/librustc_trans/declare.rs +++ b/src/librustc_trans/declare.rs @@ -20,6 +20,7 @@ //! * Use define_* family of methods when you might be defining the ValueRef. //! * When in doubt, define. use llvm::{self, ValueRef}; +use llvm::AttributePlace::Function; use rustc::ty; use abi::{Abi, FnType}; use attributes; @@ -65,16 +66,16 @@ fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: if ccx.tcx().sess.opts.cg.no_redzone .unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) { - llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoRedZone) + llvm::Attribute::NoRedZone.apply_llfn(Function, llfn); } match ccx.tcx().sess.opts.cg.opt_level.as_ref().map(String::as_ref) { Some("s") => { - llvm::SetFunctionAttribute(llfn, llvm::Attribute::OptimizeForSize); + llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn); }, Some("z") => { - llvm::SetFunctionAttribute(llfn, llvm::Attribute::MinSize); - llvm::SetFunctionAttribute(llfn, llvm::Attribute::OptimizeForSize); + llvm::Attribute::MinSize.apply_llfn(Function, llfn); + llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn); }, _ => {}, } @@ -111,7 +112,7 @@ pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx)); if sig.output == ty::FnDiverging { - llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoReturn); + llvm::Attribute::NoReturn.apply_llfn(Function, llfn); } if abi != Abi::Rust && abi != Abi::RustCall { @@ -162,7 +163,7 @@ pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, fn_type: ty::Ty<'tcx>) -> ValueRef { let llfn = define_fn(ccx, name, fn_type); - llvm::SetLinkage(llfn, llvm::InternalLinkage); + unsafe { llvm::LLVMSetLinkage(llfn, llvm::InternalLinkage) }; llfn } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 8dc5e5f993f..00db19d2739 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -824,11 +824,11 @@ pub fn const_scalar_binop(op: mir::BinOp, mir::BinOp::Gt | mir::BinOp::Ge => { if is_float { let cmp = base::bin_op_to_fcmp_predicate(op.to_hir_binop()); - llvm::ConstFCmp(cmp, lhs, rhs) + llvm::LLVMConstFCmp(cmp, lhs, rhs) } else { let cmp = base::bin_op_to_icmp_predicate(op.to_hir_binop(), signed); - llvm::ConstICmp(cmp, lhs, rhs) + llvm::LLVMConstICmp(cmp, lhs, rhs) } } } diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 96a05f11bfd..e9aacaa0f95 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -125,7 +125,9 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, if ccx.shared().translation_items().borrow().contains(&trans_item) { attributes::from_fn_attrs(ccx, attrs, lldecl); - llvm::SetLinkage(lldecl, llvm::ExternalLinkage); + unsafe { + llvm::LLVMSetLinkage(lldecl, llvm::ExternalLinkage); + } } else { // FIXME: #34151 // Normally, getting here would indicate a bug in trans::collector, diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index fc2758e50f2..35bb0481c8e 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -208,7 +208,7 @@ impl<'a, 'tcx> TransItem<'tcx> { &format!("symbol `{}` is already defined", symbol_name)) }); - llvm::SetLinkage(g, linkage); + unsafe { llvm::LLVMSetLinkage(g, linkage) }; } item => bug!("predefine_static: expected static, found {:?}", item) @@ -250,7 +250,7 @@ impl<'a, 'tcx> TransItem<'tcx> { ref attrs, node: hir::ImplItemKind::Method(..), .. }) => { let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty); - llvm::SetLinkage(lldecl, linkage); + unsafe { llvm::LLVMSetLinkage(lldecl, linkage) }; base::set_link_section(ccx, lldecl, attrs); if linkage == llvm::LinkOnceODRLinkage || linkage == llvm::WeakODRLinkage { @@ -287,7 +287,7 @@ impl<'a, 'tcx> TransItem<'tcx> { assert!(declare::get_defined_value(ccx, symbol_name).is_none()); let llfn = declare::declare_cfn(ccx, symbol_name, llfnty); - llvm::SetLinkage(llfn, linkage); + unsafe { llvm::LLVMSetLinkage(llfn, linkage) }; if linkage == llvm::LinkOnceODRLinkage || linkage == llvm::WeakODRLinkage { llvm::SetUniqueComdat(ccx.llmod(), llfn); diff --git a/src/librustc_trans/type_.rs b/src/librustc_trans/type_.rs index c09515a5138..d191591e082 100644 --- a/src/librustc_trans/type_.rs +++ b/src/librustc_trans/type_.rs @@ -208,7 +208,7 @@ impl Type { pub fn kind(&self) -> TypeKind { unsafe { - llvm::LLVMGetTypeKind(self.to_ref()) + llvm::LLVMRustGetTypeKind(self.to_ref()) } } diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp index 059cc40d511..1e873b5345c 100644 --- a/src/rustllvm/ArchiveWrapper.cpp +++ b/src/rustllvm/ArchiveWrapper.cpp @@ -61,7 +61,7 @@ from_rust(LLVMRustArchiveKind kind) case LLVMRustArchiveKind::COFF: return Archive::K_COFF; default: - abort(); + llvm_unreachable("Bad ArchiveKind."); } } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 9e72724d8ab..e3dcf45cf0f 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -196,7 +196,7 @@ from_rust(LLVMRustCodeModel model) case LLVMRustCodeModel::Large: return CodeModel::Large; default: - abort(); + llvm_unreachable("Bad CodeModel."); } } @@ -221,7 +221,7 @@ from_rust(LLVMRustCodeGenOptLevel level) case LLVMRustCodeGenOptLevel::Aggressive: return CodeGenOpt::Aggressive; default: - abort(); + llvm_unreachable("Bad CodeGenOptLevel."); } } @@ -395,7 +395,7 @@ from_rust(LLVMRustFileType type) case LLVMRustFileType::ObjectFile: return TargetMachine::CGFT_ObjectFile; default: - abort(); + llvm_unreachable("Bad FileType."); } } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index a9c31bc33e0..0da25e7ac57 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -263,7 +263,7 @@ from_rust(LLVMRustSynchronizationScope scope) case LLVMRustSynchronizationScope::CrossThread: return CrossThread; default: - abort(); + llvm_unreachable("bad SynchronizationScope."); } } @@ -281,15 +281,34 @@ extern "C" void LLVMRustSetDebug(int Enabled) { #endif } +enum class LLVMRustAsmDialect { + Other, + Att, + Intel, +}; + +static InlineAsm::AsmDialect +from_rust(LLVMRustAsmDialect dialect) +{ + switch (dialect) { + case LLVMRustAsmDialect::Att: + return InlineAsm::AD_ATT; + case LLVMRustAsmDialect::Intel: + return InlineAsm::AD_Intel; + default: + llvm_unreachable("bad AsmDialect."); + } +} + extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, char *Constraints, LLVMBool HasSideEffects, LLVMBool IsAlignStack, - unsigned Dialect) { + LLVMRustAsmDialect Dialect) { return wrap(InlineAsm::get(unwrap(Ty), AsmString, Constraints, HasSideEffects, - IsAlignStack, (InlineAsm::AsmDialect) Dialect)); + IsAlignStack, from_rust(Dialect))); } typedef DIBuilder* LLVMRustDIBuilderRef; @@ -797,35 +816,6 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) { return true; } -enum class LLVMRustDLLStorageClassTypes { - Other, - Default, - DllImport, - DllExport, -}; - -static GlobalValue::DLLStorageClassTypes -from_rust(LLVMRustDLLStorageClassTypes Class) -{ - switch (Class) { - case LLVMRustDLLStorageClassTypes::Default: - return GlobalValue::DefaultStorageClass; - case LLVMRustDLLStorageClassTypes::DllImport: - return GlobalValue::DLLImportStorageClass; - case LLVMRustDLLStorageClassTypes::DllExport: - return GlobalValue::DLLExportStorageClass; - default: - abort(); - } -} - -extern "C" void -LLVMRustSetDLLStorageClass(LLVMValueRef Value, - LLVMRustDLLStorageClassTypes Class) { - GlobalValue *V = unwrap(Value); - V->setDLLStorageClass(from_rust(Class)); -} - // Note that the two following functions look quite similar to the // LLVMGetSectionName function. Sadly, it appears that this function only // returns a char* pointer, which isn't guaranteed to be null-terminated. The @@ -955,10 +945,53 @@ to_rust(DiagnosticKind kind) } } - extern "C" LLVMRustDiagnosticKind LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef di) { return to_rust((DiagnosticKind) unwrap(di)->getKind()); } +// This is kept distinct from LLVMGetTypeKind, because when +// a new type kind is added, the Rust-side enum must be +// updated or UB will result. +extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) { + switch (unwrap(Ty)->getTypeID()) { + case Type::VoidTyID: + return LLVMVoidTypeKind; + case Type::HalfTyID: + return LLVMHalfTypeKind; + case Type::FloatTyID: + return LLVMFloatTypeKind; + case Type::DoubleTyID: + return LLVMDoubleTypeKind; + case Type::X86_FP80TyID: + return LLVMX86_FP80TypeKind; + case Type::FP128TyID: + return LLVMFP128TypeKind; + case Type::PPC_FP128TyID: + return LLVMPPC_FP128TypeKind; + case Type::LabelTyID: + return LLVMLabelTypeKind; + case Type::MetadataTyID: + return LLVMMetadataTypeKind; + case Type::IntegerTyID: + return LLVMIntegerTypeKind; + case Type::FunctionTyID: + return LLVMFunctionTypeKind; + case Type::StructTyID: + return LLVMStructTypeKind; + case Type::ArrayTyID: + return LLVMArrayTypeKind; + case Type::PointerTyID: + return LLVMPointerTypeKind; + case Type::VectorTyID: + return LLVMVectorTypeKind; + case Type::X86_MMXTyID: + return LLVMX86_MMXTypeKind; +#if LLVM_VERSION_MINOR >= 8 + case Type::TokenTyID: + return LLVMTokenTypeKind; +#endif + } + llvm_unreachable("Unhandled TypeID."); +} extern "C" void LLVMRustWriteDebugLocToString( LLVMContextRef C, @@ -971,7 +1004,6 @@ extern "C" void LLVMRustWriteDebugLocToString( DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef) -// FIXME(type-audit): assume this function-pointer type does not change extern "C" void LLVMRustSetInlineAsmDiagnosticHandler( LLVMContextRef C, LLVMContext::InlineAsmDiagHandlerTy H, @@ -1028,8 +1060,6 @@ LLVMRustBuildCleanupRet(LLVMBuilderRef Builder, #endif } -// FIXME: to here. - extern "C" LLVMValueRef LLVMRustBuildCatchPad(LLVMBuilderRef Builder, LLVMValueRef ParentPad, -- cgit 1.4.1-3-g733a5 From 63f0c4de6732b699e2b4ded5fb9a8530a1c8a5ac Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 3 Aug 2016 22:37:57 +0300 Subject: Support removed LLVM intrinsics by invoking its AutoUpgrade mechanism. --- src/rustllvm/PassWrapper.cpp | 8 ++++++++ src/test/run-pass/simd-upgraded.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/test/run-pass/simd-upgraded.rs (limited to 'src/rustllvm/PassWrapper.cpp') diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index e3dcf45cf0f..3a20bb2714e 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -17,6 +17,7 @@ #include "llvm/Support/Host.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/AutoUpgrade.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" @@ -361,10 +362,17 @@ extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { llvm::legacy::FunctionPassManager *P = unwrap(PM); P->doInitialization(); + + // Upgrade all calls to old intrinsics first. + for (Module::iterator I = unwrap(M)->begin(), + E = unwrap(M)->end(); I != E;) + UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove + for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E; ++I) if (!I->isDeclaration()) P->run(*I); + P->doFinalization(); } diff --git a/src/test/run-pass/simd-upgraded.rs b/src/test/run-pass/simd-upgraded.rs new file mode 100644 index 00000000000..821a505c138 --- /dev/null +++ b/src/test/run-pass/simd-upgraded.rs @@ -0,0 +1,30 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that removed LLVM SIMD intrinsics continue +// to work via the "AutoUpgrade" mechanism. + +#![feature(cfg_target_feature, repr_simd)] +#![feature(platform_intrinsics, stmt_expr_attributes)] + +#[repr(simd)] +#[derive(PartialEq, Debug)] +struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); + +fn main() { + #[cfg(target_feature = "sse2")] unsafe { + extern "platform-intrinsic" { + fn x86_mm_min_epi16(x: i16x8, y: i16x8) -> i16x8; + } + assert_eq!(x86_mm_min_epi16(i16x8(0, 1, 2, 3, 4, 5, 6, 7), + i16x8(7, 6, 5, 4, 3, 2, 1, 0)), + i16x8(0, 1, 2, 3, 3, 2, 1, 0)); + }; +} -- cgit 1.4.1-3-g733a5