Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b70a4ee

Browse files
authored
Feat: add LLVM global values. Remove all unsafe dispose calls and all unsafe public API. (#14)
* Added basic implementations for global values * Added Linkage and Visibility * Added documentation
1 parent 05a45b3 commit b70a4ee

File tree

8 files changed

+774
-16
lines changed

8 files changed

+774
-16
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "llvm-lib"
3-
version = "0.6.0"
3+
version = "0.6.1"
44
authors = ["Evgeny Ukhanov <[email protected]>"]
55
description = "LLVM library with safe and flexibility in mind, without over complexity based on LLVM-C API"
66
categories = ["compilers", "development-tools", "development-tools::build-utils"]

src/core/context.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -766,14 +766,13 @@ impl GetRef for DiagnosticInfoRef {
766766
}
767767

768768
impl DiagnosticInfoRef {
769-
/// Return a string representation of the `DiagnosticInfo`. Use
770-
/// [`crate::core::dispose_message`] (`LLVMDisposeMessage`) to free the string.
769+
/// Return a string representation of the `DiagnosticInfo`.
771770
///
772771
/// # Details
773772
///
774773
/// This function wraps the `LLVMGetDiagInfoDescription` function from the LLVM core library. It retrieves a description
775774
/// of the diagnostic information represented by `self` as a `String`. The description provides a human-readable explanation
776-
/// of the diagnostic. After obtaining the string, the memory must be freed using [`crate::core::dispose_message`].
775+
/// of the diagnostic. After obtaining the string, the memory is freed using `LLVMDisposeMessage`.
777776
///
778777
/// # Returns
779778
///
@@ -783,7 +782,7 @@ impl DiagnosticInfoRef {
783782
///
784783
/// # Safety
785784
///
786-
/// This function allocates memory for the string, which must be freed using [`crate::core::dispose_message`].
785+
/// This function allocates memory for the string, which is freed using `LLVMDisposeMessage`.
787786
#[must_use]
788787
pub fn get_description(&self) -> Option<String> {
789788
unsafe {
@@ -793,7 +792,7 @@ impl DiagnosticInfoRef {
793792
}
794793
let value = CStr::new(c_str).to_string();
795794
// Dispose message
796-
crate::core::dispose_message(c_str);
795+
core::LLVMDisposeMessage(c_str);
797796
Some(value)
798797
}
799798
}

src/core/mod.rs

Lines changed: 220 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use crate::CUint;
2-
use llvm_sys::{core, LLVMIntPredicate, LLVMOpcode, LLVMRealPredicate};
2+
use llvm_sys::{
3+
core, LLVMDLLStorageClass, LLVMIntPredicate, LLVMLinkage, LLVMOpcode, LLVMRealPredicate,
4+
LLVMUnnamedAddr, LLVMVisibility,
5+
};
36
use std::fmt::Display;
47
use std::ops::Deref;
58

@@ -42,10 +45,16 @@ impl AddressSpace {
4245
}
4346

4447
/// Dispose LLVM message
45-
/// ## Safety
46-
/// Common function to dispose allocated message
47-
pub unsafe fn dispose_message(message: *mut libc::c_char) {
48-
unsafe { core::LLVMDisposeMessage(message) }
48+
///
49+
/// ## Panics
50+
/// This function is purely informative and panics with a message about the call
51+
/// being unavailable. Since there are no cases in which it can be called in
52+
/// safe code. For raw access, if there is such a need, must be called
53+
/// `LLVMDisposeMessage` directly.
54+
pub fn dispose_message(_message: libc::c_char) {
55+
unreachable!(
56+
"LLVMDisposeMessage is unsafe adn restricted to operated to operate directly for safe code"
57+
);
4958
}
5059

5160
/// LLVM version representation
@@ -559,3 +568,209 @@ impl From<RealPredicate> for LLVMRealPredicate {
559568
}
560569
}
561570
}
571+
572+
/// Represents the linkage types in LLVM for global values.
573+
/// Linkage types determine the visibility and behavior of symbols across different modules and within the same module.
574+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
575+
pub enum Linkage {
576+
/// Externally visible function or variable. Can be linked from another module.
577+
ExternalLinkage,
578+
/// Similar to `ExternalLinkage`, but the symbol may be discarded if not used.
579+
AvailableExternallyLinkage,
580+
/// Keeps one copy of the function or variable when linking, discarding others.
581+
LinkOnceAnyLinkage,
582+
/// Similar to `LinkOnceAnyLinkage`, but the symbol cannot be discarded.
583+
LinkOnceODRLinkage,
584+
/// Same as `LinkOnceODRLinkage`, but with hidden visibility.
585+
LinkOnceODRAutoHideLinkage,
586+
/// Keeps one copy, discarding others, but prefer the local copy.
587+
WeakAnyLinkage,
588+
/// Similar to `WeakAnyLinkage`, but ensures that the symbol is unique and is emitted only once.
589+
WeakODRLinkage,
590+
/// Appending linkage: when linked, multiple definitions of the same variable are concatenated.
591+
AppendingLinkage,
592+
/// Local to the translation unit, not visible outside of it.
593+
InternalLinkage,
594+
/// Similar to `InternalLinkage`, but prevents inlining and other optimizations.
595+
PrivateLinkage,
596+
/// Indicates that the global value should be imported from a DLL.
597+
DLLImportLinkage,
598+
/// Indicates that the global value should be exported to a DLL.
599+
DLLExportLinkage,
600+
/// The global variable or function is merged into the program only if it is used.
601+
ExternalWeakLinkage,
602+
/// A special linkage type used internally by the linker.
603+
GhostLinkage,
604+
/// Common linkage for uninitialized global variables.
605+
CommonLinkage,
606+
/// Linker private linkage, used to indicate a symbol that is internal to the module.
607+
LinkerPrivateLinkage,
608+
/// Weak version of `LinkerPrivateLinkage`.
609+
LinkerPrivateWeakLinkage,
610+
}
611+
612+
impl From<LLVMLinkage> for Linkage {
613+
fn from(linkage: LLVMLinkage) -> Self {
614+
match linkage {
615+
LLVMLinkage::LLVMExternalLinkage => Self::ExternalLinkage,
616+
LLVMLinkage::LLVMAvailableExternallyLinkage => Self::AvailableExternallyLinkage,
617+
LLVMLinkage::LLVMLinkOnceAnyLinkage => Self::LinkOnceAnyLinkage,
618+
LLVMLinkage::LLVMLinkOnceODRLinkage => Self::LinkOnceODRLinkage,
619+
LLVMLinkage::LLVMLinkOnceODRAutoHideLinkage => Self::LinkOnceODRAutoHideLinkage,
620+
LLVMLinkage::LLVMWeakAnyLinkage => Self::WeakAnyLinkage,
621+
LLVMLinkage::LLVMWeakODRLinkage => Self::WeakODRLinkage,
622+
LLVMLinkage::LLVMAppendingLinkage => Self::AppendingLinkage,
623+
LLVMLinkage::LLVMInternalLinkage => Self::InternalLinkage,
624+
LLVMLinkage::LLVMPrivateLinkage => Self::PrivateLinkage,
625+
LLVMLinkage::LLVMDLLImportLinkage => Self::DLLImportLinkage,
626+
LLVMLinkage::LLVMDLLExportLinkage => Self::DLLExportLinkage,
627+
LLVMLinkage::LLVMExternalWeakLinkage => Self::ExternalWeakLinkage,
628+
LLVMLinkage::LLVMGhostLinkage => Self::GhostLinkage,
629+
LLVMLinkage::LLVMCommonLinkage => Self::CommonLinkage,
630+
LLVMLinkage::LLVMLinkerPrivateLinkage => Self::LinkerPrivateLinkage,
631+
LLVMLinkage::LLVMLinkerPrivateWeakLinkage => Self::LinkerPrivateWeakLinkage,
632+
}
633+
}
634+
}
635+
636+
impl From<Linkage> for LLVMLinkage {
637+
fn from(linkage: Linkage) -> Self {
638+
match linkage {
639+
Linkage::ExternalLinkage => Self::LLVMExternalLinkage,
640+
Linkage::AvailableExternallyLinkage => Self::LLVMAvailableExternallyLinkage,
641+
Linkage::LinkOnceAnyLinkage => Self::LLVMLinkOnceAnyLinkage,
642+
Linkage::LinkOnceODRLinkage => Self::LLVMLinkOnceODRLinkage,
643+
Linkage::LinkOnceODRAutoHideLinkage => Self::LLVMLinkOnceODRAutoHideLinkage,
644+
Linkage::WeakAnyLinkage => Self::LLVMWeakAnyLinkage,
645+
Linkage::WeakODRLinkage => Self::LLVMWeakODRLinkage,
646+
Linkage::AppendingLinkage => Self::LLVMAppendingLinkage,
647+
Linkage::InternalLinkage => Self::LLVMInternalLinkage,
648+
Linkage::PrivateLinkage => Self::LLVMPrivateLinkage,
649+
Linkage::DLLImportLinkage => Self::LLVMDLLImportLinkage,
650+
Linkage::DLLExportLinkage => Self::LLVMDLLExportLinkage,
651+
Linkage::ExternalWeakLinkage => Self::LLVMExternalWeakLinkage,
652+
Linkage::GhostLinkage => Self::LLVMGhostLinkage,
653+
Linkage::CommonLinkage => Self::LLVMCommonLinkage,
654+
Linkage::LinkerPrivateLinkage => Self::LLVMLinkerPrivateLinkage,
655+
Linkage::LinkerPrivateWeakLinkage => Self::LLVMLinkerPrivateWeakLinkage,
656+
}
657+
}
658+
}
659+
660+
/// `Visibility` is an enumeration in LLVM that represents the
661+
/// visibility of global values such as functions and global
662+
/// variables. Visibility determines how symbols are treated by
663+
/// the linker and whether they can be seen by other modules or
664+
/// shared libraries.
665+
/// Generally `Visibility` represent access to the symbol after `Linkage`.
666+
/// Useful to compose `Linkage` and `Visibility` to define the symbol behavior.
667+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
668+
pub enum Visibility {
669+
/// Default visibility. The symbol is visible to other modules.
670+
DefaultVisibility,
671+
/// Hidden visibility. The symbol is not visible to other modules or shared libraries.
672+
HiddenVisibility,
673+
/// Protected visibility. The symbol is visible to other modules but cannot be overridden.
674+
ProtectedVisibility,
675+
}
676+
677+
impl From<LLVMVisibility> for Visibility {
678+
fn from(visibility: LLVMVisibility) -> Self {
679+
match visibility {
680+
LLVMVisibility::LLVMDefaultVisibility => Self::DefaultVisibility,
681+
LLVMVisibility::LLVMHiddenVisibility => Self::HiddenVisibility,
682+
LLVMVisibility::LLVMProtectedVisibility => Self::ProtectedVisibility,
683+
}
684+
}
685+
}
686+
687+
impl From<Visibility> for LLVMVisibility {
688+
fn from(visibility: Visibility) -> Self {
689+
match visibility {
690+
Visibility::DefaultVisibility => Self::LLVMDefaultVisibility,
691+
Visibility::HiddenVisibility => Self::LLVMHiddenVisibility,
692+
Visibility::ProtectedVisibility => Self::LLVMProtectedVisibility,
693+
}
694+
}
695+
}
696+
697+
/// Represents the DLL storage classes in LLVM, that specifies how a global value,
698+
/// such as a function or global variable, should be treated with respect to
699+
/// dynamic link libraries (DLLs) on platforms like Windows. The `DLLStorageClass`
700+
/// controls whether a symbol should be imported from a DLL, exported to a DLL, or
701+
/// treated as a normal global symbol.
702+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
703+
pub enum DLLStorageClass {
704+
/// `DefaultStorageClass`: The default storage class. The symbol is not specifically marked for import or export
705+
/// from a DLL. It is treated as a normal global symbol.
706+
DefaultStorageClass,
707+
/// `DLLImportStorageClass`: Specifies that the symbol should be imported from a DLL. This is used when you want
708+
/// to use a function or variable that is defined in another DLL. The linker will ensure that the symbol is correctly
709+
/// imported at runtime.
710+
DLLImportStorageClass,
711+
/// `DLLExportStorageClass`: Specifies that the symbol should be exported to a DLL. This is used when you want to make
712+
/// a function or variable available for use by other modules or executables. The linker will ensure that the symbol is
713+
/// correctly exported and accessible to other programs.
714+
DLLExportStorageClass,
715+
}
716+
717+
impl From<DLLStorageClass> for LLVMDLLStorageClass {
718+
fn from(storage_class: DLLStorageClass) -> Self {
719+
match storage_class {
720+
DLLStorageClass::DefaultStorageClass => Self::LLVMDefaultStorageClass,
721+
DLLStorageClass::DLLImportStorageClass => Self::LLVMDLLImportStorageClass,
722+
DLLStorageClass::DLLExportStorageClass => Self::LLVMDLLExportStorageClass,
723+
}
724+
}
725+
}
726+
727+
impl From<LLVMDLLStorageClass> for DLLStorageClass {
728+
fn from(storage_class: LLVMDLLStorageClass) -> Self {
729+
match storage_class {
730+
LLVMDLLStorageClass::LLVMDefaultStorageClass => Self::DefaultStorageClass,
731+
LLVMDLLStorageClass::LLVMDLLImportStorageClass => Self::DLLImportStorageClass,
732+
LLVMDLLStorageClass::LLVMDLLExportStorageClass => Self::DLLExportStorageClass,
733+
}
734+
}
735+
}
736+
737+
/// Represents the unnamed address attribute for global values in LLVM.
738+
///
739+
/// `UnnamedAddr` is an enumeration that specifies whether a global variable or function's address is significant.
740+
/// This can help LLVM's optimizer determine whether it can merge or duplicate global values with identical content,
741+
/// potentially reducing code size or improving performance.
742+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
743+
pub enum UnnamedAddr {
744+
/// `NoUnnamedAddr`: The address of the global value is significant, and it must be unique.
745+
/// The global variable or function cannot be merged with others, even if they have the same content.
746+
/// This is the default behavior for most global values.
747+
NoUnnamedAddr,
748+
/// `LocalUnnamedAddr`: The address of the global value is not significant within the module, allowing the optimizer
749+
/// to merge or duplicate global values with the same content. However, the address is still unique within the module.
750+
/// This is useful for variables or functions that are only accessed within the same module and do not need a unique address.
751+
LocalUnnamedAddr,
752+
/// `GlobalUnnamedAddr`: The address of the global value is not significant across the entire program, allowing the optimizer
753+
/// to freely merge or duplicate global values with identical content across different modules.
754+
/// This can lead to more aggressive optimizations and is useful for constants or functions that do not rely on having a unique address.
755+
GlobalUnnamedAddr,
756+
}
757+
758+
impl From<UnnamedAddr> for LLVMUnnamedAddr {
759+
fn from(unnamed_addr: UnnamedAddr) -> Self {
760+
match unnamed_addr {
761+
UnnamedAddr::NoUnnamedAddr => Self::LLVMNoUnnamedAddr,
762+
UnnamedAddr::LocalUnnamedAddr => Self::LLVMLocalUnnamedAddr,
763+
UnnamedAddr::GlobalUnnamedAddr => Self::LLVMGlobalUnnamedAddr,
764+
}
765+
}
766+
}
767+
768+
impl From<LLVMUnnamedAddr> for UnnamedAddr {
769+
fn from(unnamed_addr: LLVMUnnamedAddr) -> Self {
770+
match unnamed_addr {
771+
LLVMUnnamedAddr::LLVMNoUnnamedAddr => Self::NoUnnamedAddr,
772+
LLVMUnnamedAddr::LLVMLocalUnnamedAddr => Self::LocalUnnamedAddr,
773+
LLVMUnnamedAddr::LLVMGlobalUnnamedAddr => Self::GlobalUnnamedAddr,
774+
}
775+
}
776+
}

src/core/module.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,22 @@ impl NamedMetadataNodeRef {
9292
}
9393
}
9494

95-
#[derive(Debug)]
95+
#[derive(Debug, Clone)]
9696
pub struct MetadataRef(LLVMMetadataRef);
9797

98+
impl From<LLVMMetadataRef> for MetadataRef {
99+
fn from(metadata: LLVMMetadataRef) -> Self {
100+
Self(metadata)
101+
}
102+
}
103+
104+
impl GetRef for MetadataRef {
105+
type RawRef = LLVMMetadataRef;
106+
fn get_ref(&self) -> Self::RawRef {
107+
self.0
108+
}
109+
}
110+
98111
/// Represents flags that describe information about the module for use by
99112
/// an external entity e.g. the dynamic linker.
100113
#[allow(dead_code)]
@@ -221,6 +234,12 @@ impl Drop for ModuleRef {
221234
}
222235
}
223236

237+
impl From<LLVMModuleRef> for ModuleRef {
238+
fn from(module: LLVMModuleRef) -> Self {
239+
Self(module)
240+
}
241+
}
242+
224243
impl GetRef for ModuleRef {
225244
type RawRef = LLVMModuleRef;
226245
fn get_ref(&self) -> Self::RawRef {
@@ -418,7 +437,7 @@ impl ModuleRef {
418437
} else {
419438
unsafe {
420439
let error = CStr::new(error_message).to_string();
421-
crate::core::dispose_message(error_message);
440+
core::LLVMDisposeMessage(error_message);
422441
Err(error)
423442
}
424443
}
@@ -433,7 +452,7 @@ impl ModuleRef {
433452
return None;
434453
}
435454
let result = CStr::new(c_str).to_string();
436-
crate::core::dispose_message(c_str);
455+
core::LLVMDisposeMessage(c_str);
437456
Some(result)
438457
}
439458
}

src/core/types/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ impl TypeRef {
226226
return String::new();
227227
}
228228
let rust_string = CStr::new(c_str).to_string();
229-
super::dispose_message(c_str);
229+
core::LLVMDisposeMessage(c_str);
230230
rust_string
231231
}
232232
}

0 commit comments

Comments
 (0)