Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 84 additions & 151 deletions solc/CommandLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,39 +51,27 @@ ostream& CommandLineParser::serr()
#define cout
#define cerr

static string const g_strAbi = "abi";
static string const g_strAllowPaths = "allow-paths";
static string const g_strBasePath = "base-path";
static string const g_strIncludePath = "include-path";
static string const g_strAsm = "asm";
static string const g_strAsmJson = "asm-json";
static string const g_strAssemble = "assemble";
static string const g_strAst = "ast";
static string const g_strAstCompactJson = "ast-compact-json";
static string const g_strBinary = "bin";
static string const g_strBinaryRuntime = "bin-runtime";
static string const g_strCombinedJson = "combined-json";
static string const g_strErrorRecovery = "error-recovery";
static string const g_strEVM = "evm";
static string const g_strEVMVersion = "evm-version";
static string const g_strEwasm = "ewasm";
static string const g_strExperimentalViaIR = "experimental-via-ir";
static string const g_strGeneratedSources = "generated-sources";
static string const g_strGeneratedSourcesRuntime = "generated-sources-runtime";
static string const g_strGas = "gas";
static string const g_strHelp = "help";
static string const g_strImportAst = "import-ast";
static string const g_strInputFile = "input-file";
static string const g_strYul = "yul";
static string const g_strYulDialect = "yul-dialect";
static string const g_strIR = "ir";
static string const g_strIROptimized = "ir-optimized";
static string const g_strIPFS = "ipfs";
static string const g_strLicense = "license";
static string const g_strLibraries = "libraries";
static string const g_strLink = "link";
static string const g_strMachine = "machine";
static string const g_strMetadata = "metadata";
static string const g_strMetadataHash = "metadata-hash";
static string const g_strMetadataLiteral = "metadata-literal";
static string const g_strModelCheckerContracts = "model-checker-contracts";
Expand All @@ -93,19 +81,15 @@ static string const g_strModelCheckerShowUnproved = "model-checker-show-unproved
static string const g_strModelCheckerSolvers = "model-checker-solvers";
static string const g_strModelCheckerTargets = "model-checker-targets";
static string const g_strModelCheckerTimeout = "model-checker-timeout";
static string const g_strNatspecDev = "devdoc";
static string const g_strNatspecUser = "userdoc";
static string const g_strNone = "none";
static string const g_strNoOptimizeYul = "no-optimize-yul";
static string const g_strOpcodes = "opcodes";
static string const g_strOptimize = "optimize";
static string const g_strOptimizeRuns = "optimize-runs";
static string const g_strOptimizeYul = "optimize-yul";
static string const g_strYulOptimizations = "yul-optimizations";
static string const g_strOutputDir = "output-dir";
static string const g_strOverwrite = "overwrite";
static string const g_strRevertStrings = "revert-strings";
static string const g_strStorageLayout = "storage-layout";
static string const g_strStopAfter = "stop-after";
static string const g_strParsing = "parsing";

Expand All @@ -118,13 +102,8 @@ static set<string> const g_revertStringsArgs
revertStringsToString(RevertStrings::VerboseDebug)
};

static string const g_strSignatureHashes = "hashes";
static string const g_strSources = "sources";
static string const g_strSourceList = "sourceList";
static string const g_strSrcMap = "srcmap";
static string const g_strSrcMapRuntime = "srcmap-runtime";
static string const g_strFunDebug = "function-debug";
static string const g_strFunDebugRuntime = "function-debug-runtime";
static string const g_strStandardJSON = "standard-json";
static string const g_strStrictAssembly = "strict-assembly";
static string const g_strSwarm = "swarm";
Expand All @@ -136,28 +115,6 @@ static string const g_strColor = "color";
static string const g_strNoColor = "no-color";
static string const g_strErrorIds = "error-codes";

