Skip to content

Commit

Permalink
Started replacing cfgs with attribute macro
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDan64 committed Oct 19, 2018
1 parent ac2441a commit 7b328db
Show file tree
Hide file tree
Showing 22 changed files with 134 additions and 54 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Generated by Cargo
# will have compiled files and executables
/target/
internal_macros/target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ either = "1.5"
enum-methods = "0.0.8"
libc = "0.2"
llvm-sys = "70.0"
inkwell_internal_macros = { path = "./internal_macros", version = "0.1.0" }

[badges]
travis-ci = { repository = "TheDan64/inkwell" }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Inkwell aims to help you pen your own programming languages by safely wrapping l

## Requirements

* Any Rust version released in the last year or so
* Rust 1.30+
* Rust Stable, Beta, or Nightly
* LLVM 3.6, 3.7, 3.8, 3.9, 4.0, 5.0, 6.0, or 7

Expand Down
11 changes: 11 additions & 0 deletions internal_macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "inkwell_internal_macros"
version = "0.1.0"
authors = ["Daniel Kolsoi <[email protected]>"]

[dependencies]
syn = { version = "0.15", features = ["full"] }
quote = "0.6"

[lib]
proc-macro = true
67 changes: 67 additions & 0 deletions internal_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! These macros are only intended to be used by inkwell internally
//! and should not be expected to have public support nor stability
extern crate proc_macro;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;

use proc_macro::TokenStream;
use syn::{Arm, Expr, ExprLit, Item, Lit, punctuated::Pair, Pat, PatLit};

// We could include_str! inkwell's Cargo.toml and extract these features
// so that they don't need to also be managed here...
const ALL_FEATURE_VERSIONS: [&str; 8] = [
"llvm3-6",
"llvm3-7",
"llvm3-8",
"llvm3-9",
"llvm4-0",
"llvm5-0",
"llvm6-0",
"llvm7-0",
];

fn panic_with_feature_versions_usage() -> ! {
panic!("feature_version must take the form: \"llvmX-Y\" => (\"llvmX-Y\" || latest)");
}

fn get_latest_feature() -> String {
ALL_FEATURE_VERSIONS[ALL_FEATURE_VERSIONS.len() - 1].into()
}

#[proc_macro_attribute]
pub fn feature_versions(attribute_args: TokenStream, attributee: TokenStream) -> TokenStream {
let arm = parse_macro_input!(attribute_args as Arm);

if arm.pats.len() != 1 {
panic_with_feature_versions_usage();
}

let start_feature = match arm.pats.first().unwrap() {
Pair::End(Pat::Lit(PatLit { expr })) => match **expr {
Expr::Lit(ExprLit { lit: Lit::Str(ref literal_str), .. }) => literal_str.value(),
_ => panic_with_feature_versions_usage(),
},
_ => panic_with_feature_versions_usage(),
};
let end_feature = match *arm.body {
Expr::Lit(ExprLit { lit: Lit::Str(literal_str), .. }) => Some(literal_str.value()),
// We could assert the path is just "latest" but this seems like a lot of extra work...
Expr::Path(_) => None,
_ => panic_with_feature_versions_usage(),
}.unwrap_or_else(get_latest_feature);

let start_index = ALL_FEATURE_VERSIONS.iter().position(|&str| str == start_feature).unwrap();
let end_index = ALL_FEATURE_VERSIONS.iter().position(|&str| str == end_feature).unwrap();
let features = &ALL_FEATURE_VERSIONS[start_index..=end_index];
let attributee: Item = syn::parse(attributee).expect("Could not parse attributed item");

let q = quote! {
#[cfg(any(#(feature = #features),*))]
#attributee
};

q.into()
}
4 changes: 2 additions & 2 deletions src/basic_block.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! A `BasicBlock` is a container of instructions.
use llvm_sys::core::{LLVMGetBasicBlockParent, LLVMGetBasicBlockTerminator, LLVMGetNextBasicBlock, LLVMInsertBasicBlock, LLVMIsABasicBlock, LLVMIsConstant, LLVMMoveBasicBlockAfter, LLVMMoveBasicBlockBefore, LLVMPrintTypeToString, LLVMPrintValueToString, LLVMTypeOf, LLVMDeleteBasicBlock, LLVMGetPreviousBasicBlock, LLVMRemoveBasicBlockFromParent, LLVMGetFirstInstruction, LLVMGetLastInstruction, LLVMGetTypeContext, LLVMBasicBlockAsValue};
#[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8")))]
#[feature_versions("llvm3-9" => latest)]
use llvm_sys::core::LLVMGetBasicBlockName;
use llvm_sys::prelude::{LLVMValueRef, LLVMBasicBlockRef};

