summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/crate.cpp51
-rw-r--r--src/ast/crate.hpp4
-rw-r--r--src/hir/deserialise.cpp21
-rw-r--r--src/hir/from_ast.cpp4
-rw-r--r--src/hir/hir.hpp3
-rw-r--r--src/hir/serialise.cpp4
-rw-r--r--src/main.cpp52
-rw-r--r--src/resolve/absolute.cpp4
-rw-r--r--src/trans/codegen_c.cpp4
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) {