/// Possible arguments to for --combined-json
static set<string> const g_combinedJsonArgs
{
g_strAbi,
g_strAsm,
g_strAst,
g_strBinary,
g_strBinaryRuntime,
g_strFunDebug,
g_strFunDebugRuntime,
g_strGeneratedSources,
g_strGeneratedSourcesRuntime,
g_strMetadata,
g_strNatspecUser,
g_strNatspecDev,
g_strOpcodes,
g_strSignatureHashes,
g_strSrcMap,
g_strSrcMapRuntime,
g_strStorageLayout
};

/// Possible arguments to for --machine
static set<string> const g_machineArgs
{
Expand Down Expand Up @@ -213,54 +170,62 @@ bool CommandLineParser::checkMutuallyExclusive(vector<string> const& _optionName

bool CompilerOutputs::operator==(CompilerOutputs const& _other) const noexcept
{
static_assert(
sizeof(*this) == 15 * sizeof(bool),
"Remember to update code below if you add/remove fields."
);
for (bool CompilerOutputs::* member: componentMap() | ranges::views::values)
if (this->*member != _other.*member)
return false;
return true;
}

return
astCompactJson == _other.astCompactJson &&
asm_ == _other.asm_ &&
asmJson == _other.asmJson &&
opcodes == _other.opcodes &&
binary == _other.binary &&
binaryRuntime == _other.binaryRuntime &&
abi == _other.abi &&
ir == _other.ir &&
irOptimized == _other.irOptimized &&
ewasm == _other.ewasm &&
signatureHashes == _other.signatureHashes &&
natspecUser == _other.natspecUser &&
natspecDev == _other.natspecDev &&
metadata == _other.metadata &&
storageLayout == _other.storageLayout;
ostream& operator<<(ostream& _out, CompilerOutputs const& _selection)
{
vector<string> serializedSelection;
for (auto&& [componentName, component]: CompilerOutputs::componentMap())
if (_selection.*component)
serializedSelection.push_back(CompilerOutputs::componentName(component));

return _out << joinHumanReadable(serializedSelection, ",");
}

string const& CompilerOutputs::componentName(bool CompilerOutputs::* _component)
{
solAssert(_component, "");

// NOTE: Linear search is not optimal but it's simpler than getting pointers-to-members to work as map keys.
for (auto const& [componentName, component]: CompilerOutputs::componentMap())
if (component == _component)
return componentName;

solAssert(false, "");
}

bool CombinedJsonRequests::operator==(CombinedJsonRequests const& _other) const noexcept
{
static_assert(
sizeof(*this) == 17 * sizeof(bool),
"Remember to update code below if you add/remove fields."
);
for (bool CombinedJsonRequests::* member: componentMap() | ranges::views::values)
if (this->*member != _other.*member)
return false;
return true;
}

return
abi == _other.abi &&
metadata == _other.metadata &&
binary == _other.binary &&
binaryRuntime == _other.binaryRuntime &&
opcodes == _other.opcodes &&
asm_ == _other.asm_ &&
storageLayout == _other.storageLayout &&
generatedSources == _other.generatedSources &&
generatedSourcesRuntime == _other.generatedSourcesRuntime &&
srcMap == _other.srcMap &&
srcMapRuntime == _other.srcMapRuntime &&
funDebug == _other.funDebug &&
funDebugRuntime == _other.funDebugRuntime &&
signatureHashes == _other.signatureHashes &&
natspecDev == _other.natspecDev &&
natspecUser == _other.natspecUser &&
ast == _other.ast;

ostream& operator<<(ostream& _out, CombinedJsonRequests const& _requests)
{
vector<string> serializedRequests;
for (auto&& [componentName, component]: CombinedJsonRequests::componentMap())
if (_requests.*component)
serializedRequests.push_back(CombinedJsonRequests::componentName(component));

return _out << joinHumanReadable(serializedRequests, ",");
}

string const& CombinedJsonRequests::componentName(bool CombinedJsonRequests::* _component)
{
solAssert(_component, "");

for (auto const& [componentName, component]: CombinedJsonRequests::componentMap())
if (component == _component)
return componentName;

solAssert(false, "");
}

bool CommandLineOptions::operator==(CommandLineOptions const& _other) const noexcept
Expand Down Expand Up @@ -511,7 +476,7 @@ at standard output or in files in the output directory, if specified.
Imports are automatically read from the filesystem, but it is also possible to
remap paths using the context:prefix=path syntax.
Example:
solc --)" + g_strBinary + R"( -o /tmp/solcoutput dapp-bin=/usr/local/lib/dapp-bin contract.sol
solc --)" + CompilerOutputs::componentName(&CompilerOutputs::binary) + R"( -o /tmp/solcoutput dapp-bin=/usr/local/lib/dapp-bin contract.sol

General Information)").c_str(),
po::options_description::m_default_line_length,
Expand Down Expand Up @@ -578,7 +543,7 @@ General Information)").c_str(),
)
(
g_strRevertStrings.c_str(),
po::value<string>()->value_name(boost::join(g_revertStringsArgs, ",")),
po::value<string>()->value_name(joinHumanReadable(g_revertStringsArgs, ",")),
"Strip revert (and require) reason strings or add additional debugging information."
)
(
Expand Down Expand Up @@ -623,7 +588,7 @@ General Information)").c_str(),
g_strImportAst.c_str(),
("Import ASTs to be compiled, assumes input holds the AST in compact JSON format. "
"Supported Inputs is the output of the --" + g_strStandardJSON + " or the one produced by "
"--" + g_strCombinedJson + " " + g_strAst).c_str()
"--" + g_strCombinedJson + " " + CombinedJsonRequests::componentName(&CombinedJsonRequests::ast)).c_str()
)
;
desc.add(alternativeInputModes);
Expand All @@ -632,12 +597,12 @@ General Information)").c_str(),
assemblyModeOptions.add_options()
(
g_strMachine.c_str(),
po::value<string>()->value_name(boost::join(g_machineArgs, ",")),
po::value<string>()->value_name(joinHumanReadable(g_machineArgs, ",")),
"Target machine in assembly or Yul mode."
)
(
g_strYulDialect.c_str(),
po::value<string>()->value_name(boost::join(g_yulDialectArgs, ",")),
po::value<string>()->value_name(joinHumanReadable(g_yulDialectArgs, ",")),
"Input dialect to use in assembly or yul mode."
)
;
Expand Down Expand Up @@ -683,21 +648,21 @@ General Information)").c_str(),

