Skip to content

Add DMLC option to not suppress GCC's Wunused for local variables -- SIMICS-21585 #240

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
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
16 changes: 16 additions & 0 deletions RELEASENOTES-1.4.docu
Original file line number Diff line number Diff line change
Expand Up @@ -521,4 +521,20 @@
This fix is only enabled by default with Simics API version 7 or above.
With version 6 or below it must be explicitly enabled by passing
<tt>--no-compat=shared_logs_on_device</tt> to DMLC.</add-note></build-id>
<build-id value="next"><add-note> Added the <em>discard reference</em>
'<tt>_</tt>' &mdash; a non-value expression which may be used as an assign
target in order to explictly discard the result of an evaluated expression
or return value of a method call <bug number="SIMICS-21584"/>.
Example usage:
<pre>
_ = any_expression;
_ = throwing_method();
(_, x, _) = method_with_multiple_return_values();
</pre>
For backwards compatibility, declared variables and object members are
still allowed to be named '<tt>_</tt>' with Simics API version 6 or below.
Any such declaration will <em>shadow</em> the discard reference &mdash;
i.e. make it unavailable within the scope that the declaration is
accessible. This compatibility feature can be disabled by passing
<tt>--no-compat=discard_ref_shadowing</tt> to DMLC.</add-note></build-id>
</rn>
27 changes: 27 additions & 0 deletions doc/1.4/language.md
Original file line number Diff line number Diff line change
Expand Up @@ -3808,6 +3808,33 @@ independent method callback(int i, void *aux) {
}
```

### The Discard Reference (`_`)
```
_
```

The discard reference *`_`* is an expression without any run-time representation
that may be used as the target of an assignment in order to explicitly discard
the result of an evaluated expression or return value of a method call.

When the compatibility feature `discard_ref_shadowing` is enabled, `_` is not a
keyword, but instead behaves more closely as a global identifier.
What this means is that declared identifiers (e.g. local variables) are allowed
to shadow it by being named `_`.

Example usage:
```
// Evaluate an expression and explicitly discard its result.
// Can be relevant to e.g. suppress Coverity's CHECKED_RETURN checker
_ = nonthrowing_single_return_method();

