1
Fork 0

audit LLVM C++ types in ArchiveWrapper and PassWrapper

This commit is contained in:
Ariel Ben-Yehuda 2016-08-02 00:16:16 +03:00 committed by Ariel Ben-Yehuda
parent 81df89fc2d
commit 696691e3c4
8 changed files with 275 additions and 114 deletions

View file

@ -40,13 +40,9 @@ pub use self::TypeKind::*;
pub use self::AtomicBinOp::*; pub use self::AtomicBinOp::*;
pub use self::AtomicOrdering::*; pub use self::AtomicOrdering::*;
pub use self::SynchronizationScope::*; pub use self::SynchronizationScope::*;
pub use self::FileType::*;
pub use self::MetadataType::*; pub use self::MetadataType::*;
pub use self::AsmDialect::*; pub use self::AsmDialect::*;
pub use self::CodeGenOptLevel::*;
pub use self::CodeGenOptSize::*; pub use self::CodeGenOptSize::*;
pub use self::RelocMode::*;
pub use self::CodeGenModel::*;
pub use self::DiagnosticKind::*; pub use self::DiagnosticKind::*;
pub use self::CallConv::*; pub use self::CallConv::*;
pub use self::Visibility::*; pub use self::Visibility::*;
@ -75,9 +71,26 @@ pub type Bool = c_uint;
pub const True: Bool = 1 as Bool; pub const True: Bool = 1 as Bool;
pub const False: Bool = 0 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. // Consts for the LLVM CallConv type, pre-cast to usize.
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
#[repr(C)]
pub enum CallConv { pub enum CallConv {
CCallConv = 0, CCallConv = 0,
FastCallConv = 8, FastCallConv = 8,
@ -89,6 +102,7 @@ pub enum CallConv {
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[repr(C)]
pub enum Visibility { pub enum Visibility {
LLVMDefaultVisibility = 0, LLVMDefaultVisibility = 0,
HiddenVisibility = 1, HiddenVisibility = 1,
@ -100,6 +114,7 @@ pub enum Visibility {
// LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either; // LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
// they've been removed in upstream LLVM commit r203866. // they've been removed in upstream LLVM commit r203866.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
#[repr(C)]
pub enum Linkage { pub enum Linkage {
ExternalLinkage = 0, ExternalLinkage = 0,
AvailableExternallyLinkage = 1, AvailableExternallyLinkage = 1,
@ -337,12 +352,12 @@ pub enum SynchronizationScope {
CrossThread = 1 CrossThread = 1
} }
// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum FileType { pub enum FileType {
AssemblyFileType = 0, Other,
ObjectFileType = 1 AssemblyFile,
ObjectFile,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -371,10 +386,11 @@ pub enum AsmDialect {
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
#[repr(C)] #[repr(C)]
pub enum CodeGenOptLevel { pub enum CodeGenOptLevel {
CodeGenLevelNone = 0, Other,
CodeGenLevelLess = 1, None,
CodeGenLevelDefault = 2, Less,
CodeGenLevelAggressive = 3, Default,
Aggressive,
} }
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
@ -388,21 +404,22 @@ pub enum CodeGenOptSize {
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
#[repr(C)] #[repr(C)]
pub enum RelocMode { pub enum RelocMode {
RelocDefault = 0, Default = 0,
RelocStatic = 1, Static = 1,
RelocPIC = 2, PIC = 2,
RelocDynamicNoPic = 3, DynamicNoPic = 3,
} }
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum CodeGenModel { pub enum CodeModel {
CodeModelDefault = 0, Other,
CodeModelJITDefault = 1, Default,
CodeModelSmall = 2, JITDefault,
CodeModelKernel = 3, Small,
CodeModelMedium = 4, Kernel,
CodeModelLarge = 5, Medium,
Large,
} }
#[repr(C)] #[repr(C)]
@ -421,6 +438,7 @@ pub enum DiagnosticKind {
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum ArchiveKind { pub enum ArchiveKind {
Other,
K_GNU, K_GNU,
K_MIPS64, K_MIPS64,
K_BSD, K_BSD,
@ -444,10 +462,10 @@ impl FromStr for ArchiveKind {
/// Represents the different LLVM passes Rust supports /// Represents the different LLVM passes Rust supports
#[derive(Copy, Clone, PartialEq, Debug)] #[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C)] #[repr(C)]
pub enum SupportedPassKind { pub enum PassKind {
Other,
Function, Function,
Module, Module,
Unsupported,
} }
// Opaque pointer types // Opaque pointer types
@ -2021,7 +2039,7 @@ extern {
pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef; pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
pub fn LLVMIsAConstantInt(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 LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef); pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef);
@ -2031,7 +2049,7 @@ extern {
pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
CPU: *const c_char, CPU: *const c_char,
Features: *const c_char, Features: *const c_char,
Model: CodeGenModel, Model: CodeModel,
Reloc: RelocMode, Reloc: RelocMode,
Level: CodeGenOptLevel, Level: CodeGenOptLevel,
UseSoftFP: bool, UseSoftFP: bool,
@ -2057,7 +2075,8 @@ extern {
PM: PassManagerRef, PM: PassManagerRef,
M: ModuleRef, M: ModuleRef,
Output: *const c_char, Output: *const c_char,
FileType: FileType) -> bool; FileType: FileType)
-> LLVMRustResult;
pub fn LLVMRustPrintModule(PM: PassManagerRef, pub fn LLVMRustPrintModule(PM: PassManagerRef,
M: ModuleRef, M: ModuleRef,
Output: *const c_char); Output: *const c_char);
@ -2123,7 +2142,8 @@ extern {
NumMembers: size_t, NumMembers: size_t,
Members: *const RustArchiveMemberRef, Members: *const RustArchiveMemberRef,
WriteSymbtab: bool, WriteSymbtab: bool,
Kind: ArchiveKind) -> c_int; Kind: ArchiveKind) ->
LLVMRustResult;
pub fn LLVMRustArchiveMemberNew(Filename: *const c_char, pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
Name: *const c_char, Name: *const c_char,
Child: ArchiveChildRef) -> RustArchiveMemberRef; Child: ArchiveChildRef) -> RustArchiveMemberRef;

View file

@ -293,7 +293,7 @@ impl<'a> ArchiveBuilder<'a> {
members.as_ptr(), members.as_ptr(),
self.should_update_symbols, self.should_update_symbols,
kind); kind);
let ret = if r != 0 { let ret = if r.into_result().is_err() {
let err = llvm::LLVMRustGetLastError(); let err = llvm::LLVMRustGetLastError();
let msg = if err.is_null() { let msg = if err.is_null() {
"failed to write archive".to_string() "failed to write archive".to_string()

View file

@ -54,7 +54,7 @@ pub fn write_output_file(
let output_c = path2cstr(output); let output_c = path2cstr(output);
let result = llvm::LLVMRustWriteOutputFile( let result = llvm::LLVMRustWriteOutputFile(
target, pm, m, output_c.as_ptr(), file_type); 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())); 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 { fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
match optimize { match optimize {
config::OptLevel::No => llvm::CodeGenLevelNone, config::OptLevel::No => llvm::CodeGenOptLevel::None,
config::OptLevel::Less => llvm::CodeGenLevelLess, config::OptLevel::Less => llvm::CodeGenOptLevel::Less,
config::OptLevel::Default => llvm::CodeGenLevelDefault, config::OptLevel::Default => llvm::CodeGenOptLevel::Default,
config::OptLevel::Aggressive => llvm::CodeGenLevelAggressive, config::OptLevel::Aggressive => llvm::CodeGenOptLevel::Aggressive,
_ => llvm::CodeGenLevelDefault, _ => llvm::CodeGenOptLevel::Default,
} }
} }
@ -169,11 +169,11 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
}; };
let code_model = match code_model_arg { let code_model = match code_model_arg {
"default" => llvm::CodeModelDefault, "default" => llvm::CodeModel::Default,
"small" => llvm::CodeModelSmall, "small" => llvm::CodeModel::Small,
"kernel" => llvm::CodeModelKernel, "kernel" => llvm::CodeModel::Kernel,
"medium" => llvm::CodeModelMedium, "medium" => llvm::CodeModel::Medium,
"large" => llvm::CodeModelLarge, "large" => llvm::CodeModel::Large,
_ => { _ => {
sess.err(&format!("{:?} is not a valid code model", sess.err(&format!("{:?} is not a valid code model",
sess.opts sess.opts
@ -449,9 +449,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
return false; return false;
} }
let pass_manager = match llvm::LLVMRustPassKind(pass) { let pass_manager = match llvm::LLVMRustPassKind(pass) {
llvm::SupportedPassKind::Function => fpm, llvm::PassKind::Function => fpm,
llvm::SupportedPassKind::Module => mpm, llvm::PassKind::Module => mpm,
llvm::SupportedPassKind::Unsupported => { llvm::PassKind::Other => {
cgcx.handler.err("Encountered LLVM pass kind we can't handle"); cgcx.handler.err("Encountered LLVM pass kind we can't handle");
return true return true
}, },
@ -579,7 +579,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
}; };
with_codegen(tm, llmod, config.no_builtins, |cpm| { with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(cgcx.handler, tm, cpm, llmod, &path, write_output_file(cgcx.handler, tm, cpm, llmod, &path,
llvm::AssemblyFileType); llvm::FileType::AssemblyFile);
}); });
if config.emit_obj { if config.emit_obj {
llvm::LLVMDisposeModule(llmod); llvm::LLVMDisposeModule(llmod);
@ -588,7 +588,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
if write_obj { if write_obj {
with_codegen(tm, llmod, config.no_builtins, |cpm| { 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 // reasonable defaults and prepare it to actually populate the pass
// manager. // manager.
let builder = llvm::LLVMPassManagerBuilderCreate(); 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 opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone);
let inline_threshold = config.inline_threshold; let inline_threshold = config.inline_threshold;
@ -1102,7 +1103,7 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
(_, _, Some(t)) => { (_, _, Some(t)) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32); llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32);
} }
(llvm::CodeGenLevelAggressive, _, _) => { (llvm::CodeGenOptLevel::Aggressive, _, _) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275); llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
} }
(_, llvm::CodeGenOptSizeDefault, _) => { (_, llvm::CodeGenOptSizeDefault, _) => {
@ -1111,15 +1112,18 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
(_, llvm::CodeGenOptSizeAggressive, _) => { (_, llvm::CodeGenOptSizeAggressive, _) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25); llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25);
} }
(llvm::CodeGenLevelNone, _, _) => { (llvm::CodeGenOptLevel::None, _, _) => {
llvm::LLVMRustAddAlwaysInlinePass(builder, false); llvm::LLVMRustAddAlwaysInlinePass(builder, false);
} }
(llvm::CodeGenLevelLess, _, _) => { (llvm::CodeGenOptLevel::Less, _, _) => {
llvm::LLVMRustAddAlwaysInlinePass(builder, true); llvm::LLVMRustAddAlwaysInlinePass(builder, true);
} }
(llvm::CodeGenLevelDefault, _, _) => { (llvm::CodeGenOptLevel::Default, _, _) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225); llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
} }
(llvm::CodeGenOptLevel::Other, _, _) => {
bug!("CodeGenOptLevel::Other selected")
}
} }
f(builder); f(builder);

View file

@ -325,10 +325,10 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
}; };
match reloc_model_arg { match reloc_model_arg {
"pic" => llvm::RelocPIC, "pic" => llvm::RelocMode::PIC,
"static" => llvm::RelocStatic, "static" => llvm::RelocMode::Static,
"default" => llvm::RelocDefault, "default" => llvm::RelocMode::Default,
"dynamic-no-pic" => llvm::RelocDynamicNoPic, "dynamic-no-pic" => llvm::RelocMode::DynamicNoPic,
_ => { _ => {
sess.err(&format!("{:?} is not a valid relocation mode", sess.err(&format!("{:?} is not a valid relocation mode",
sess.opts sess.opts
@ -347,7 +347,7 @@ fn is_any_library(sess: &Session) -> bool {
} }
pub fn is_pie_binary(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) { unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {

View file

@ -16,24 +16,62 @@
using namespace llvm; using namespace llvm;
using namespace llvm::object; using namespace llvm::object;
struct LLVMRustArchiveMember { struct RustArchiveMember {
const char *filename; const char *filename;
const char *name; const char *name;
Archive::Child child; Archive::Child child;
LLVMRustArchiveMember(): filename(NULL), name(NULL), RustArchiveMember(): filename(NULL), name(NULL),
#if LLVM_VERSION_MINOR >= 8 #if LLVM_VERSION_MINOR >= 8
child(NULL, NULL, NULL) child(NULL, NULL, NULL)
#else #else
child(NULL, NULL) child(NULL, NULL)
#endif #endif
{} {}
~LLVMRustArchiveMember() {} ~RustArchiveMember() {}
}; };
typedef OwningBinary<Archive> 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<Archive> *LLVMRustArchiveRef;
typedef RustArchiveMember *LLVMRustArchiveMemberRef;
typedef Archive::Child *LLVMRustArchiveChildRef;
typedef Archive::Child const *LLVMRustArchiveChildConstRef;
typedef RustArchiveIterator *LLVMRustArchiveIteratorRef;
extern "C" LLVMRustArchiveRef
LLVMRustOpenArchive(char *path) { LLVMRustOpenArchive(char *path) {
ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path, ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path,
-1, -1,
@ -66,20 +104,12 @@ LLVMRustOpenArchive(char *path) {
} }
extern "C" void extern "C" void
LLVMRustDestroyArchive(RustArchive *ar) { LLVMRustDestroyArchive(LLVMRustArchiveRef ar) {
delete ar; delete ar;
} }
struct RustArchiveIterator { extern "C" LLVMRustArchiveIteratorRef
Archive::child_iterator cur; LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) {
Archive::child_iterator end;
#if LLVM_VERSION_MINOR >= 9
Error err;
#endif
};
extern "C" RustArchiveIterator*
LLVMRustArchiveIteratorNew(RustArchive *ra) {
Archive *ar = ra->getBinary(); Archive *ar = ra->getBinary();
RustArchiveIterator *rai = new RustArchiveIterator(); RustArchiveIterator *rai = new RustArchiveIterator();
#if LLVM_VERSION_MINOR <= 8 #if LLVM_VERSION_MINOR <= 8
@ -95,8 +125,8 @@ LLVMRustArchiveIteratorNew(RustArchive *ra) {
return rai; return rai;
} }
extern "C" const Archive::Child* extern "C" LLVMRustArchiveChildConstRef
LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) { LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) {
#if LLVM_VERSION_MINOR >= 9 #if LLVM_VERSION_MINOR >= 9
if (rai->err) { if (rai->err) {
LLVMRustSetLastError(toString(std::move(rai->err)).c_str()); LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
@ -122,17 +152,17 @@ LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
} }
extern "C" void extern "C" void
LLVMRustArchiveChildFree(Archive::Child *child) { LLVMRustArchiveChildFree(LLVMRustArchiveChildRef child) {
delete child; delete child;
} }
extern "C" void extern "C" void
LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) { LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef rai) {
delete rai; delete rai;
} }
extern "C" const char* extern "C" const char*
LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) { LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef child, size_t *size) {
ErrorOr<StringRef> name_or_err = child->getName(); ErrorOr<StringRef> name_or_err = child->getName();
if (name_or_err.getError()) if (name_or_err.getError())
return NULL; return NULL;
@ -142,7 +172,7 @@ LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
} }
extern "C" const char* extern "C" const char*
LLVMRustArchiveChildData(Archive::Child *child, size_t *size) { LLVMRustArchiveChildData(LLVMRustArchiveChildRef child, size_t *size) {
StringRef buf; StringRef buf;
ErrorOr<StringRef> buf_or_err = child->getBuffer(); ErrorOr<StringRef> buf_or_err = child->getBuffer();
if (buf_or_err.getError()) { if (buf_or_err.getError()) {
@ -154,9 +184,10 @@ LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
return buf.data(); return buf.data();
} }
extern "C" LLVMRustArchiveMember* extern "C" LLVMRustArchiveMemberRef
LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) { LLVMRustArchiveMemberNew(char *Filename, char *Name,
LLVMRustArchiveMember *Member = new LLVMRustArchiveMember; LLVMRustArchiveChildRef child) {
RustArchiveMember *Member = new RustArchiveMember;
Member->filename = Filename; Member->filename = Filename;
Member->name = Name; Member->name = Name;
if (child) if (child)
@ -165,22 +196,23 @@ LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) {
} }
extern "C" void extern "C" void
LLVMRustArchiveMemberFree(LLVMRustArchiveMember *Member) { LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
delete Member; delete Member;
} }
extern "C" int extern "C" LLVMRustResult
LLVMRustWriteArchive(char *Dst, LLVMRustWriteArchive(char *Dst,
size_t NumMembers, size_t NumMembers,
const LLVMRustArchiveMember **NewMembers, const LLVMRustArchiveMemberRef *NewMembers,
bool WriteSymbtab, bool WriteSymbtab,
Archive::Kind Kind) { LLVMRustArchiveKind rust_kind) {
#if LLVM_VERSION_MINOR <= 8 #if LLVM_VERSION_MINOR <= 8
std::vector<NewArchiveIterator> Members; std::vector<NewArchiveIterator> Members;
#else #else
std::vector<NewArchiveMember> Members; std::vector<NewArchiveMember> Members;
#endif #endif
auto Kind = from_rust(rust_kind);
for (size_t i = 0; i < NumMembers; i++) { for (size_t i = 0; i < NumMembers; i++) {
auto Member = NewMembers[i]; auto Member = NewMembers[i];
@ -190,7 +222,7 @@ LLVMRustWriteArchive(char *Dst,
Expected<NewArchiveMember> MOrErr = NewArchiveMember::getFile(Member->filename, true); Expected<NewArchiveMember> MOrErr = NewArchiveMember::getFile(Member->filename, true);
if (!MOrErr) { if (!MOrErr) {
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str()); LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
return -1; return LLVMRustResult::Failure;
} }
Members.push_back(std::move(*MOrErr)); Members.push_back(std::move(*MOrErr));
#elif LLVM_VERSION_MINOR == 8 #elif LLVM_VERSION_MINOR == 8
@ -205,7 +237,7 @@ LLVMRustWriteArchive(char *Dst,
Expected<NewArchiveMember> MOrErr = NewArchiveMember::getOldMember(Member->child, true); Expected<NewArchiveMember> MOrErr = NewArchiveMember::getOldMember(Member->child, true);
if (!MOrErr) { if (!MOrErr) {
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str()); LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
return -1; return LLVMRustResult::Failure;
} }
Members.push_back(std::move(*MOrErr)); Members.push_back(std::move(*MOrErr));
#endif #endif
@ -217,7 +249,7 @@ LLVMRustWriteArchive(char *Dst,
auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true); auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true);
#endif #endif
if (!pair.second) if (!pair.second)
return 0; return LLVMRustResult::Success;
LLVMRustSetLastError(pair.second.message().c_str()); LLVMRustSetLastError(pair.second.message().c_str());
return -1; return LLVMRustResult::Failure;
} }

View file

@ -54,41 +54,48 @@ LLVMInitializePasses() {
initializeTarget(Registry); initializeTarget(Registry);
} }
enum class LLVMRustPassKind {
enum class SupportedPassKind { Other,
Function, Function,
Module, 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) { LLVMRustFindAndCreatePass(const char *PassName) {
StringRef SR(PassName); StringRef SR(PassName);
PassRegistry *PR = PassRegistry::getPassRegistry(); PassRegistry *PR = PassRegistry::getPassRegistry();
const PassInfo *PI = PR->getPassInfo(SR); const PassInfo *PI = PR->getPassInfo(SR);
if (PI) { if (PI) {
return PI->createPass(); return wrap(PI->createPass());
} }
return NULL; return NULL;
} }
extern "C" SupportedPassKind extern "C" LLVMRustPassKind
LLVMRustPassKind(Pass *pass) { LLVMRustPassKind(LLVMPassRef rust_pass) {
assert(pass); assert(rust_pass);
PassKind passKind = pass->getPassKind(); Pass *pass = unwrap(rust_pass);
if (passKind == PT_Module) { return to_rust(pass->getPassKind());
return SupportedPassKind::Module;
} else if (passKind == PT_Function) {
return SupportedPassKind::Function;
} else {
return SupportedPassKind::Unsupported;
}
} }
extern "C" void extern "C" void
LLVMRustAddPass(LLVMPassManagerRef PM, Pass *pass) { LLVMRustAddPass(LLVMPassManagerRef PM, LLVMPassRef rust_pass) {
assert(pass); assert(rust_pass);
Pass *pass = unwrap(rust_pass);
PassManagerBase *pm = unwrap(PM); PassManagerBase *pm = unwrap(PM);
pm->add(pass); pm->add(pass);
} }
@ -162,13 +169,69 @@ LLVMRustHasFeature(LLVMTargetMachineRef TM,
return (Bits & FeatureEntry->Value) == FeatureEntry->Value; 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 extern "C" LLVMTargetMachineRef
LLVMRustCreateTargetMachine(const char *triple, LLVMRustCreateTargetMachine(const char *triple,
const char *cpu, const char *cpu,
const char *feature, const char *feature,
CodeModel::Model CM, LLVMRustCodeModel rust_CM,
LLVMRelocMode Reloc, LLVMRelocMode Reloc,
CodeGenOpt::Level OptLevel, LLVMRustCodeGenOptLevel rust_OptLevel,
bool UseSoftFloat, bool UseSoftFloat,
bool PositionIndependentExecutable, bool PositionIndependentExecutable,
bool FunctionSections, bool FunctionSections,
@ -179,6 +242,9 @@ LLVMRustCreateTargetMachine(const char *triple,
#else #else
Optional<Reloc::Model> RM; Optional<Reloc::Model> RM;
#endif #endif
auto CM = from_rust(rust_CM);
auto OptLevel = from_rust(rust_OptLevel);
switch (Reloc){ switch (Reloc){
case LLVMRelocStatic: case LLVMRelocStatic:
RM = Reloc::Static; RM = Reloc::Static;
@ -251,14 +317,14 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
extern "C" void extern "C" void
LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB, LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
CodeGenOpt::Level OptLevel, LLVMRustCodeGenOptLevel OptLevel,
bool MergeFunctions, bool MergeFunctions,
bool SLPVectorize, bool SLPVectorize,
bool LoopVectorize) { bool LoopVectorize) {
// Ignore mergefunc for now as enabling it causes crashes. // Ignore mergefunc for now as enabling it causes crashes.
//unwrap(PMB)->MergeFunctions = MergeFunctions; //unwrap(PMB)->MergeFunctions = MergeFunctions;
unwrap(PMB)->SLPVectorize = SLPVectorize; unwrap(PMB)->SLPVectorize = SLPVectorize;
unwrap(PMB)->OptLevel = OptLevel; unwrap(PMB)->OptLevel = from_rust(OptLevel);
unwrap(PMB)->LoopVectorize = LoopVectorize; unwrap(PMB)->LoopVectorize = LoopVectorize;
} }
@ -314,13 +380,33 @@ LLVMRustSetLLVMOptions(int Argc, char **Argv) {
cl::ParseCommandLineOptions(Argc, 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, LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
LLVMPassManagerRef PMR, LLVMPassManagerRef PMR,
LLVMModuleRef M, LLVMModuleRef M,
const char *path, const char *path,
TargetMachine::CodeGenFileType FileType) { LLVMRustFileType rust_FileType) {
llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR); llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
auto FileType = from_rust(rust_FileType);
std::string ErrorInfo; std::string ErrorInfo;
std::error_code EC; std::error_code EC;
@ -329,7 +415,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
ErrorInfo = EC.message(); ErrorInfo = EC.message();
if (ErrorInfo != "") { if (ErrorInfo != "") {
LLVMRustSetLastError(ErrorInfo.c_str()); LLVMRustSetLastError(ErrorInfo.c_str());
return false; return LLVMRustResult::Failure;
} }
unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false); 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 // stream (OS), so the only real safe place to delete this is here? Don't we
// wish this was written in Rust? // wish this was written in Rust?
delete PM; delete PM;
return true; return LLVMRustResult::Success;
} }
extern "C" void extern "C" void

View file

@ -1,2 +1,16 @@
This directory currently contains some LLVM support code. This will generally This directory currently contains some LLVM support code. This will generally
be sent upstream to LLVM in time; for now it lives here. 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.

View file

@ -58,6 +58,11 @@
void LLVMRustSetLastError(const char*); void LLVMRustSetLastError(const char*);
enum class LLVMRustResult {
Success,
Failure
};
typedef struct OpaqueRustString *RustStringRef; typedef struct OpaqueRustString *RustStringRef;
typedef struct LLVMOpaqueTwine *LLVMTwineRef; typedef struct LLVMOpaqueTwine *LLVMTwineRef;
typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef; typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;