po::options_description outputComponents("Output Components");
outputComponents.add_options()
(g_strAstCompactJson.c_str(), "AST of all source files in a compact JSON format.")
(g_strAsm.c_str(), "EVM assembly of the contracts.")
(g_strAsmJson.c_str(), "EVM assembly of the contracts in JSON format.")
(g_strOpcodes.c_str(), "Opcodes of the contracts.")
(g_strBinary.c_str(), "Binary of the contracts in hex.")
(g_strBinaryRuntime.c_str(), "Binary of the runtime part of the contracts in hex.")
(g_strAbi.c_str(), "ABI specification of the contracts.")
(g_strIR.c_str(), "Intermediate Representation (IR) of all contracts (EXPERIMENTAL).")
(g_strIROptimized.c_str(), "Optimized intermediate Representation (IR) of all contracts (EXPERIMENTAL).")
(g_strEwasm.c_str(), "Ewasm text representation of all contracts (EXPERIMENTAL).")
(g_strSignatureHashes.c_str(), "Function signature hashes of the contracts.")
(g_strNatspecUser.c_str(), "Natspec user documentation of all contracts.")
(g_strNatspecDev.c_str(), "Natspec developer documentation of all contracts.")
(g_strMetadata.c_str(), "Combined Metadata JSON whose Swarm hash is stored on-chain.")
(g_strStorageLayout.c_str(), "Slots, offsets and types of the contract's state variables.")
(CompilerOutputs::componentName(&CompilerOutputs::astCompactJson).c_str(), "AST of all source files in a compact JSON format.")
(CompilerOutputs::componentName(&CompilerOutputs::asm_).c_str(), "EVM assembly of the contracts.")
(CompilerOutputs::componentName(&CompilerOutputs::asmJson).c_str(), "EVM assembly of the contracts in JSON format.")
(CompilerOutputs::componentName(&CompilerOutputs::opcodes).c_str(), "Opcodes of the contracts.")
(CompilerOutputs::componentName(&CompilerOutputs::binary).c_str(), "Binary of the contracts in hex.")
(CompilerOutputs::componentName(&CompilerOutputs::binaryRuntime).c_str(), "Binary of the runtime part of the contracts in hex.")
(CompilerOutputs::componentName(&CompilerOutputs::abi).c_str(), "ABI specification of the contracts.")
(CompilerOutputs::componentName(&CompilerOutputs::ir).c_str(), "Intermediate Representation (IR) of all contracts (EXPERIMENTAL).")
(CompilerOutputs::componentName(&CompilerOutputs::irOptimized).c_str(), "Optimized intermediate Representation (IR) of all contracts (EXPERIMENTAL).")
(CompilerOutputs::componentName(&CompilerOutputs::ewasm).c_str(), "Ewasm text representation of all contracts (EXPERIMENTAL).")
(CompilerOutputs::componentName(&CompilerOutputs::signatureHashes).c_str(), "Function signature hashes of the contracts.")
(CompilerOutputs::componentName(&CompilerOutputs::natspecUser).c_str(), "Natspec user documentation of all contracts.")
(CompilerOutputs::componentName(&CompilerOutputs::natspecDev).c_str(), "Natspec developer documentation of all contracts.")
(CompilerOutputs::componentName(&CompilerOutputs::metadata).c_str(), "Combined Metadata JSON whose Swarm hash is stored on-chain.")
(CompilerOutputs::componentName(&CompilerOutputs::storageLayout).c_str(), "Slots, offsets and types of the contract's state variables.")
;
desc.add(outputComponents);

