diff options
-rw-r--r-- | src/ast/crate.cpp | 51 | ||||
-rw-r--r-- | src/ast/crate.hpp | 4 | ||||
-rw-r--r-- | src/hir/deserialise.cpp | 21 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 4 | ||||
-rw-r--r-- | src/hir/hir.hpp | 3 | ||||
-rw-r--r-- | src/hir/serialise.cpp | 4 | ||||
-rw-r--r-- | src/main.cpp | 52 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 4 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 4 |
9 files changed, 108 insertions, 39 deletions
diff --git a/src/ast/crate.cpp b/src/ast/crate.cpp index f003a00b..d6992ca4 100644 --- a/src/ast/crate.cpp +++ b/src/ast/crate.cpp @@ -55,10 +55,10 @@ void Crate::load_externs() for( const auto& it : mod.items() ) { TU_IFLET(AST::Item, it.data, Crate, c, - const auto& name = c.name; + auto name = c.name; if( check_item_cfg(it.data.attrs) ) { - load_extern_crate( it.data.span, name ); + name = load_extern_crate( it.data.span, name ); } ) } @@ -93,19 +93,23 @@ void Crate::load_externs() // Don't load anything } else if( no_std ) { - this->load_extern_crate(Span(), "core"); + auto n = this->load_extern_crate(Span(), "core"); + ASSERT_BUG(Span(), n == "core", "libcore wasn't loaded as `core`, instead `" << n << "`"); } else { - this->load_extern_crate(Span(), "std"); + auto n = this->load_extern_crate(Span(), "std"); + ASSERT_BUG(Span(), n == "std", "libstd wasn't loaded as `std`, instead `" << n << "`"); } } -void Crate::load_extern_crate(Span sp, const ::std::string& name) +// TODO: Handle disambiguating crates with the same name (e.g. libc in std and crates.io libc) +// - Crates recorded in rlibs should specify a hash/tag that's passed in to this function. +::std::string Crate::load_extern_crate(Span sp, const ::std::string& name, const ::std::string& basename/*=""*/) { DEBUG("Loading crate '" << name << "'"); ::std::string path; auto it = g_crate_overrides.find(name); - if(it != g_crate_overrides.end()) + if(basename == "" && it != g_crate_overrides.end()) { path = it->second; } @@ -114,28 +118,55 @@ void Crate::load_extern_crate(Span sp, const ::std::string& name) // Search a list of load paths for the crate for(const auto& p : g_crate_load_dirs) { - path = p + "/lib" + name + ".hir"; + if( basename == "" ) + { + path = p + "/lib" + name + ".hir"; + // TODO: Search for `p+"/lib"+name+"-*.hir" (which would match e.g. libnum-0.11.hir) + } + else + { + path = p + "/" + basename; + } if( ::std::ifstream(path).good() ) { break ; } + // TODO: Search for `p+"/lib"+name+"-*.hir" (which would match e.g. libnum-0.11.hir) } } if( !::std::ifstream(path).good() ) { - ERROR(sp, E0000, "Unable to locate crate '" << name << "'"); + if( basename.empty() ) + ERROR(sp, E0000, "Unable to locate crate '" << name << "'"); + else + ERROR(sp, E0000, "Unable to locate crate '" << name << "' with filename " << basename); } + // NOTE: Creating `ExternCrate` loads the crate from the specified path auto res = m_extern_crates.insert(::std::make_pair( name, ExternCrate { name, path } )); - auto crate_ext_list = mv$( res.first->second.m_hir->m_ext_crates ); + if( !res.second ) { + // Crate already loaded? + } + auto& ext_crate = res.first->second; + // Move the external list out (doesn't need to be kept in the nested crate) + auto crate_ext_list = mv$( ext_crate.m_hir->m_ext_crates ); // Load referenced crates for( const auto& ext : crate_ext_list ) { if( m_extern_crates.count(ext.first) == 0 ) { - this->load_extern_crate(sp, ext.first); + const auto load_name = this->load_extern_crate(sp, ext.first, ext.second.m_basename); + if( load_name != ext.first ) + { + // ERROR - The crate loaded wasn't the one that was used when compiling this crate. + ERROR(sp, E0000, "The crate file `" << ext.second.m_basename << "` didn't load the expected crate - have " << load_name << " != exp " << ext.first); + } } } + + assert(!ext_crate.m_hir->m_crate_name.empty()); + DEBUG("Loaded '" << name << "' from '" << basename << "' (actual name is '" << ext_crate.m_hir->m_crate_name << "')"); + return ext_crate.m_hir->m_crate_name; } ExternCrate::ExternCrate(const ::std::string& name, const ::std::string& path): diff --git a/src/ast/crate.hpp b/src/ast/crate.hpp index 53dea1b9..4fd5c421 100644 --- a/src/ast/crate.hpp +++ b/src/ast/crate.hpp @@ -67,7 +67,9 @@ public: /// Load referenced crates void load_externs(); - void load_extern_crate(Span sp, const ::std::string& name); + /// Load the named crate and returns the crate's unique name + /// If the parameter `file` is non-empty, only that particular filename will be loaded (from any of the search paths) + ::std::string load_extern_crate(Span sp, const ::std::string& name, const ::std::string& file=""); }; /// Representation of an imported crate diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 1eccfcac..b9d87bfa 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -23,11 +23,10 @@ namespace { class HirDeserialiser { - const ::std::string& m_crate_name; + ::std::string m_crate_name; ::HIR::serialise::Reader& m_in; public: - HirDeserialiser(const ::std::string& crate_name, ::HIR::serialise::Reader& in): - m_crate_name( crate_name ), + HirDeserialiser(::HIR::serialise::Reader& in): m_in(in) {} @@ -227,7 +226,10 @@ namespace { rv.m_rules = deserialise_vec_c< ::MacroRulesArm>( [&](){ return deserialise_macrorulesarm(); }); rv.m_source_crate = m_in.read_string(); if(rv.m_source_crate == "") + { + assert(!m_crate_name.empty()); rv.m_source_crate = m_crate_name; + } return rv; } ::MacroPatEnt deserialise_macropatent() { @@ -770,7 +772,10 @@ namespace { auto crate_name = m_in.read_string(); auto components = deserialise_vec< ::std::string>(); if( crate_name == "" && components.size() > 0) + { + assert(!m_crate_name.empty()); crate_name = m_crate_name; + } return ::HIR::SimplePath { mv$(crate_name), mv$(components) @@ -1119,6 +1124,9 @@ namespace { { ::HIR::Crate rv; + this->m_crate_name = m_in.read_string(); + assert(!this->m_crate_name.empty() && "Empty crate name loaded from metadata"); + rv.m_crate_name = this->m_crate_name; rv.m_root_module = deserialise_module(); rv.m_type_impls = deserialise_vec< ::HIR::TypeImpl>(); @@ -1148,7 +1156,10 @@ namespace { for(size_t i = 0; i < n; i ++) { auto ext_crate_name = m_in.read_string(); - rv.m_ext_crates.insert( ::std::make_pair(ext_crate_name, ::HIR::ExternCrate{}) ); + auto ext_crate_file = m_in.read_string(); + auto ext_crate = ::HIR::ExternCrate {}; + ext_crate.m_basename = ext_crate_file; + rv.m_ext_crates.insert( ::std::make_pair( mv$(ext_crate_name), mv$(ext_crate) ) ); } } @@ -1164,7 +1175,7 @@ namespace { try { ::HIR::serialise::Reader in{ filename }; - HirDeserialiser s { loaded_name, in }; + HirDeserialiser s { in }; ::HIR::Crate rv = s.deserialise_crate(); diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index b005f79b..50e4a290 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -1619,7 +1619,9 @@ public: ERROR(sp, E0000, "Conflicting definitions of lang item '" << name << "'. " << path << " and " << irv.first->second); } } - rv.m_ext_crates.insert( ::std::make_pair( ext_crate.first, ::HIR::ExternCrate { mv$(ext_crate.second.m_hir), ext_crate.second.m_filename } ) ); + auto p = ext_crate.second.m_filename.find('/'); + auto crate_file = (p == ::std::string::npos ? ext_crate.second.m_filename : ext_crate.second.m_filename.substr(p+1)); + rv.m_ext_crates.insert( ::std::make_pair( ext_crate.first, ::HIR::ExternCrate { mv$(ext_crate.second.m_hir), crate_file, ext_crate.second.m_filename } ) ); } path_Sized = rv.get_lang_item_path(sp, "sized"); diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index fc928348..cc34c227 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -438,7 +438,8 @@ class ExternCrate { public: ::HIR::CratePtr m_data; - ::std::string m_filename; + ::std::string m_basename; // Just the filename (serialised) + ::std::string m_path; // The path used to load this crate }; class ExternLibrary { diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index f5c07c35..cac6b3c9 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -239,6 +239,7 @@ namespace { void serialise_crate(const ::HIR::Crate& crate) { + m_out.write_string(crate.m_crate_name); serialise_module(crate.m_root_module); m_out.write_count(crate.m_type_impls.size()); @@ -261,7 +262,10 @@ namespace { m_out.write_count(crate.m_ext_crates.size()); for(const auto& ext : crate.m_ext_crates) + { m_out.write_string(ext.first); + m_out.write_string(ext.second.m_basename); + } serialise_vec(crate.m_ext_libs); serialise_vec(crate.m_link_paths); } diff --git a/src/main.cpp b/src/main.cpp index c159ca4b..fb229a0c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -147,7 +147,6 @@ struct ProgramParams ::std::string outfile; ::std::string output_dir = ""; ::std::string target = DEFAULT_TARGET_NAME; - const char *crate_path = "."; ::AST::Crate::Type crate_type = ::AST::Crate::Type::Unknown; ::std::string crate_name; @@ -159,6 +158,7 @@ struct ProgramParams ::std::vector<const char*> lib_search_dirs; ::std::vector<const char*> libraries; + ::std::map<::std::string, ::std::string> crate_overrides; // --extern name=path ::std::set< ::std::string> features; @@ -227,6 +227,7 @@ int main(int argc, char *argv[]) // Load external crates. CompilePhaseV("LoadCrates", [&]() { // Hacky! + AST::g_crate_overrides = params.crate_overrides; for(const auto& ld : params.lib_search_dirs) { AST::g_crate_load_dirs.push_back(ld); @@ -580,12 +581,7 @@ int main(int argc, char *argv[]) // ::std::cerr << "Internal Compiler Error: " << e << ::std::endl; // return 2; //} - - // TODO: Make this conditional -#if 0 - ::std::cout << "Press enter to exit..." << ::std::endl; - ::std::cin.get(); -#endif + return 0; } @@ -605,6 +601,8 @@ ProgramParams::ProgramParams(int argc, char *argv[]) else { // TODO: Error + ::std::cerr << "Unexpected free argument" << ::std::endl; + exit(1); } } else if( arg[1] != '-' ) @@ -616,7 +614,7 @@ ProgramParams::ProgramParams(int argc, char *argv[]) case 'L': if( arg[1] == '\0' ) { if( i == argc - 1 ) { - // TODO: BAIL! + ::std::cerr << "Option " << arg << " requires an argument" << ::std::endl; exit(1); } this->lib_search_dirs.push_back( argv[++i] ); @@ -628,7 +626,7 @@ ProgramParams::ProgramParams(int argc, char *argv[]) case 'l': if( arg[1] == '\0' ) { if( i == argc - 1 ) { - // TODO: BAIL! + ::std::cerr << "Option " << arg << " requires an argument" << ::std::endl; exit(1); } this->libraries.push_back( argv[++i] ); @@ -641,6 +639,7 @@ ProgramParams::ProgramParams(int argc, char *argv[]) ::std::string optname; if( arg[1] == '\0' ) { if( i == argc - 1) { + ::std::cerr << "Option " << arg << " requires an argument" << ::std::endl; exit(1); } optname = argv[++i]; @@ -675,7 +674,7 @@ ProgramParams::ProgramParams(int argc, char *argv[]) // "-o <file>" : Set output file case 'o': if( i == argc - 1 ) { - // TODO: BAIL! + ::std::cerr << "Option -" << *arg << " requires an argument" << ::std::endl; exit(1); } this->outfile = argv[++i]; @@ -693,13 +692,10 @@ ProgramParams::ProgramParams(int argc, char *argv[]) } else { - if( strcmp(arg, "--crate-path") == 0 ) { - if( i == argc - 1 ) { - ::std::cerr << "Flag --crate-path requires an argument" << ::std::endl; - exit(1); - } - this->crate_path = argv[++i]; + if( strcmp(arg, "--help") == 0 ) { + // TODO: Help } + // --out-dir <dir> >> Set the output directory for automatically-named files else if (strcmp(arg, "--out-dir") == 0) { if (i == argc - 1) { ::std::cerr << "Flag " << arg << " requires an argument" << ::std::endl; @@ -712,6 +708,24 @@ ProgramParams::ProgramParams(int argc, char *argv[]) if( this->output_dir.back() != '/' ) this->output_dir += '/'; } + // --extern <name>=<path> >> Override the file to load for `extern crate <name>;` + else if( strcmp(arg, "--extern") == 0 ) { + if( i == argc - 1 ) { + ::std::cerr << "Option " << arg << " requires an argument" << ::std::endl; + exit(1); + } + const char* desc = argv[++i]; + auto* pos = ::std::strchr(desc, '='); + if( pos == nullptr ) { + ::std::cerr << "--extern takes an argument of the format name=path" << ::std::endl; + exit(1); + } + + auto name = ::std::string(desc, pos); + auto path = ::std::string(pos+1); + this->crate_overrides.insert(::std::make_pair( mv$(name), mv$(path) )); + } + // --crate-name <name> >> Specify the crate name (overrides `#![crate_name="<name>"]`) else if( strcmp(arg, "--crate-name") == 0 ) { if( i == argc - 1 ) { ::std::cerr << "Flag --crate-name requires an argument" << ::std::endl; @@ -720,6 +734,7 @@ ProgramParams::ProgramParams(int argc, char *argv[]) const char* name_str = argv[++i]; this->crate_name = name_str; } + // `--crate-type <name>` - Specify the crate type (overrides `#![crate_type="<name>"]`) else if( strcmp(arg, "--crate-type") == 0 ) { if( i == argc - 1 ) { ::std::cerr << "Flag --crate-type requires an argument" << ::std::endl; @@ -738,6 +753,8 @@ ProgramParams::ProgramParams(int argc, char *argv[]) exit(1); } } + // `--cfg <flag>` + // `--cfg <var>=<value>` else if( strcmp(arg, "--cfg") == 0 ) { if( i == argc - 1 ) { ::std::cerr << "Flag --cfg requires an argument" << ::std::endl; @@ -770,6 +787,7 @@ ProgramParams::ProgramParams(int argc, char *argv[]) Cfg_SetFlag(opt_and_val); } } + // `--target <triple>` - Override the default compiler target else if( strcmp(arg, "--target") == 0 ) { if (i == argc - 1) { ::std::cerr << "Flag " << arg << " requires an argument" << ::std::endl; @@ -777,6 +795,8 @@ ProgramParams::ProgramParams(int argc, char *argv[]) } this->target = argv[++i]; } + // `--stop-after <stage>` - Stops the compiler after the specified stage + // TODO: Convert this to a `-Z` option else if( strcmp(arg, "--stop-after") == 0 ) { if( i == argc - 1 ) { ::std::cerr << "Flag --stop-after requires an argument" << ::std::endl; diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index f21dc77d..cee4df7e 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -785,7 +785,7 @@ namespace { void Resolve_Absolute_Path_BindAbsolute__hir_from(Context& context, const Span& sp, Context::LookupMode& mode, ::AST::Path& path, const AST::ExternCrate& crate, unsigned int start) { - TRACE_FUNCTION_FR(path << " start=" << start, path); + TRACE_FUNCTION_FR( crate.m_hir->m_crate_name << " - " << path << " start=" << start, path); auto& path_abs = path.m_class.as_Absolute(); if( path_abs.nodes.empty() ) { @@ -1009,12 +1009,10 @@ namespace { ), (StructConstructor, auto ty_path = e.ty; - ty_path.m_crate_name = ""; path.bind( ::AST::PathBinding::make_Struct({nullptr, &crate.m_hir->get_struct_by_path(sp, ty_path)}) ); ), (StructConstant, auto ty_path = e.ty; - ty_path.m_crate_name = ""; path.bind( ::AST::PathBinding::make_Struct({nullptr, &crate.m_hir->get_struct_by_path(sp, ty_path)}) ); ), (Static, diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 65152a62..9c4586e6 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -487,7 +487,7 @@ namespace { { for( const auto& crate : m_crate.m_ext_crates ) { - args.push_back(cache_str( crate.second.m_filename + ".o" )); + args.push_back(cache_str( crate.second.m_path + ".o" )); } for(const auto& path : link_dirs ) { @@ -544,7 +544,7 @@ namespace { for( const auto& crate : m_crate.m_ext_crates ) { - args.push_back(cache_str( crate.second.m_filename + ".o" )); + args.push_back(cache_str( crate.second.m_path + ".o" )); } // Crate-specified libraries for(const auto& lib : m_crate.m_ext_libs) { |