Got compiler crash in Mangler::mangleFuncType
Uranuz via Digitalmars-d
digitalmars-d at puremagic.com
Sat Mar 25 04:34:29 PDT 2017
On Saturday, 25 March 2017 at 08:24:04 UTC, Stefan Koch wrote:
> On Saturday, 25 March 2017 at 08:13:08 UTC, Uranuz wrote:
>> On Saturday, 25 March 2017 at 07:57:11 UTC, Stefan Koch wrote:
>>> [...]
>>
>> I just put debug messages on every `assert` and figured out it
>> fails on lines:
>> bool implicit0 = (f.next.ty == Tvoid &&
>> isMain());
>> Type tret = implicit0 ? Type.tint32 :
>> f.next;
>> assert(tret.ty != Tvoid);
>> if (vresult || returnLabel)
>> buildResultVar(scout ? scout : sc2,
>> tret);
>> I really don't understand what it is... Now I cannot share
>> codebase easily. Seems that it fails on my programme `main`
>> function or near that, because compiler stack not so deep.
>> There is some check for isMain AFAIK... What is this about?
>
> are you creating a function called main ?
> that would be about the only time this would be triggered.
Seems that compiler thinks that `struct` constructor returns some
value, but declared type of return value for struct ctor is
Tvoid, so it fails on assert. Printing returns.toChars() after
condition `if (returns)` gives `[return this;`. Maybe `returns`
should be null there or not? I'm very confident that it fails on
constructor. Tried to reduce example manually (I'm not very
confident about Dustmite). But it doesn't reproduce error:
import std.stdio;
struct DirValueAttr(bool isForCompiler = false)
{
string name;
string typeName;
static if( isForCompiler )
{
import ivy.node: IExpression;
IExpression defaultValueExpr;
this( string name, string typeName, IExpression defValue )
{
this.name = name;
this.typeName = typeName;
this.defaultValueExpr = defValue;
}
}
else
{
this( string name, string typeName )
{
this.name = name;
this.typeName = typeName;
}
}
DirValueAttr!(false) toInterpreterValue() {
return DirValueAttr!(false)(name, typeName);
}
}
// We pass callable attributes by blocks. Every attribute block
has size an type
// Size and type stored in single integer argument in stack
preceding the block
// Size is major binary part of this integer denoted by bit
offset:
enum size_t _stackBlockHeaderSizeOffset = 4;
// To have some validity check bit between size and block type
must always be zero
// The following mask is used to check for validity:
enum size_t _stackBlockHeaderCheckMask = 0b1000;
// And there is mask to extract type of block
enum size_t _stackBlockHeaderTypeMask = 0b111;
enum DirAttrKind { NamedAttr, ExprAttr, IdentAttr, KwdAttr,
BodyAttr };
static this()
{
static assert( DirAttrKind.max <= _stackBlockHeaderTypeMask,
`DirAttrKind set of values exeeded of defined limit` );
}
struct DirAttrsBlock(bool isForCompiler = false)
{
import std.typecons: Tuple, tuple;
alias TValueAttr = DirValueAttr!(isForCompiler);
static if( isForCompiler ) {
import ivy.node: ICompoundStatement;
alias TBodyTuple = Tuple!(ICompoundStatement, "ast", bool,
"isNoscope");
}
else {
alias TBodyTuple = Tuple!(bool, "isNoscope");
}
static struct Storage {
union {
TValueAttr[string] namedAttrs;
TValueAttr[] exprAttrs;
string[] names;
string keyword;
TBodyTuple bodyAttr;
}
}
private DirAttrKind _kind;
private Storage _storage;
this( DirAttrKind attrKind, TValueAttr[string] attrs )
{
assert( attrKind == DirAttrKind.NamedAttr, `Expected NamedAttr
kind for attr block` );
_kind = attrKind;
_storage.namedAttrs = attrs;
}
this( DirAttrKind attrKind, TValueAttr[] attrs )
{
assert( attrKind == DirAttrKind.ExprAttr, `Expected ExprAttr
kind for attr block` );
_kind = attrKind;
_storage.exprAttrs = attrs;
}
this( DirAttrKind attrKind, string[] names )
{
assert( attrKind == DirAttrKind.IdentAttr, `Expected IdentAttr
kind for attr block` );
_kind = attrKind;
_storage.names = names;
}
this( DirAttrKind attrKind, string kwd )
{
assert( attrKind == DirAttrKind.KwdAttr, `Expected Keyword kind
for attr block` );
_kind = attrKind;
_storage.keyword = kwd;
}
this( DirAttrKind attrKind, TBodyTuple value )
{
assert( attrKind == DirAttrKind.BodyAttr, `Expected BodyAttr
kind for attr block` );
_kind = attrKind;
_storage.bodyAttr = value;
}
this( DirAttrKind attrKind )
{
_kind = attrKind;
}
DirAttrKind kind() @property {
return _kind;
}
void kind(DirAttrKind value) @property {
_kind = value;
}
void namedAttrs( TValueAttr[string] attrs ) @property {
_storage.namedAttrs = attrs;
_kind = DirAttrKind.NamedAttr;
}
TValueAttr[string] namedAttrs() @property {
assert( _kind == DirAttrKind.NamedAttr, `Directive attrs block
is not of NamedAttr kind` );
return _storage.namedAttrs;
}
void exprAttrs( TValueAttr[] attrs ) @property {
_storage.exprAttrs = attrs;
_kind = DirAttrKind.ExprAttr;
}
TValueAttr[] exprAttrs() @property {
assert( _kind == DirAttrKind.ExprAttr, `Directive attrs block
is not of ExprAttr kind` );
return _storage.exprAttrs;
}
void names(string[] names) @property {
_storage.names = names;
_kind = DirAttrKind.IdentAttr;
}
string[] names() @property {
assert( _kind == DirAttrKind.IdentAttr, `Directive attrs block
is not of IdentAttr kind` );
return _storage.names;
}
void keyword(string value) @property {
_storage.keyword = value;
_kind = DirAttrKind.KwdAttr;
}
string keyword() @property {
assert( _kind == DirAttrKind.KwdAttr, `Directive attrs block is
not of KwdAttr kind` );
return _storage.keyword;
}
void bodyAttr(TBodyTuple value) @property {
_storage.bodyAttr = value;
_kind = DirAttrKind.BodyAttr;
}
TBodyTuple bodyAttr() @property {
assert( _kind == DirAttrKind.BodyAttr, `Directive attrs block
is not of BodyAttr kind` );
return _storage.bodyAttr;
}
DirAttrsBlock!(false) toInterpreterBlock()
{
import std.algorithm: map;
import std.array: array;
final switch( _kind )
{
case DirAttrKind.NamedAttr: {
DirValueAttr!(false)[string] attrs;
foreach( key, ref currAttr; _storage.namedAttrs ) {
attrs[key] = currAttr.toInterpreterValue();
}
return DirAttrsBlock!(false)( _kind, attrs );
}
case DirAttrKind.ExprAttr:
return DirAttrsBlock!(false)( _kind, _storage.exprAttrs.map!(
a => a.toInterpreterValue() ).array );
case DirAttrKind.IdentAttr:
return DirAttrsBlock!(false)( _kind, _storage.names );
case DirAttrKind.KwdAttr:
return DirAttrsBlock!(false)( _kind, _storage.keyword );
case DirAttrKind.BodyAttr:
return DirAttrsBlock!(false)( _kind,
tuple!("isNoscope")(_storage.bodyAttr.isNoscope) );
}
assert( false, `This should never happen` );
}
string toString()
{
import std.conv: to;
final switch( _kind ) with( DirAttrKind )
{
case NamedAttr:
case ExprAttr:
case IdentAttr:
case KwdAttr:
case BodyAttr:
return `<` ~ _kind.to!string ~ ` attrs block>`;
}
}
}
void func() {
DirAttrsBlock!(false)[] _attrBlocks = [
DirAttrsBlock!false( DirAttrKind.NamedAttr, [
"__result__": DirValueAttr!(false)( "__result__", "any" )
]),
DirAttrsBlock!false( DirAttrKind.BodyAttr )
];
}
void main()
{
func();
}
In full project it fails on `this( DirAttrKind attrKind,
TValueAttr[string] attrs )` ctor.
More information about the Digitalmars-d
mailing list