Expand All @@ -709,7 +674,7 @@ General Information)").c_str(),
)
(
g_strCombinedJson.c_str(),
po::value<string>()->value_name(boost::join(g_combinedJsonArgs, ",")),
po::value<string>()->value_name(joinHumanReadable(CombinedJsonRequests::componentMap() | ranges::views::keys, ",")),
"Output a single json document containing the specified information."
)
;
Expand All @@ -719,7 +684,7 @@ General Information)").c_str(),
metadataOptions.add_options()
(
g_strMetadataHash.c_str(),
po::value<string>()->value_name(boost::join(g_metadataHashArgs, ",")),
po::value<string>()->value_name(joinHumanReadable(g_metadataHashArgs, ",")),
"Choose hash method for the bytecode metadata or disable it."
)
(
Expand Down Expand Up @@ -889,14 +854,14 @@ bool CommandLineParser::processArgs()
return false;

array<string, 8> const conflictingWithStopAfter{
g_strBinary,
g_strIR,
g_strIROptimized,
g_strEwasm,
CompilerOutputs::componentName(&CompilerOutputs::binary),
CompilerOutputs::componentName(&CompilerOutputs::ir),
CompilerOutputs::componentName(&CompilerOutputs::irOptimized),
CompilerOutputs::componentName(&CompilerOutputs::ewasm),
g_strGas,
g_strAsm,
g_strAsmJson,
g_strOpcodes
CompilerOutputs::componentName(&CompilerOutputs::asm_),
CompilerOutputs::componentName(&CompilerOutputs::asmJson),
CompilerOutputs::componentName(&CompilerOutputs::opcodes),
};

for (auto& option: conflictingWithStopAfter)
Expand Down Expand Up @@ -965,25 +930,8 @@ bool CommandLineParser::processArgs()
m_options.formatting.json.indent = m_args[g_strJsonIndent].as<uint32_t>();
}