Expand Down Expand Up @@ -436,7 +436,7 @@ impl BasicBlock {
///
/// assert_eq!(*bb.get_name(), *CString::new("entry").unwrap());
/// ```
#[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8")))]
#[feature_versions("llvm3-9" => latest)]
pub fn get_name(&self) -> &CStr {
let ptr = unsafe {
LLVMGetBasicBlockName(self.basic_block)
Expand Down
8 changes: 4 additions & 4 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! A `Context` is an opaque owner and manager of core global data.
use llvm_sys::core::{LLVMAppendBasicBlockInContext, LLVMContextCreate, LLVMContextDispose, LLVMCreateBuilderInContext, LLVMDoubleTypeInContext, LLVMFloatTypeInContext, LLVMFP128TypeInContext, LLVMInsertBasicBlockInContext, LLVMInt16TypeInContext, LLVMInt1TypeInContext, LLVMInt32TypeInContext, LLVMInt64TypeInContext, LLVMInt8TypeInContext, LLVMIntTypeInContext, LLVMModuleCreateWithNameInContext, LLVMStructCreateNamed, LLVMStructTypeInContext, LLVMVoidTypeInContext, LLVMHalfTypeInContext, LLVMGetGlobalContext, LLVMPPCFP128TypeInContext, LLVMConstStructInContext, LLVMMDNodeInContext, LLVMMDStringInContext, LLVMGetMDKindIDInContext, LLVMX86FP80TypeInContext, LLVMConstStringInContext, LLVMContextSetDiagnosticHandler};
#[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9")))]
#[feature_versions("llvm4-0" => latest)]
use llvm_sys::core::{LLVMCreateEnumAttribute, LLVMCreateStringAttribute};
use llvm_sys::prelude::{LLVMContextRef, LLVMTypeRef, LLVMValueRef, LLVMDiagnosticInfoRef};
use llvm_sys::ir_reader::LLVMParseIRInContext;
use libc::c_void;

#[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9")))]
#[feature_versions("llvm4-0" => latest)]
use attributes::Attribute;
use basic_block::BasicBlock;
use builder::Builder;
Expand Down Expand Up @@ -733,7 +733,7 @@ impl Context {
///
/// assert!(enum_attribute.is_enum());
/// ```
#[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9")))]
#[feature_versions("llvm4-0" => latest)]
pub fn create_enum_attribute(&self, kind_id: u32, val: u64) -> Attribute {
let attribute = unsafe {
LLVMCreateEnumAttribute(*self.context, kind_id, val)
Expand All @@ -754,7 +754,7 @@ impl Context {
///
/// assert!(string_attribute.is_string());
/// ```
#[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9")))]
#[feature_versions("llvm4-0" => latest)]
pub fn create_string_attribute(&self, key: &str, val: &str) -> Attribute {
let attribute = unsafe {
LLVMCreateStringAttribute(*self.context, key.as_ptr() as *const _, key.len() as u32, val.as_ptr() as *const _, val.len() as u32)
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ extern crate either;
extern crate enum_methods;
extern crate libc;
extern crate llvm_sys;
#[macro_use]
extern crate inkwell_internal_macros;

#[deny(missing_docs)]
#[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8")))]
Expand Down
23 changes: 11 additions & 12 deletions src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use llvm_sys::prelude::{LLVMPassManagerRef, LLVMPassRegistryRef};
use llvm_sys::transforms::ipo::{LLVMAddArgumentPromotionPass, LLVMAddConstantMergePass, LLVMAddDeadArgEliminationPass, LLVMAddFunctionAttrsPass, LLVMAddFunctionInliningPass, LLVMAddAlwaysInlinerPass, LLVMAddGlobalDCEPass, LLVMAddGlobalOptimizerPass, LLVMAddIPConstantPropagationPass, LLVMAddIPSCCPPass, LLVMAddInternalizePass, LLVMAddStripDeadPrototypesPass, LLVMAddPruneEHPass, LLVMAddStripSymbolsPass};
use llvm_sys::transforms::pass_manager_builder::{LLVMPassManagerBuilderRef, LLVMPassManagerBuilderCreate, LLVMPassManagerBuilderDispose, LLVMPassManagerBuilderSetOptLevel, LLVMPassManagerBuilderSetSizeLevel, LLVMPassManagerBuilderSetDisableUnitAtATime, LLVMPassManagerBuilderSetDisableUnrollLoops, LLVMPassManagerBuilderSetDisableSimplifyLibCalls, LLVMPassManagerBuilderUseInlinerWithThreshold, LLVMPassManagerBuilderPopulateFunctionPassManager, LLVMPassManagerBuilderPopulateModulePassManager, LLVMPassManagerBuilderPopulateLTOPassManager};
use llvm_sys::transforms::scalar::{LLVMAddAggressiveDCEPass, LLVMAddMemCpyOptPass, LLVMAddAlignmentFromAssumptionsPass, LLVMAddCFGSimplificationPass, LLVMAddDeadStoreEliminationPass, LLVMAddScalarizerPass, LLVMAddMergedLoadStoreMotionPass, LLVMAddGVNPass, LLVMAddIndVarSimplifyPass, LLVMAddInstructionCombiningPass, LLVMAddJumpThreadingPass, LLVMAddLICMPass, LLVMAddLoopDeletionPass, LLVMAddLoopIdiomPass, LLVMAddLoopRotatePass, LLVMAddLoopRerollPass, LLVMAddLoopUnrollPass, LLVMAddLoopUnswitchPass, LLVMAddPartiallyInlineLibCallsPass, LLVMAddSCCPPass, LLVMAddScalarReplAggregatesPass, LLVMAddScalarReplAggregatesPassSSA, LLVMAddScalarReplAggregatesPassWithThreshold, LLVMAddSimplifyLibCallsPass, LLVMAddTailCallEliminationPass, LLVMAddConstantPropagationPass, LLVMAddDemoteMemoryToRegisterPass, LLVMAddVerifierPass, LLVMAddCorrelatedValuePropagationPass, LLVMAddEarlyCSEPass, LLVMAddLowerExpectIntrinsicPass, LLVMAddTypeBasedAliasAnalysisPass, LLVMAddScopedNoAliasAAPass, LLVMAddBasicAliasAnalysisPass, LLVMAddReassociatePass};
#[cfg(not(feature = "llvm3-6"))]
#[feature_versions("llvm3-7" => latest)]
use llvm_sys::transforms::scalar::LLVMAddBitTrackingDCEPass;
use llvm_sys::transforms::vectorize::{LLVMAddLoopVectorizePass, LLVMAddSLPVectorizePass};

use OptimizationLevel;
use module::Module;
#[cfg(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8"))]
#[feature_versions("llvm3-6" => "llvm3-8")]
use targets::TargetData;
use values::{AsValueRef, FunctionValue};

Expand Down Expand Up @@ -167,7 +167,7 @@ impl PassManager {
}
}

#[cfg(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8"))]
#[feature_versions("llvm3-6" => "llvm3-8")]
pub fn add_target_data(&self, target_data: &TargetData) {
use llvm_sys::target::LLVMAddTargetData;

Expand Down Expand Up @@ -352,8 +352,7 @@ impl PassManager {
/// for each pair of compatible instructions. These heuristics
/// are intended to prevent vectorization in cases where it would
/// not yield a performance increase of the resulting code.
#[cfg(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9", feature = "llvm4-0",
feature = "llvm5-0", feature = "llvm6-0"))]
#[feature_versions("llvm3-6" => "llvm6-0")]
pub fn add_bb_vectorize_pass(&self) {
use llvm_sys::transforms::vectorize::LLVMAddBBVectorizePass;

Expand Down Expand Up @@ -387,7 +386,7 @@ impl PassManager {
}
}

#[cfg(not(feature = "llvm3-6"))]
#[feature_versions("llvm3-7" => latest)]
/// No LLVM documentation is available at this time.
pub fn add_bit_tracking_dce_pass(&self) {
unsafe {
Expand Down Expand Up @@ -449,7 +448,7 @@ impl PassManager {
/// performs redundant load elimination.
// REVIEW: Is `LLVMAddGVNPass` deprecated? Should we just seemlessly replace
// the old one with this one in 4.0+?
#[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9")))]
#[feature_versions("llvm4-0" => latest)]
pub fn add_new_gvn_pass(&self) {
use llvm_sys::transforms::scalar::LLVMAddNewGVNPass;

Expand Down Expand Up @@ -704,9 +703,9 @@ impl PassManager {
/// which allows targets to get away with not implementing the
/// switch instruction until it is convenient.
pub fn add_lower_switch_pass(&self) {
#[cfg(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9", feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0"))]
#[feature_versions("llvm3-6" => "llvm6-0")]
use llvm_sys::transforms::scalar::LLVMAddLowerSwitchPass;
#[cfg(feature = "llvm7-0")]
#[feature_versions("llvm7-0" => latest)]
use llvm_sys::transforms::util::LLVMAddLowerSwitchPass;

unsafe {
Expand All @@ -721,9 +720,9 @@ impl PassManager {
/// order to rewrite loads and stores as appropriate. This is just
/// the standard SSA construction algorithm to construct "pruned" SSA form.
pub fn add_promote_memory_to_register_pass(&self) {
#[cfg(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9", feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0"))]
#[feature_versions("llvm3-6" => "llvm6-0")]
use llvm_sys::transforms::scalar::LLVMAddPromoteMemoryToRegisterPass;
#[cfg(feature = "llvm7-0")]
#[feature_versions("llvm7-0" => latest)]
use llvm_sys::transforms::util::LLVMAddPromoteMemoryToRegisterPass;

unsafe {
Expand Down Expand Up @@ -926,7 +925,7 @@ impl PassManager {
}
}

#[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9")))]
#[feature_versions("llvm4-0" => latest)]
/// No LLVM documentation is available at this time.
pub fn add_early_cse_mem_ssa_pass(&self) {
use llvm_sys::transforms::scalar::LLVMAddEarlyCSEMemSSAPass;
Expand Down
5 changes: 2 additions & 3 deletions src/support/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,9 @@ pub fn is_multithreaded() -> bool {
}

pub fn enable_llvm_pretty_stack_trace() {
#[cfg(any(feature = "llvm3-6", feature = "llvm3-7"))]
#[feature_versions("llvm3-6" => "llvm3-7")]
use llvm_sys::core::LLVMEnablePrettyStackTrace;
#[cfg(any(feature = "llvm3-8", feature = "llvm3-9", feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0",
feature = "llvm7-0"))]
#[feature_versions("llvm3-8" => latest)]
use llvm_sys::error_handling::LLVMEnablePrettyStackTrace;

unsafe {
Expand Down
2 changes: 1 addition & 1 deletion src/types/array_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ impl ArrayType {

// See Type::print_to_stderr note on 5.0+ status
/// Prints the definition of an `ArrayType` to stderr. Not available in newer LLVM versions.
#[cfg(not(any(feature = "llvm3-6", feature = "llvm5-0")))]
#[feature_versions("llvm3-7" => "llvm4-0")]
pub fn print_to_stderr(&self) {
self.array_type.print_to_stderr()
}
Expand Down
2 changes: 1 addition & 1 deletion src/types/float_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ impl FloatType {

// See Type::print_to_stderr note on 5.0+ status
/// Prints the definition of an `IntType` to stderr. Not available in newer LLVM versions.
#[cfg(any(feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9", feature = "llvm4-0"))]
#[feature_versions("llvm3-7" => "llvm4-0")]
pub fn print_to_stderr(&self) {
self.float_type.print_to_stderr()
}
Expand Down
2 changes: 1 addition & 1 deletion src/types/fn_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ impl FunctionType {

// See Type::print_to_stderr note on 5.0+ status
/// Prints the definition of an `IntType` to stderr. Not available in newer LLVM versions.
#[cfg(not(any(feature = "llvm3-6", feature = "llvm5-0")))]
#[feature_versions("llvm3-7" => "llvm4-0")]
pub fn print_to_stderr(&self) {
self.fn_type.print_to_stderr()
}
Expand Down
2 changes: 1 addition & 1 deletion src/types/int_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ impl IntType {

// See Type::print_to_stderr note on 5.0+ status
/// Prints the definition of an `IntType` to stderr. Not available in newer LLVM versions.
#[cfg(any(feature = "llvm3-7", feature = "llvm3-8", feature = "llvm3-9", feature = "llvm4-0"))]
#[feature_versions("llvm3-7" => "llvm4-0")]
pub fn print_to_stderr(&self) {
self.int_type.print_to_stderr()
}
Expand Down
4 changes: 2 additions & 2 deletions src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub use types::vec_type::VectorType;
pub use types::void_type::VoidType;
pub(crate) use types::traits::AsTypeRef;

#[cfg(not(feature = "llvm3-6"))]
#[feature_versions("llvm3-7" => "llvm4-0")]
use llvm_sys::core::LLVMDumpType;
use llvm_sys::core::{LLVMAlignOf, LLVMGetTypeContext, LLVMFunctionType, LLVMArrayType, LLVMGetUndef, LLVMPointerType, LLVMPrintTypeToString, LLVMTypeIsSized, LLVMSizeOf, LLVMVectorType, LLVMConstPointerNull, LLVMGetElementType, LLVMConstNull};
use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef};
Expand Down Expand Up @@ -65,7 +65,7 @@ impl Type {
// and so will fail to link when used. I've decided to remove it from 5.0+
// for now. We should consider removing it altogether since print_to_string
// could be used and manually written to stderr in rust...
#[cfg(not(any(feature = "llvm3-6", feature = "llvm5-0")))]
#[feature_versions("llvm3-7" => "llvm4-0")]
fn print_to_stderr(&self) {
unsafe {
LLVMDumpType(self.type_);
Expand Down
2 changes: 1 addition & 1 deletion src/types/ptr_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ impl PointerType {

// See Type::print_to_stderr note on 5.0+ status
/// Prints the definition of an `IntType` to stderr. Not available in newer LLVM versions.
#[cfg(not(any(feature = "llvm3-6", feature = "llvm5-0")))]
#[feature_versions("llvm3-7" => "llvm4-0")]
pub fn print_to_stderr(&self) {
self.ptr_type.print_to_stderr()
}
Expand Down
2 changes: 1 addition & 1 deletion src/types/struct_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ impl StructType {

// See Type::print_to_stderr note on 5.0+ status
/// Prints the definition of an `StructType` to stderr. Not available in newer LLVM versions.
#[cfg(not(any(feature = "llvm3-6", feature = "llvm5-0")))]
#[feature_versions("llvm3-7" => "llvm4-0")]
pub fn print_to_stderr(&self) {
self.struct_type.print_to_stderr()
}
Expand Down
2 changes: 1 addition & 1 deletion src/types/vec_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ impl VectorType {

// See Type::print_to_stderr note on 5.0+ status
/// Prints the definition of an `IntType` to stderr. Not available in newer LLVM versions.
#[cfg(not(any(feature = "llvm3-6", feature = "llvm5-0")))]
#[feature_versions("llvm3-7" => "llvm4-0")]
pub fn print_to_stderr(&self) {
self.vec_type.print_to_stderr()
}
Expand Down
2 changes: 1 addition & 1 deletion src/types/void_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ impl VoidType {

// See Type::print_to_stderr note on 5.0+ status
/// Prints the definition of a `VoidType` to stderr. Not available in newer LLVM versions.
#[cfg(not(any(feature = "llvm3-6", feature = "llvm5-0")))]
#[feature_versions("llvm3-7" => "llvm4-0")]
pub fn print_to_stderr(&self) {
self.void_type.print_to_stderr()
}
Expand Down
Loading

0 comments on commit 7b328db

Please sign in to comment.