From c883463e9481ca58c9c3b0aefe7873c88e2aa4e0 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Tue, 16 Feb 2016 17:07:30 +0100 Subject: [PATCH] Implement feature extraction from `TargetMachine` Add the `LLVMRustHasFeature` function to check whether a `TargetMachine` has a given feature. --- mk/rustllvm.mk | 4 +++ src/librustc_llvm/build.rs | 7 ++++ src/librustc_llvm/lib.rs | 3 ++ src/rustllvm/PassWrapper.cpp | 69 ++++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+) diff --git a/mk/rustllvm.mk b/mk/rustllvm.mk index 6adffda7d1b32..834a11d37fa40 100644 --- a/mk/rustllvm.mk +++ b/mk/rustllvm.mk @@ -43,6 +43,9 @@ $$(RT_OUTPUT_DIR_$(1))/$$(call CFG_STATIC_LIB_NAME_$(1),rustllvm): \ @$$(call E, link: $$@) $$(Q)$$(call CFG_CREATE_ARCHIVE_$(1),$$@) $$^ +RUSTLLVM_COMPONENTS_$(1) = $$(shell echo $$(LLVM_ALL_COMPONENTS_$(1)) |\ + tr 'a-z-' 'A-Z_'| sed -e 's/^ //;s/\([^ ]*\)/\-DLLVM_COMPONENT_\1/g') + # On MSVC we need to double-escape arguments that llvm-config printed which # start with a '/'. The shell we're running in will auto-translate the argument # `/foo` to `C:/msys64/foo` but we really want it to be passed through as `/foo` @@ -51,6 +54,7 @@ $(1)/rustllvm/%.o: $(S)src/rustllvm/%.cpp $$(MKFILE_DEPS) $$(LLVM_CONFIG_$(1)) @$$(call E, compile: $$@) $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@,) \ $$(subst /,//,$$(LLVM_CXXFLAGS_$(1))) \ + $$(RUSTLLVM_COMPONENTS_$(1)) \ $$(EXTRA_RUSTLLVM_CXXFLAGS_$(1)) \ $$(RUSTLLVM_INCS_$(1)) \ $$< diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index dcfb518ba7938..0c6db2cb8ba8d 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -100,6 +100,13 @@ fn main() { } cfg.flag(flag); } + + for component in &components[..] { + let mut flag = String::from("-DLLVM_COMPONENT_"); + flag.push_str(&component.to_uppercase()); + cfg.flag(&flag); + } + cfg.file("../rustllvm/ExecutionEngineWrapper.cpp") .file("../rustllvm/PassWrapper.cpp") .file("../rustllvm/RustWrapper.cpp") diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 4df2da801f925..f28935fbcc2c6 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -2013,6 +2013,9 @@ extern { pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef; pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef); + pub fn LLVMRustHasFeature(T: TargetMachineRef, + s: *const c_char) -> bool; + pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, CPU: *const c_char, Features: *const c_char, diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index d6985719acbfa..b3d4e35d7b09c 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -97,6 +97,75 @@ LLVMRustAddPass(LLVMPassManagerRef PM, Pass *pass) { pm->add(pass); } +#ifdef LLVM_COMPONENT_X86 +#define SUBTARGET_X86 SUBTARGET(X86) +#else +#define SUBTARGET_X86 +#endif + +#ifdef LLVM_COMPONENT_ARM +#define SUBTARGET_ARM SUBTARGET(ARM) +#else +#define SUBTARGET_ARM +#endif + +#ifdef LLVM_COMPONENT_AARCH64 +#define SUBTARGET_AARCH64 SUBTARGET(AArch64) +#else +#define SUBTARGET_AARCH64 +#endif + +#ifdef LLVM_COMPONENT_MIPS +#define SUBTARGET_MIPS SUBTARGET(Mips) +#else +#define SUBTARGET_MIPS +#endif + +#ifdef LLVM_COMPONENT_POWERPC +#define SUBTARGET_PPC SUBTARGET(PPC) +#else +#define SUBTARGET_PPC +#endif + +#define GEN_SUBTARGETS \ + SUBTARGET_X86 \ + SUBTARGET_ARM \ + SUBTARGET_AARCH64 \ + SUBTARGET_MIPS \ + SUBTARGET_PPC + +#define SUBTARGET(x) namespace llvm { \ + extern const SubtargetFeatureKV x##FeatureKV[]; \ + extern const SubtargetFeatureKV x##SubTypeKV[]; \ + } + +GEN_SUBTARGETS +#undef SUBTARGET + +extern "C" bool +LLVMRustHasFeature(LLVMTargetMachineRef TM, + const char *feature) { + TargetMachine *Target = unwrap(TM); + const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); + const FeatureBitset &Bits = MCInfo->getFeatureBits(); + const llvm::SubtargetFeatureKV *FeatureEntry; + +#define SUBTARGET(x) \ + if (MCInfo->isCPUStringValid(x##SubTypeKV[0].Key)) { \ + FeatureEntry = x##FeatureKV; \ + } else + + GEN_SUBTARGETS { + return false; + } +#undef SUBTARGET + + while (strcmp(feature, FeatureEntry->Key) != 0) + FeatureEntry++; + + return (Bits & FeatureEntry->Value) == FeatureEntry->Value; +} + extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(const char *triple, const char *cpu,