static_assert(
sizeof(m_options.compiler.outputs) == 15 * sizeof(bool),
"Remember to update code below if you add/remove fields."
);
m_options.compiler.outputs.astCompactJson = (m_args.count(g_strAstCompactJson) > 0);
m_options.compiler.outputs.asm_ = (m_args.count(g_strAsm) > 0);
m_options.compiler.outputs.asmJson = (m_args.count(g_strAsmJson) > 0);
m_options.compiler.outputs.opcodes = (m_args.count(g_strOpcodes) > 0);
m_options.compiler.outputs.binary = (m_args.count(g_strBinary) > 0);
m_options.compiler.outputs.binaryRuntime = (m_args.count(g_strBinaryRuntime) > 0);
m_options.compiler.outputs.abi = (m_args.count(g_strAbi) > 0);
m_options.compiler.outputs.ir = (m_args.count(g_strIR) > 0);
m_options.compiler.outputs.irOptimized = (m_args.count(g_strIROptimized) > 0);
m_options.compiler.outputs.ewasm = (m_args.count(g_strEwasm) > 0);
m_options.compiler.outputs.signatureHashes = (m_args.count(g_strSignatureHashes) > 0);
m_options.compiler.outputs.natspecUser = (m_args.count(g_strNatspecUser) > 0);
m_options.compiler.outputs.natspecDev = (m_args.count(g_strNatspecDev) > 0);
m_options.compiler.outputs.metadata = (m_args.count(g_strMetadata) > 0);
m_options.compiler.outputs.storageLayout = (m_args.count(g_strStorageLayout) > 0);
for (auto&& [optionName, outputComponent]: CompilerOutputs::componentMap())
m_options.compiler.outputs.*outputComponent = (m_args.count(optionName) > 0);

m_options.compiler.estimateGas = (m_args.count(g_strGas) > 0);

Expand Down Expand Up @@ -1270,30 +1218,15 @@ bool CommandLineParser::parseCombinedJsonOption()

set<string> requests;
for (string const& item: boost::split(requests, m_args[g_strCombinedJson].as<string>(), boost::is_any_of(",")))
if (!g_combinedJsonArgs.count(item))
if (CombinedJsonRequests::componentMap().count(item) == 0)
{
serr() << "Invalid option to --" << g_strCombinedJson << ": " << item << endl;
return false;
}

m_options.compiler.combinedJsonRequests = CombinedJsonRequests{};
m_options.compiler.combinedJsonRequests->abi = (requests.count(g_strAbi) > 0);
m_options.compiler.combinedJsonRequests->metadata = (requests.count("metadata") > 0);
m_options.compiler.combinedJsonRequests->binary = (requests.count(g_strBinary) > 0);
m_options.compiler.combinedJsonRequests->binaryRuntime = (requests.count(g_strBinaryRuntime) > 0);
m_options.compiler.combinedJsonRequests->opcodes = (requests.count(g_strOpcodes) > 0);
m_options.compiler.combinedJsonRequests->asm_ = (requests.count(g_strAsm) > 0);
m_options.compiler.combinedJsonRequests->storageLayout = (requests.count(g_strStorageLayout) > 0);
m_options.compiler.combinedJsonRequests->generatedSources = (requests.count(g_strGeneratedSources) > 0);
m_options.compiler.combinedJsonRequests->generatedSourcesRuntime = (requests.count(g_strGeneratedSourcesRuntime) > 0);
m_options.compiler.combinedJsonRequests->srcMap = (requests.count(g_strSrcMap) > 0);
m_options.compiler.combinedJsonRequests->srcMapRuntime = (requests.count(g_strSrcMapRuntime) > 0);
m_options.compiler.combinedJsonRequests->funDebug = (requests.count(g_strFunDebug) > 0);
m_options.compiler.combinedJsonRequests->funDebugRuntime = (requests.count(g_strFunDebugRuntime) > 0);
m_options.compiler.combinedJsonRequests->signatureHashes = (requests.count(g_strSignatureHashes) > 0);
m_options.compiler.combinedJsonRequests->natspecDev = (requests.count(g_strNatspecDev) > 0);
m_options.compiler.combinedJsonRequests->natspecUser = (requests.count(g_strNatspecUser) > 0);
m_options.compiler.combinedJsonRequests->ast = (requests.count(g_strAst) > 0);
for (auto&& [componentName, component]: CombinedJsonRequests::componentMap())
m_options.compiler.combinedJsonRequests.value().*component = (requests.count(componentName) > 0);

return true;
}
Expand Down
Loading