// Calls to methods that throw or have multiple return values require a target
// for each return value. `_` can be used to discard return values not of
// interest.
_ = throwing_method();
(_, x, _) = method_with_multiple_return_values();
```

### New Expressions

<pre>
Expand Down
1 change: 1 addition & 0 deletions lib/1.2/dml-builtins.dml
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ template device {
parameter _compat_port_obj_param auto;
parameter _compat_io_memory auto;
parameter _compat_shared_logs_on_device auto;
parameter _compat_discard_ref_shadowing auto;
parameter _compat_dml12_inline auto;
parameter _compat_dml12_not auto;
parameter _compat_dml12_goto auto;
Expand Down
8 changes: 3 additions & 5 deletions lib/1.4/dml-builtins.dml
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ template device {
param _compat_port_obj_param auto;
param _compat_io_memory auto;
param _compat_shared_logs_on_device auto;
param _compat_discard_ref_shadowing auto;
param _compat_dml12_inline auto;
param _compat_dml12_not auto;
param _compat_dml12_goto auto;
Expand Down Expand Up @@ -1848,7 +1849,7 @@ template bank is (object, shown_desc) {
}

shared method _num_registers() -> (uint32) {
local (const register *_, uint64 table_size) = _reginfo_table();
local (const register *_table, uint64 table_size) = _reginfo_table();
return table_size;
}

Expand Down Expand Up @@ -2808,7 +2809,7 @@ template register is (_conf_attribute, get, set, shown_desc,
shared method _size() -> (int) { return this.bitsize / 8; }
shared method _num_fields() -> (uint32) {
local uint32 num_fields = 0;
foreach f in (fields) {
foreach _f in (fields) {
num_fields++;
}
return num_fields;
Expand Down Expand Up @@ -2991,7 +2992,6 @@ template register is (_conf_attribute, get, set, shown_desc,
local uint64 unmapped_bits = unmapped & ~field_bits;
local uint64 val = (this.val & default_access_bits & enabled_bytes);

local int r_lsb = _enabled_bytes_to_offset(enabled_bytes) * 8;
for (local int f = 0; f < num_fields; f++) {
local int f_lsb = fields[f].lsb;
local int f_msb = f_lsb + fields[f].bitsize - 1;
Expand Down Expand Up @@ -3080,8 +3080,6 @@ template register is (_conf_attribute, get, set, shown_desc,
return;
}

local int r_lsb = _enabled_bytes_to_offset(enabled_bytes) * 8;
local int r_msb = _enabled_bytes_to_size(enabled_bytes) * 8 - 1;
for (local int f = 0; f < num_fields; f++) {
local int f_lsb = fields[f].lsb;
local int f_msb = f_lsb + fields[f].bitsize - 1;
Expand Down
62 changes: 27 additions & 35 deletions py/dml/c_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -1837,7 +1837,7 @@ def generate_init_data_objs(device):
start_function_definition(
'void _init_data_objs(%s *_dev)' % (crep.structtype(device),))
out('{\n', postindent = 1)
with crep.DeviceInstanceContext():
with crep.DeviceInstanceContext(), allow_linemarks():
for node in device.initdata:
# Usually, the initializer is constant, but we permit that it
# depends on index. When the initializer is constant, we use a loop
Expand All @@ -1859,37 +1859,39 @@ def generate_init_data_objs(device):
# mainly meant to capture EIDXVAR; for other errors, the error will
# normally re-appear when evaluating per instance
except DMLError:
with allow_linemarks():
for indices in node.all_indices():
index_exprs = tuple(mkIntegerLiteral(node.site, i)
for i in indices)
nref = mkNodeRef(node.site, node, index_exprs)
try:
init = eval_initializer(
node.site, node._type, node.astinit,
Location(node.parent, index_exprs),
global_scope, True)
except DMLError as e:
report(e)
else:
markers = ([('store_writes_const_field', 'FALSE')]
if deep_const(node._type) else [])
coverity_markers(markers, init.site)
init.assign_to(nref, node._type)
for indices in node.all_indices():
index_exprs = tuple(mkIntegerLiteral(node.site, i)
for i in indices)
nref = mkNodeRef(node.site, node, index_exprs)
try:
init = eval_initializer(
node.site, node._type, node.astinit,
Location(node.parent, index_exprs),
global_scope, True)
except DMLError as e:
report(e)
else:
markers = ([('store_writes_const_field', 'FALSE')]
if deep_const(node._type) else [])
coverity_markers(markers, init.site)
out(init.assign_to(nref.read(), node._type) + ';\n')
else:
index_exprs = ()
if node.dimensions:
reset_line_directive()
for (i, sz) in enumerate(node.dimsizes):
var = 'i%d' % (i,)
out(('for (int %s = 0; %s < %s; ++%s) {\n'
% (var, var, sz, var)),
postindent=1)
index_exprs += (mkLit(node.site, var, TInt(64, True)),)
nref = mkNodeRef(node.site, node, index_exprs)
with allow_linemarks():
markers = ([('store_writes_const_field', 'FALSE')]
if deep_const(node._type) else [])
coverity_markers(markers, init.site)
init.assign_to(nref, node._type)
markers = ([('store_writes_const_field', 'FALSE')]
if deep_const(node._type) else [])
coverity_markers(markers, init.site)
out(init.assign_to(nref.read(), node._type) + ';\n')
if node.dimensions:
reset_line_directive()
for _ in range(node.dimensions):
out('}\n', postindent=-1)
out('}\n\n', preindent = -1)
Expand Down Expand Up @@ -3120,12 +3122,7 @@ def generate_startup_trait_calls(data, idxvars):
ref = ObjTraitRef(site, node, trait, indices)
out(f'_tref = {ref.read()};\n')
for method in trait_methods:
outargs = [mkLit(method.site,
('*((%s) {0})'
% ((TArray(t, mkIntegerLiteral(method.site, 1))
.declaration('')),)),
t)
for (_, t) in method.outp]
outargs = [mkDiscardRef(method.site) for _ in method.outp]

method_ref = TraitMethodDirect(
method.site, mkLit(method.site, '_tref', TTrait(trait)), method)
Expand All @@ -3137,12 +3134,7 @@ def generate_startup_trait_calls(data, idxvars):
def generate_startup_regular_call(method, idxvars):
site = method.site
indices = tuple(mkLit(site, idx, TInt(32, False)) for idx in idxvars)
outargs = [mkLit(site,
('*((%s) {0})'
% ((TArray(t, mkIntegerLiteral(site, 1))
.declaration('')),)),
t)
for (_, t) in method.outp]
outargs = [mkDiscardRef(method.site) for _ in method.outp]
# startup memoized methods can throw, which is ignored during startup.
# Memoization of the throw then allows for the user to check whether
# or not the method did throw during startup by calling the method
Expand Down
Loading