diff --git a/changelog/bitfields.dd b/changelog/bitfields.dd new file mode 100644 index 000000000000..40290e3190e4 --- /dev/null +++ b/changelog/bitfields.dd @@ -0,0 +1,21 @@ +Add bit fields to D + +They work just like the bit fields in ImportC do. + +https://github.com/dlang/dlang.org/pull/3190 + +--- +struct B +{ + int x:3, y:2; +} + +static assert(B.sizeof == 4); + +int vaporator(B b) +{ + b.x = 4; + b.y = 2; + return b.x + b.y; // returns 6 +} +--- diff --git a/src/dmd/cli.d b/src/dmd/cli.d index e610d24f7a30..415adb49464e 100644 --- a/src/dmd/cli.d +++ b/src/dmd/cli.d @@ -843,6 +843,7 @@ dmd -cov -unittest myprog.d "implement https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1008.md (@nogc Throwable)"), Feature("dip1021", "useDIP1021", "implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md (Mutable function arguments)"), + Feature("bitfields", "bitfields", "add bitfields https://github.com/dlang/dlang.org/pull/3190"), Feature("fieldwise", "fieldwise", "use fieldwise comparisons for struct equality"), Feature("fixAliasThis", "fixAliasThis", "when a symbol is resolved, check alias this scope before going to upper scopes"), diff --git a/src/dmd/declaration.d b/src/dmd/declaration.d index a533d30ca808..7805a4c2395f 100644 --- a/src/dmd/declaration.d +++ b/src/dmd/declaration.d @@ -1691,6 +1691,32 @@ extern (C++) class BitFieldDeclaration : VarDeclaration v.visit(this); } + /*********************************** + * Retrieve the .min or .max values. + * Only valid after semantic analysis. + * Params: + * id = Id.min or Id.max + * Returns: + * the min or max value + */ + final ulong getMinMax(Identifier id) + { + const width = fieldWidth; + const uns = type.isunsigned(); + const min = id == Id.min; + ulong v; + assert(width != 0); // should have been rejected in semantic pass + if (width == ulong.sizeof * 8) + v = uns ? (min ? ulong.min : ulong.max) + : (min ? long.min : long.max); + else + v = uns ? (min ? 0 + : (1L << width) - 1) + : (min ? -(1L << (width - 1)) + : (1L << (width - 1)) - 1); + return v; + } + override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) { //printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars()); diff --git a/src/dmd/dsymbolsem.d b/src/dmd/dsymbolsem.d index 5415401e0e4d..8053d142d4b5 100644 --- a/src/dmd/dsymbolsem.d +++ b/src/dmd/dsymbolsem.d @@ -1204,6 +1204,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (dsym.errors) return; + if (!dsym.parent.isStructDeclaration() && !dsym.parent.isClassDeclaration()) + { + dsym.error("bit-field must be member of struct, union, or class"); + } + sc = sc.startCTFE(); auto width = dsym.width.expressionSemantic(sc); sc = sc.endCTFE(); diff --git a/src/dmd/expressionsem.d b/src/dmd/expressionsem.d index 22a1f45f4e8b..c016422e69c5 100644 --- a/src/dmd/expressionsem.d +++ b/src/dmd/expressionsem.d @@ -12605,6 +12605,22 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag) Expression e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t); return e; } + else if ((exp.ident == Id.max || exp.ident == Id.min) && + exp.e1.isVarExp() && + exp.e1.isVarExp().var.isBitFieldDeclaration()) + { + // For `x.max` and `x.min` get the max/min of the bitfield, not the max/min of its type + auto bf = exp.e1.isVarExp().var.isBitFieldDeclaration(); + return new IntegerExp(exp.loc, bf.getMinMax(exp.ident), bf.type); + } + else if ((exp.ident == Id.max || exp.ident == Id.min) && + exp.e1.isDotVarExp() && + exp.e1.isDotVarExp().var.isBitFieldDeclaration()) + { + // For `x.max` and `x.min` get the max/min of the bitfield, not the max/min of its type + auto bf = exp.e1.isDotVarExp().var.isBitFieldDeclaration(); + return new IntegerExp(exp.loc, bf.getMinMax(exp.ident), bf.type); + } else if (cfile && exp.ident == Id.__sizeof && exp.e1.isStringExp()) { // Sizeof string literal includes the terminating 0 @@ -12618,7 +12634,9 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag) flag = 0; Expression e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0)); if (e) + { e = e.expressionSemantic(sc); + } return e; } } diff --git a/src/dmd/frontend.h b/src/dmd/frontend.h index c4798121ea91..f415e6866c29 100644 --- a/src/dmd/frontend.h +++ b/src/dmd/frontend.h @@ -507,6 +507,7 @@ struct Param final bool ehnogc; FeatureState dtorFields; bool fieldwise; + bool bitfields; FeatureState rvalueRefParam; CppStdRevision cplusplus; bool markdown; @@ -632,6 +633,7 @@ struct Param final inclusiveInContracts(), ehnogc(), fieldwise(), + bitfields(), cplusplus((CppStdRevision)201103u), markdown(true), vmarkdown(), @@ -705,7 +707,7 @@ struct Param final mapfile() { } - Param(bool obj, bool link = true, bool dll = false, bool lib = false, bool multiobj = false, bool oneobj = false, bool trace = false, bool tracegc = false, bool verbose = false, bool vcg_ast = false, bool showColumns = false, bool vtls = false, bool vtemplates = false, bool vtemplatesListInstances = false, bool vgc = false, bool vfield = false, bool vcomplex = true, bool vin = false, uint8_t symdebug = 0u, bool symdebugref = false, bool optimize = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool stackstomp = false, bool useUnitTests = false, bool useInline = false, FeatureState useDIP25 = (FeatureState)-1, FeatureState useDIP1000 = (FeatureState)-1, bool useDIP1021 = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, PIC pic = (PIC)0u, bool color = false, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool nofloat = false, bool ignoreUnsupportedPragmas = false, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool noSharedAccess = false, bool previewIn = false, bool shortenedMethods = false, bool betterC = false, bool addMain = false, bool allInst = false, bool fix16997 = true, bool fixAliasThis = false, bool inclusiveInContracts = false, bool ehnogc = false, FeatureState dtorFields = (FeatureState)-1, bool fieldwise = false, FeatureState rvalueRefParam = (FeatureState)-1, CppStdRevision cplusplus = (CppStdRevision)201103u, bool markdown = true, bool vmarkdown = false, bool showGaggedErrors = false, bool printErrorContext = false, bool manual = false, bool usage = false, bool mcpuUsage = false, bool transitionUsage = false, bool checkUsage = false, bool checkActionUsage = false, bool revertUsage = false, bool previewUsage = false, bool externStdUsage = false, bool hcUsage = false, bool logo = false, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, uint32_t errorLimit = 20u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, bool doDocComments = false, _d_dynamicArray< const char > docdir = {}, _d_dynamicArray< const char > docname = {}, Array ddocfiles = Array(), bool doHdrGeneration = false, _d_dynamicArray< const char > hdrdir = {}, _d_dynamicArray< const char > hdrname = {}, bool hdrStripPlainFunctions = true, CxxHeaderMode doCxxHdrGeneration = (CxxHeaderMode)0u, _d_dynamicArray< const char > cxxhdrdir = {}, _d_dynamicArray< const char > cxxhdrname = {}, bool doJsonGeneration = false, _d_dynamicArray< const char > jsonfilename = {}, JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, OutBuffer* mixinOut = nullptr, const char* mixinFile = nullptr, int32_t mixinLines = 0, uint32_t debuglevel = 0u, Array* debugids = nullptr, uint32_t versionlevel = 0u, Array* versionids = nullptr, _d_dynamicArray< const char > defaultlibname = {}, _d_dynamicArray< const char > debuglibname = {}, _d_dynamicArray< const char > mscrtlib = {}, _d_dynamicArray< const char > moduleDepsFile = {}, OutBuffer* moduleDeps = nullptr, bool emitMakeDeps = false, _d_dynamicArray< const char > makeDepsFile = {}, Array makeDeps = Array(), MessageStyle messageStyle = (MessageStyle)0u, bool run = false, Array runargs = Array(), Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : + Param(bool obj, bool link = true, bool dll = false, bool lib = false, bool multiobj = false, bool oneobj = false, bool trace = false, bool tracegc = false, bool verbose = false, bool vcg_ast = false, bool showColumns = false, bool vtls = false, bool vtemplates = false, bool vtemplatesListInstances = false, bool vgc = false, bool vfield = false, bool vcomplex = true, bool vin = false, uint8_t symdebug = 0u, bool symdebugref = false, bool optimize = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool stackstomp = false, bool useUnitTests = false, bool useInline = false, FeatureState useDIP25 = (FeatureState)-1, FeatureState useDIP1000 = (FeatureState)-1, bool useDIP1021 = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, PIC pic = (PIC)0u, bool color = false, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool nofloat = false, bool ignoreUnsupportedPragmas = false, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool noSharedAccess = false, bool previewIn = false, bool shortenedMethods = false, bool betterC = false, bool addMain = false, bool allInst = false, bool fix16997 = true, bool fixAliasThis = false, bool inclusiveInContracts = false, bool ehnogc = false, FeatureState dtorFields = (FeatureState)-1, bool fieldwise = false, bool bitfields = false, FeatureState rvalueRefParam = (FeatureState)-1, CppStdRevision cplusplus = (CppStdRevision)201103u, bool markdown = true, bool vmarkdown = false, bool showGaggedErrors = false, bool printErrorContext = false, bool manual = false, bool usage = false, bool mcpuUsage = false, bool transitionUsage = false, bool checkUsage = false, bool checkActionUsage = false, bool revertUsage = false, bool previewUsage = false, bool externStdUsage = false, bool hcUsage = false, bool logo = false, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, uint32_t errorLimit = 20u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, bool doDocComments = false, _d_dynamicArray< const char > docdir = {}, _d_dynamicArray< const char > docname = {}, Array ddocfiles = Array(), bool doHdrGeneration = false, _d_dynamicArray< const char > hdrdir = {}, _d_dynamicArray< const char > hdrname = {}, bool hdrStripPlainFunctions = true, CxxHeaderMode doCxxHdrGeneration = (CxxHeaderMode)0u, _d_dynamicArray< const char > cxxhdrdir = {}, _d_dynamicArray< const char > cxxhdrname = {}, bool doJsonGeneration = false, _d_dynamicArray< const char > jsonfilename = {}, JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, OutBuffer* mixinOut = nullptr, const char* mixinFile = nullptr, int32_t mixinLines = 0, uint32_t debuglevel = 0u, Array* debugids = nullptr, uint32_t versionlevel = 0u, Array* versionids = nullptr, _d_dynamicArray< const char > defaultlibname = {}, _d_dynamicArray< const char > debuglibname = {}, _d_dynamicArray< const char > mscrtlib = {}, _d_dynamicArray< const char > moduleDepsFile = {}, OutBuffer* moduleDeps = nullptr, bool emitMakeDeps = false, _d_dynamicArray< const char > makeDepsFile = {}, Array makeDeps = Array(), MessageStyle messageStyle = (MessageStyle)0u, bool run = false, Array runargs = Array(), Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : obj(obj), link(link), dll(dll), @@ -759,6 +761,7 @@ struct Param final ehnogc(ehnogc), dtorFields(dtorFields), fieldwise(fieldwise), + bitfields(bitfields), rvalueRefParam(rvalueRefParam), cplusplus(cplusplus), markdown(markdown), @@ -5855,6 +5858,7 @@ class BitFieldDeclaration : public VarDeclaration BitFieldDeclaration* syntaxCopy(Dsymbol* s); BitFieldDeclaration* isBitFieldDeclaration(); void accept(Visitor* v); + uint64_t getMinMax(Identifier* id); void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion); }; diff --git a/src/dmd/globals.d b/src/dmd/globals.d index 6b6655c2ea22..023a7bf75a4e 100644 --- a/src/dmd/globals.d +++ b/src/dmd/globals.d @@ -162,6 +162,7 @@ extern (C++) struct Param FeatureState dtorFields; // destruct fields of partially constructed objects // https://issues.dlang.org/show_bug.cgi?id=14246 bool fieldwise; // do struct equality testing field-wise rather than by memcmp() + bool bitfields; // support C style bit fields FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters // https://dconf.org/2019/talks/alexandrescu.html // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a diff --git a/src/dmd/globals.h b/src/dmd/globals.h index 2a33692380eb..079d8e109342 100644 --- a/src/dmd/globals.h +++ b/src/dmd/globals.h @@ -147,6 +147,7 @@ struct Param FeatureState dtorFields; // destruct fields of partially constructed objects // https://issues.dlang.org/show_bug.cgi?id=14246 bool fieldwise; // do struct equality testing field-wise rather than by memcmp() + bool bitfields; // support C style bit fields FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters CppStdRevision cplusplus; // version of C++ name mangling to support bool markdown; // enable Markdown replacements in Ddoc diff --git a/src/dmd/parse.d b/src/dmd/parse.d index 4b9c0f2119f5..d742e7ce249e 100644 --- a/src/dmd/parse.d +++ b/src/dmd/parse.d @@ -289,6 +289,15 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer return true; } + /************************************ + * Parse declarations and definitions + * Params: + * once = !=0 means parse exactly one decl or def + * pLastDecl = set to last decl or def parsed + * pAttrs = keep track of attributes + * Returns: + * array of declared symbols + */ AST.Dsymbols* parseDeclDefs(int once, AST.Dsymbol* pLastDecl = null, PrefixAttributes!AST* pAttrs = null) { AST.Dsymbol lastDecl = null; // used to link unittest to its previous declaration @@ -4298,7 +4307,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer * These can be: * 1. declarations at global/class level * 2. declarations at statement level - * Return array of Declaration *'s. + * Returns: + * array of Declarations. */ private AST.Dsymbols* parseDeclarations(bool autodecl, PrefixAttributes!AST* pAttrs, const(char)* comment) { @@ -4459,6 +4469,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer else if (t != tfirst) error("multiple declarations must have the same type, not `%s` and `%s`", tfirst.toChars(), t.toChars()); + if (token.value == TOK.colon && !ident && t.ty != Tfunction) + { + // Unnamed bit field + ident = Identifier.generateAnonymousId("BitField"); + } + bool isThis = (t.ty == Tident && (cast(AST.TypeIdentifier)t).ident == Id.This && token.value == TOK.assign); if (ident) checkCstyleTypeSyntax(loc, t, alt, ident); @@ -4591,6 +4607,13 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } else if (ident) { + AST.Expression width; + if (token.value == TOK.colon) + { + nextToken(); + width = parseCondExp(); + } + AST.Initializer _init = null; if (token.value == TOK.assign) { @@ -4598,12 +4621,25 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer _init = parseInitializer(); } - auto v = new AST.VarDeclaration(loc, t, ident, _init); - v.storage_class = storage_class; - if (pAttrs) - pAttrs.storageClass = STC.undefined_; - - AST.Dsymbol s = v; + AST.Dsymbol s; + if (width) + { + if (!global.params.bitfields) + error("use -preview=bitfields for bitfield support"); + if (_init) + error("initializer not allowed for bit-field declaration"); + if (storage_class) + error("storage class not allowed for bit-field declaration"); + s = new AST.BitFieldDeclaration(width.loc, t, ident, width); + } + else + { + auto v = new AST.VarDeclaration(loc, t, ident, _init); + v.storage_class = storage_class; + if (pAttrs) + pAttrs.storageClass = STC.undefined_; + s = v; + } if (tpl && _init) { @@ -4616,7 +4652,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer { auto ax = new AST.Dsymbols(); ax.push(s); - s = new AST.AlignDeclaration(v.loc, ealign, ax); + s = new AST.AlignDeclaration(s.loc, ealign, ax); } if (link != linkage) { @@ -4646,12 +4682,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer default: if (loc.linnum != token.loc.linnum) { - error("semicolon needed to end declaration of `%s`, instead of `%s`", v.toChars(), token.toChars()); - errorSupplemental(loc, "`%s` declared here", v.toChars()); + error("semicolon needed to end declaration of `%s`, instead of `%s`", s.toChars(), token.toChars()); + errorSupplemental(loc, "`%s` declared here", s.toChars()); } else { - error("semicolon needed to end declaration of `%s` instead of `%s`", v.toChars(), token.toChars()); + error("semicolon needed to end declaration of `%s` instead of `%s`", s.toChars(), token.toChars()); } break; } diff --git a/src/dmd/todt.d b/src/dmd/todt.d index d9f234ef36fe..07f5a0b2b638 100644 --- a/src/dmd/todt.d +++ b/src/dmd/todt.d @@ -761,10 +761,13 @@ private void membersToDt(AggregateDeclaration ad, ref DtBuilder dtb, { foreach (i, field; ad.fields) { - printf(" fields[%d]: %s %d\n", cast(int)i, field.toChars(), field.offset); + if (auto bf = field.isBitFieldDeclaration()) + printf(" fields[%d]: %s %2d bitoffset %2d width %2d\n", cast(int)i, bf.toChars(), bf.offset, bf.bitOffset, bf.fieldWidth); + else + printf(" fields[%d]: %s %2d\n", cast(int)i, field.toChars(), field.offset); } } - version (all) + version (none) { printf(" firstFieldIndex: %d\n", cast(int)firstFieldIndex); foreach (i; 0 .. elements.length) @@ -857,6 +860,7 @@ private void membersToDt(AggregateDeclaration ad, ref DtBuilder dtb, firstFieldIndex <= elements.dim && firstFieldIndex + ad.fields.dim <= elements.dim); + uint bitByteOffset = 0; // byte offset of bit field uint bitOffset = 0; // starting bit number ulong bitFieldValue = 0; // in-flight bit field value uint bitFieldSize; // in-flight size in bytes of bit field @@ -865,8 +869,16 @@ private void membersToDt(AggregateDeclaration ad, ref DtBuilder dtb, { if (bitOffset) { - //printf("finishInFlightBitField() offset %d bitOffset %d bitFieldSize %d\n", offset, bitOffset, bitFieldSize); + //printf("finishInFlightBitField() offset %d bitOffset %d bitFieldSize %d bitFieldValue x%llx\n", offset, bitOffset, bitFieldSize, bitFieldValue); assert(bitFieldSize); + + // advance to start of bit field + if (offset < bitByteOffset) + { + dtb.nzeros(bitByteOffset - offset); + offset = bitByteOffset; + } + dtb.nbytes(bitFieldSize, cast(char*)&bitFieldValue); offset += bitFieldSize; bitOffset = 0; @@ -875,6 +887,28 @@ private void membersToDt(AggregateDeclaration ad, ref DtBuilder dtb, } } + static if (0) + { + foreach (i, field; ad.fields) + { + if (elements && !(*elements)[firstFieldIndex + i]) + continue; // no element for this field + + if (!elements || !(*elements)[firstFieldIndex + i]) + { + if (field._init && field._init.isVoidInitializer()) + continue; // void initializer for this field + } + + VarDeclaration vd = field; + auto bf = vd.isBitFieldDeclaration(); + if (bf) + printf("%s\t offset: %d width: %u bit: %u\n", bf.toChars(), bf.offset, bf.fieldWidth, bf.bitOffset); + else + printf("%s\t offset: %d\n", vd.toChars(), vd.offset); + } + } + foreach (i, field; ad.fields) { // skip if no element for this field @@ -943,7 +977,7 @@ private void membersToDt(AggregateDeclaration ad, ref DtBuilder dtb, switch (target.c.bitFieldStyle) { case TargetC.BitFieldStyle.Gcc_Clang: - bitFieldSize = (bitOffset + bf.fieldWidth + 7) / 8; + bitFieldSize = (bf.bitOffset + bf.fieldWidth + 7) / 8; break; case TargetC.BitFieldStyle.DM: @@ -957,10 +991,14 @@ private void membersToDt(AggregateDeclaration ad, ref DtBuilder dtb, } } - assert(offset <= vd.offset); + //printf("offset: %u, vd: %s vd.offset: %u\n", offset, vd.toChars(), vd.offset); + if (vd.offset < offset) + continue; // a union field if (offset < vd.offset) + { dtb.nzeros(vd.offset - offset); - //printf("offset: %u, vd: %s vd.offset: %u\n", offset, vd.toChars(), vd.offset); + offset = vd.offset; + } auto dtbx = DtBuilder(0); if (elements) @@ -1012,6 +1050,7 @@ private void membersToDt(AggregateDeclaration ad, ref DtBuilder dtb, dtb.cat(dtbx); if (bf) { + bitByteOffset = bf.offset; bitOffset = bf.bitOffset + bf.fieldWidth; } else diff --git a/test/compilable/dbitfield.d b/test/compilable/dbitfield.d new file mode 100644 index 000000000000..e2883fdd0953 --- /dev/null +++ b/test/compilable/dbitfield.d @@ -0,0 +1,88 @@ +/* REQUIRED_ARGS: -preview=bitfields + */ + +/***************************************************/ + +class C +{ + uint a:3; + uint b:1; + ulong c:64; + + int d:3; + int e:1; + long f:64; + + int i; +} + +static assert(C.a.min == 0); +static assert(C.a.max == 7); + +static assert(C.b.min == 0); +static assert(C.b.max == 1); + +static assert(C.c.min == 0); +static assert(C.c.max == ulong.max); + +static assert(C.d.min == -4); +static assert(C.d.max == 3); + +static assert(C.e.min == -1); +static assert(C.e.max == 0); + +static assert(C.f.min == long.min); +static assert(C.f.max == long.max); + +int testc() +{ + scope c = new C(); + c.d = 9; + return c.d; +} + +static assert(testc() == 1); + +/***************************************************/ + +union U +{ + uint a:3; + uint b:1; + ulong c:64; + + int d:3; + int e:1; + long f:64; + + int i; +} + +static assert(U.sizeof == 8); + +static assert(U.a.min == 0); +static assert(U.a.max == 7); + +static assert(U.b.min == 0); +static assert(U.b.max == 1); + +static assert(U.c.min == 0); +static assert(U.c.max == ulong.max); + +static assert(U.d.min == -4); +static assert(U.d.max == 3); + +static assert(U.e.min == -1); +static assert(U.e.max == 0); + +static assert(U.f.min == long.min); +static assert(U.f.max == long.max); + +int testu() +{ + U u; + u.d = 9; + return u.d; +} + +static assert(testu() == 1); diff --git a/test/compilable/previewhelp.d b/test/compilable/previewhelp.d index cccdf0b166d2..48705f784124 100644 --- a/test/compilable/previewhelp.d +++ b/test/compilable/previewhelp.d @@ -9,6 +9,7 @@ Upcoming language changes listed by -preview=name: =dip1000 implement https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md (Scoped Pointers) =dip1008 implement https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1008.md (@nogc Throwable) =dip1021 implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md (Mutable function arguments) + =bitfields add bitfields https://github.com/dlang/dlang.org/pull/3190 =fieldwise use fieldwise comparisons for struct equality =fixAliasThis when a symbol is resolved, check alias this scope before going to upper scopes =rvaluerefparam enable rvalue arguments to ref parameters diff --git a/test/fail_compilation/biterrors.d b/test/fail_compilation/biterrors.d new file mode 100644 index 000000000000..a8f0faa07392 --- /dev/null +++ b/test/fail_compilation/biterrors.d @@ -0,0 +1,15 @@ +/* REQUIRED_ARGS: -preview=bitfields + * TEST_OUTPUT: +--- +fail_compilation/biterrors.d(103): Error: initializer not allowed for bit-field declaration +fail_compilation/biterrors.d(104): Error: storage class not allowed for bit-field declaration +--- + */ + +#line 100 + +struct S +{ + int i : 3 = 7; + static int j : 3; +} diff --git a/test/fail_compilation/biterrors2.d b/test/fail_compilation/biterrors2.d new file mode 100644 index 000000000000..c8390ba7dc30 --- /dev/null +++ b/test/fail_compilation/biterrors2.d @@ -0,0 +1,17 @@ +/* REQUIRED_ARGS: -preview=bitfields + * TEST_OUTPUT: +--- +fail_compilation/biterrors2.d(100): Error: variable `biterrors2.a` bit-field must be member of struct, union, or class +fail_compilation/biterrors2.d(104): Error: bit-field `b` has zero width +fail_compilation/biterrors2.d(105): Error: bit-field type `float` is not an integer type +--- +*/ + +#line 100 +int a : 2; + +struct S +{ + int b:0; + float c:3; +} diff --git a/test/fail_compilation/biterrors3.d b/test/fail_compilation/biterrors3.d new file mode 100644 index 000000000000..f9e1df2b7b2f --- /dev/null +++ b/test/fail_compilation/biterrors3.d @@ -0,0 +1,18 @@ +/* REQUIRED_ARGS: -preview=bitfields + * TEST_OUTPUT: +--- +fail_compilation/biterrors3.d(103): Error: storage class not allowed for bit-field declaration +fail_compilation/biterrors3.d(106): Error: `d` is not a valid attribute for enum members +fail_compilation/biterrors3.d(106): Error: `:` is not a valid attribute for enum members +fail_compilation/biterrors3.d(106): Error: `3` is not a valid attribute for enum members +--- +*/ + +#line 100 + +struct S +{ + static int : 3; +} + +enum E { d : 3 } diff --git a/test/fail_compilation/biterrors4.d b/test/fail_compilation/biterrors4.d new file mode 100644 index 000000000000..0f2ca2d0d3fc --- /dev/null +++ b/test/fail_compilation/biterrors4.d @@ -0,0 +1,19 @@ +/* REQUIRED_ARGS: -preview=bitfields + * TEST_OUTPUT: +--- +fail_compilation/biterrors4.d(109): Error: cannot take address of bit-field `a` +--- +*/ + +#line 100 + +struct S +{ + int a:3; +} + +void test() +{ + S s; + int* p = &s.a; +} diff --git a/test/fail_compilation/dbitfields.d b/test/fail_compilation/dbitfields.d new file mode 100644 index 000000000000..0dd1a0bf96e7 --- /dev/null +++ b/test/fail_compilation/dbitfields.d @@ -0,0 +1,32 @@ +/* REQUIRED_ARGS: -preview=bitfields + * TEST_OUTPUT: +--- +fail_compilation/dbitfields.d(118): Error: reinterpretation through overlapped field `e` is not allowed in CTFE +fail_compilation/dbitfields.d(121): called from here: `testu()` +fail_compilation/dbitfields.d(121): while evaluating: `static assert(testu() == 1)` +--- + */ + +#line 100 + +union U +{ + uint a:3; + uint b:1; + ulong c:64; + + int d:3; + int e:1; + long f:64; + + int i; +} + +int testu() +{ + U u; + u.d = 9; + return u.e; +} + +static assert(testu() == 1); diff --git a/test/fail_compilation/test16188.d b/test/fail_compilation/test16188.d index c8ab82504356..c4a0fa63e75e 100644 --- a/test/fail_compilation/test16188.d +++ b/test/fail_compilation/test16188.d @@ -1,8 +1,8 @@ -TEST_OUTPUT: +/* REQUIRED_ARGS: -preview=bitfields + * TEST_OUTPUT: --- -fail_compilation/test16188.d(1): Error: no identifier for declarator `TEST_OUTPUT` -fail_compilation/test16188.d(1): Error: declaration expected, not `:` -fail_compilation/test16188.d(18): Error: unmatched closing brace +fail_compilation/test16188.d(101): Error: no property `name` for type `test16188.Where` +fail_compilation/test16188.d(101): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message --- */ @@ -15,6 +15,8 @@ fail_compilation/test16188.d(18): Error: unmatched closing brace * I don't understand why. */ +#line 100 + void where() { Where().name; } struct Where diff --git a/test/fail_compilation/test17284.d b/test/fail_compilation/test17284.d index 5bb3c2cc9f6d..b7fd9796d8be 100644 --- a/test/fail_compilation/test17284.d +++ b/test/fail_compilation/test17284.d @@ -1,9 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/test17284.d(16): Error: field `U.c` cannot access pointers in `@safe` code that overlap other fields +fail_compilation/test17284.d(17): Error: field `U.c` cannot access pointers in `@safe` code that overlap other fields pure nothrow @safe void(U t) --- +REQUIRED_ARGS: -preview=bitfields */ // https://issues.dlang.org/show_bug.cgi?id=17284 diff --git a/test/runnable/bit.d b/test/runnable/bit.d new file mode 100644 index 000000000000..289e1bcfbd6a --- /dev/null +++ b/test/runnable/bit.d @@ -0,0 +1,106 @@ +/* REQUIRED_ARGS: -preview=bitfields + */ + +struct T +{ + uint x : 2, y : 3, :0; + int :0; +} + +uint foo(T s) +{ + return s.x + s.y; +} + +void test1() +{ + T s; + s.x = 2; + s.y = 4; + uint u = foo(s); + assert(u == 6); +} + +/********************************************/ + +struct S +{ + uint a:3; + uint b:1; + ulong c:64; + + int d:3; + int e:1; + long f:64; + + int i; + alias f this; +} + +static assert(S.a.min == 0); +static assert(S.a.max == 7); + +static assert(S.b.min == 0); +static assert(S.b.max == 1); + +static assert(S.c.min == 0); +static assert(S.c.max == ulong.max); + +static assert(S.d.min == -4); +static assert(S.d.max == 3); + +static assert(S.e.min == -1); +static assert(S.e.max == 0); + +static assert(S.f.min == long.min); +static assert(S.f.max == long.max); +static assert(S.max == S.f.max); + +void test2() +{ + int x; + S effect() + { + ++x; + return S(); + } + assert(effect().a.max == 7); + assert(effect().i.max == int.max); + assert(x == 0); // ensure effect() was not executed +} + +/********************************************/ + +struct U +{ + int a; + int b:3, c:4; + this(this) + { + b = 2; + } +} + +static assert(U.b.offsetof == 4); +static assert(U.b.sizeof == 4); + +void test3() +{ + U u; + u.c = 4; + U v = u; + assert(v.c == 4); + u = v; + assert(u.b == 2); + assert(__traits(getMember, u, "b") == 2); +} + +/********************************************/ + +int main() +{ + test1(); + test2(); + test3(); + return 0; +} diff --git a/test/runnable/dbitfields.d b/test/runnable/dbitfields.d new file mode 100644 index 000000000000..0d1877a7bfdf --- /dev/null +++ b/test/runnable/dbitfields.d @@ -0,0 +1,189 @@ +/* REQUIRED_ARGS: -preview=bitfields + */ + +struct S +{ + int a:2, b:4; +} + +static assert(S.sizeof == 4); + +void test1() +{ + S s; + s.a = 3; + assert(s.a == -1); + + s.b = 4; + assert(s.b == 4); +} + +/******************************************/ + +struct S2 +{ + uint a:2, b:4; +} + +S2 foo() +{ + S2 s = { 7, 8 }; // test struct literal expressions + return s; +} + +void test2() +{ + S2 s = foo(); + + assert(s.a == 3); + assert(s.b == 8); +} + +/******************************************/ + +struct S3 +{ + int i1; + uint a:2, b:4, c:6; + int i2; +} + +static assert(S3.sizeof == 12); + +S3 s3 = { 63, 7, 8 }; + +void test3() +{ + assert(s3.i1 == 63); + assert(s3.a == 3); + assert(s3.b == 8); + assert(s3.c == 0); + assert(s3.i2 == 0); +} + +/******************************************/ + +struct S4 +{ + int i1; + uint a:2, b:31; +} + +static assert(S4.sizeof == 12); + +S4 s4 = { 63, 7, 8 }; + +void test4() +{ + assert(s4.i1 == 63); + assert(s4.a == 3); + assert(s4.b == 8); +} + +/******************************************/ + +struct S5 +{ + int i1; + uint a:2, :0, b:5; +} + +static assert(S5.sizeof == 12); + +S5 s5 = { 63, 7, 8 }; + +void test5() +{ + assert(s5.i1 == 63); + assert(s5.a == 3); + assert(s5.b == 8); +} + +/******************************************/ + +// https://issues.dlang.org/show_bug.cgi?id=22710 + +struct S6 +{ + uint a:2, b:2; +} + +int boo6() +{ + S s; + s.a = 3; + s.b = 1; + s.a += 2; + return s.a; +} + +void test6() +{ + //printf("res: %d\n", test()); + assert(boo6() == 1); +} + +/******************************************/ + +// https://issues.dlang.org/show_bug.cgi?id=22710 + +struct S7 +{ + uint a:2, b:2; + int c:2, d:2; +} + +int test7u() +{ + S7 s; + s.a = 7; + s.b = 1; + s.a += 2; + return s.a; +} + +int test7s() +{ + S7 s; + s.c = 7; + s.d = 1; + s.c += 4; + return s.c; +} + +int test7s2() +{ + S7 s; + s.c = 7; + s.d = 2; + s.c += 4; + return s.d; +} + +void test7() +{ + //printf("uns: %d\n", test7u()); + assert(test7u() == 1); + //printf("sig: %d\n", test7s()); + assert(test7s() == -1); + assert(test7s2() == -2); +} + +static assert(test7u() == 1); +static assert(test7s() == -1); +static assert(test7s2() == -2); + +/******************************************/ + +int main() +{ + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + test7(); + + return 0; +} diff --git a/test/runnable/dbitfieldsdm.d b/test/runnable/dbitfieldsdm.d new file mode 100644 index 000000000000..df7762cad612 --- /dev/null +++ b/test/runnable/dbitfieldsdm.d @@ -0,0 +1,196 @@ +/* test bitfields for Digital Mars + * Note that this test is for win32 only + * + * REQUIRED_ARGS: -preview=bitfields + * DISABLED: win32mscoff win64 linux freebsd osx + * RUN_OUTPUT: +--- + DM | MS | P32 | P64 +T0 = 1 1 || 1 1 | 1 1 | 1 1 | 1 1 +T1 = 2 2 || 2 2 | 2 2 | 2 2 | 2 2 +T2 = 4 4 || 4 4 | 4 4 | 4 4 | 4 4 +T3 = 16 8 || 16 8 | 16 8 | 8 4 | 8 8 +T4 = 16 8 || 16 8 | 16 8 | 12 4 | 16 8 +T5 = 16 8 || 16 8 | 16 8 | 8 4 | 8 8 +S1 = 8 8 || 8 8 | 8 8 | 4 4 | 8 8 +S2 = 4 4 || 4 4 | 4 4 | 4 4 | 4 4 +S3 = 8 4 || 8 4 | 8 4 | 4 4 | 4 4 +S4 = 8 4 || 8 4 | 8 4 | 4 4 | 4 4 +S5 = 8 4 || 8 4 | 8 4 | 4 4 | 4 4 +S6 = 2 2 || 2 2 | 2 2 | 2 2 | 2 2 +S7 = 16 8 || 16 8 | 16 8 | 4 4 | 8 8 +S8 = 4 2 || 4 2 | 4 2 | 2 2 | 2 2 +S8A = 4 2 || 4 2 | 4 2 | 2 2 | 2 2 +S8B = 6 2 || 6 2 | 6 2 | 2 2 | 2 2 +S8C = 8 4 || 8 4 | 8 4 | 4 4 | 4 4 +S9 = 4 2 || 4 2 | 4 2 | 4 2 | 4 2 +S10 = 1 1 || 0 0 | * * | 0 1 | 0 1 +S11 = 1 1 || 0 0 | 4 1 | 0 1 | 0 1 +S12 = 4 4 || 4 4 | 4 4 | 4 4 | 4 4 +S13 = 8 4 || 8 4 | 8 4 | 8 4 | 8 4 +S14 = 8 4 || 8 4 | 8 4 | 8 4 | 8 4 +S15 = 8 4 || 8 4 | 8 4 | 4 4 | 4 4 +S16 = 1 1 || 0 0 | 4 4 | 4 1 | 4 1 +S17 = 4 4 || 4 4 | 4 4 | 4 4 | 4 4 +S18 = 2 1 || 2 1 | 2 1 | 5 1 | 9 1 +A0 = 16 8 || 16 8 | 16 8 | 12 4 | 16 8 +A1 = 12 4 || 12 4 | 12 4 | 12 4 | 12 4 +A2 = 12 4 || 12 4 | 12 4 | 12 4 | 12 4 +A3 = 16 4 || 16 4 | 16 4 | 16 4 | 16 4 +A4 = 12 4 || 12 4 | 12 4 | 8 4 | 8 4 +A5 = 2 1 || 2 1 | 2 1 | 2 1 | 2 1 +A6 = 4 2 || 4 2 | 4 2 | 2 2 | 2 2 +A7 = 16 4 || 16 4 | 16 4 | 12 4 | 16 8 +A8 = 12 4 || 12 4 | 12 4 | 8 4 | 8 8 +A9 = 32 8 || 32 8 | 32 8 | 16 4 | 16 8 +A10 = 4 2 || 4 2 | 4 2 | 2 2 | 2 2 +A11 = 16 4 || 16 4 | 16 4 | 12 4 | 12 4 +S9 = x30200 +S14 = x300000201 +S15 = x201 +S18 = 1 should be 4 +A0 = x1 +--- + */ + +import core.stdc.stdio; + +int is64bit() { return size_t.sizeof == 8; } // otherwise assume 32 bit + +/*************************************************************/ + +struct T0 { ubyte x:1; }; // +struct T1 { short x:1; }; // +struct T2 { int x:1; }; // +struct T3 { ubyte a,b,c,d; long x:1; }; // +struct T4 { ubyte a,b,c,d,e,f,g,h; long x:1; }; // +struct T5 { ubyte a,b,c,d,e,f,g; long x:1; }; // +struct S1 { long f:1; }; // +struct S2 { int x:1; int y:1; }; // +struct S3 { short c; int x:1; uint y:1; }; // +struct S4 { int x:1; short y:1; }; // +struct S5 { short x:1; int y:1; }; // +struct S6 { short x:1; short y:1; }; // +struct S7 { short x:1; int y:1; long z:1; }; // +struct S8 { ubyte a; ubyte b:1; short c:2; }; // +struct S8A { ubyte b:1; short c:2; }; // +struct S8B { ubyte a; short b:1; ubyte c:2; }; // +struct S8C { ubyte a; int b:1; }; // +struct S9 { ubyte a; ubyte b:2; short c:9; }; // +struct S10 { }; // sizeof differs from C treatment +struct S11 { int :0; }; // sizeof differs from C treatment +struct S12 { int :0; int x; }; // +struct S13 { uint x:12; uint x1:1; uint x2:1; uint x3:1; uint x4:1; int w; }; // +struct S14 { ubyte a; ubyte b:4; int c:30; }; // +struct S15 { ubyte a; ubyte b:2; int c:9; }; // +struct S16 { int :32; }; // sizeof differs from C treatment +struct S17 { int a:32; }; // +struct S18 { ubyte a; long :0; ubyte b; }; // +struct A0 { int a; long b:34, c:4; }; // +struct A1 { int a; uint b:11; int c; }; // +struct A2 { int a; uint b:11, c:5, d:16; // + int e; }; +struct A3 { int a; uint b:11, c:5, :0, d:16; // + int e; }; +struct A4 { int a:8; short b:7; // + uint c:29; }; +struct A5 { ubyte a:7, b:2; }; // +struct A6 { ubyte a:7; short b:2; }; // +struct A7 { short a:8; int b:16; int c; // + ubyte d:7; }; +struct A8 { short a:8; int b:16; int :0; // + ubyte c:7; }; +struct A9 { ushort a:8; int b:16; // + uint c:29; long d:9; + uint e:2, f:31; }; +struct A10 { ushort a:8; ubyte b; }; // +struct A11 { ubyte a; int b:5, c:11, :0, d:8; // + struct { int ee:8; } }; + +int main() +{ + /* MS produces identical results for 32 and 64 bit compiles, + * DM is 32 bit only + */ + printf(" DM | MS | P32 | P64\n"); + printf("T0 = %2d %d || 1 1 | 1 1 | 1 1 | 1 1\n", cast(int)T0.sizeof, cast(int)T0.alignof); + printf("T1 = %2d %d || 2 2 | 2 2 | 2 2 | 2 2\n", cast(int)T1.sizeof, cast(int)T1.alignof); + printf("T2 = %2d %d || 4 4 | 4 4 | 4 4 | 4 4\n", cast(int)T2.sizeof, cast(int)T2.alignof); + printf("T3 = %2d %d || 16 8 | 16 8 | 8 4 | 8 8\n", cast(int)T3.sizeof, cast(int)T3.alignof); + printf("T4 = %2d %d || 16 8 | 16 8 | 12 4 | 16 8\n", cast(int)T4.sizeof, cast(int)T4.alignof); + printf("T5 = %2d %d || 16 8 | 16 8 | 8 4 | 8 8\n", cast(int)T5.sizeof, cast(int)T5.alignof); + printf("S1 = %2d %d || 8 8 | 8 8 | 4 4 | 8 8\n", cast(int)S1.sizeof, cast(int)S1.alignof); + printf("S2 = %2d %d || 4 4 | 4 4 | 4 4 | 4 4\n", cast(int)S2.sizeof, cast(int)S2.alignof); + printf("S3 = %2d %d || 8 4 | 8 4 | 4 4 | 4 4\n", cast(int)S3.sizeof, cast(int)S3.alignof); + printf("S4 = %2d %d || 8 4 | 8 4 | 4 4 | 4 4\n", cast(int)S4.sizeof, cast(int)S4.alignof); + printf("S5 = %2d %d || 8 4 | 8 4 | 4 4 | 4 4\n", cast(int)S5.sizeof, cast(int)S5.alignof); + printf("S6 = %2d %d || 2 2 | 2 2 | 2 2 | 2 2\n", cast(int)S6.sizeof, cast(int)S6.alignof); + printf("S7 = %2d %d || 16 8 | 16 8 | 4 4 | 8 8\n", cast(int)S7.sizeof, cast(int)S7.alignof); + printf("S8 = %2d %d || 4 2 | 4 2 | 2 2 | 2 2\n", cast(int)S8.sizeof, cast(int)S8.alignof); + printf("S8A = %2d %d || 4 2 | 4 2 | 2 2 | 2 2\n", cast(int)S8A.sizeof, cast(int)S8A.alignof); + printf("S8B = %2d %d || 6 2 | 6 2 | 2 2 | 2 2\n", cast(int)S8B.sizeof, cast(int)S8B.alignof); + printf("S8C = %2d %d || 8 4 | 8 4 | 4 4 | 4 4\n", cast(int)S8C.sizeof, cast(int)S8C.alignof); + printf("S9 = %2d %d || 4 2 | 4 2 | 4 2 | 4 2\n", cast(int)S9.sizeof, cast(int)S9.alignof); + printf("S10 = %2d %d || 0 0 | * * | 0 1 | 0 1\n", cast(int)S10.sizeof, cast(int)S10.alignof); // MS doesn't compile + printf("S11 = %2d %d || 0 0 | 4 1 | 0 1 | 0 1\n", cast(int)S11.sizeof, cast(int)S11.alignof); + printf("S12 = %2d %d || 4 4 | 4 4 | 4 4 | 4 4\n", cast(int)S12.sizeof, cast(int)S12.alignof); + printf("S13 = %2d %d || 8 4 | 8 4 | 8 4 | 8 4\n", cast(int)S13.sizeof, cast(int)S13.alignof); + printf("S14 = %2d %d || 8 4 | 8 4 | 8 4 | 8 4\n", cast(int)S14.sizeof, cast(int)S14.alignof); + printf("S15 = %2d %d || 8 4 | 8 4 | 4 4 | 4 4\n", cast(int)S15.sizeof, cast(int)S15.alignof); + printf("S16 = %2d %d || 0 0 | 4 4 | 4 1 | 4 1\n", cast(int)S16.sizeof, cast(int)S16.alignof); + printf("S17 = %2d %d || 4 4 | 4 4 | 4 4 | 4 4\n", cast(int)S17.sizeof, cast(int)S17.alignof); + printf("S18 = %2d %d || 2 1 | 2 1 | 5 1 | 9 1\n", cast(int)S18.sizeof, cast(int)S18.alignof); + printf("A0 = %2d %d || 16 8 | 16 8 | 12 4 | 16 8\n", cast(int)A0.sizeof, cast(int)A0.alignof); + printf("A1 = %2d %d || 12 4 | 12 4 | 12 4 | 12 4\n", cast(int)A1.sizeof, cast(int)A1.alignof); + printf("A2 = %2d %d || 12 4 | 12 4 | 12 4 | 12 4\n", cast(int)A2.sizeof, cast(int)A2.alignof); + printf("A3 = %2d %d || 16 4 | 16 4 | 16 4 | 16 4\n", cast(int)A3.sizeof, cast(int)A3.alignof); + printf("A4 = %2d %d || 12 4 | 12 4 | 8 4 | 8 4\n", cast(int)A4.sizeof, cast(int)A4.alignof); + printf("A5 = %2d %d || 2 1 | 2 1 | 2 1 | 2 1\n", cast(int)A5.sizeof, cast(int)A5.alignof); + printf("A6 = %2d %d || 4 2 | 4 2 | 2 2 | 2 2\n", cast(int)A6.sizeof, cast(int)A6.alignof); + printf("A7 = %2d %d || 16 4 | 16 4 | 12 4 | 16 8\n", cast(int)A7.sizeof, cast(int)A7.alignof); + printf("A8 = %2d %d || 12 4 | 12 4 | 8 4 | 8 8\n", cast(int)A8.sizeof, cast(int)A8.alignof); + printf("A9 = %2d %d || 32 8 | 32 8 | 16 4 | 16 8\n", cast(int)A9.sizeof, cast(int)A9.alignof); + printf("A10 = %2d %d || 4 2 | 4 2 | 2 2 | 2 2\n", cast(int)A10.sizeof, cast(int)A10.alignof); + printf("A11 = %2d %d || 16 4 | 16 4 | 12 4 | 12 4\n", cast(int)A11.sizeof, cast(int)A11.alignof); + + { + S9 s; + uint x; + *cast(uint *)&s = 0; + s.b = 2; s.c = 3; + x = *cast(uint *)&s; + printf("S9 = x%x\n", x); + } + { + S14 s = { 1, 2, 3 }; + ulong v; + *cast(long *)&s = 0; + s.a = 1; + s.b = 2; + s.c = 3; + v = *cast(ulong *)&s; + printf("S14 = x%llx\n", v); + } + { + S15 s = { 1,2,3 }; + uint x; + *cast(uint *)&s = 0; + s.a = 1; s.b = 2; s.c = 3; + x = *cast(uint *)&s; + printf("S15 = x%x\n", x); + } + { + S18 s; + printf("S18 = %d should be %d\n", cast(int)(&s.b - &s.a), is64bit() ? 8 : 4); + } + { + A0 s; + long x; + *cast(long *)&s = 0; + s.a = 1; s.b = 15; + x = *cast(long *)&s; + printf("A0 = x%llx\n", x); + } + + return 0; +} diff --git a/test/runnable/dbitfieldsms.d b/test/runnable/dbitfieldsms.d new file mode 100644 index 000000000000..b323ce37f829 --- /dev/null +++ b/test/runnable/dbitfieldsms.d @@ -0,0 +1,193 @@ +/* test bitfields for Microsoft C + * REQUIRED_ARGS: -preview=bitfields + * DISABLED: win32 linux32 freebsd32 osx32 linux64 freebsd64 osx64 + * RUN_OUTPUT: +--- + DM | MS | P32 | P64 +T0 = 1 1 || 1 1 | 1 1 | 1 1 | 1 1 +T1 = 2 2 || 2 2 | 2 2 | 2 2 | 2 2 +T2 = 4 4 || 4 4 | 4 4 | 4 4 | 4 4 +T3 = 16 8 || 16 8 | 16 8 | 8 4 | 8 8 +T4 = 16 8 || 16 8 | 16 8 | 12 4 | 16 8 +T5 = 16 8 || 16 8 | 16 8 | 8 4 | 8 8 +S1 = 8 8 || 8 8 | 8 8 | 4 4 | 8 8 +S2 = 4 4 || 4 4 | 4 4 | 4 4 | 4 4 +S3 = 8 4 || 8 4 | 8 4 | 4 4 | 4 4 +S4 = 8 4 || 8 4 | 8 4 | 4 4 | 4 4 +S5 = 8 4 || 8 4 | 8 4 | 4 4 | 4 4 +S6 = 2 2 || 2 2 | 2 2 | 2 2 | 2 2 +S7 = 16 8 || 16 8 | 16 8 | 4 4 | 8 8 +S8 = 4 2 || 4 2 | 4 2 | 2 2 | 2 2 +S8A = 4 2 || 4 2 | 4 2 | 2 2 | 2 2 +S8B = 6 2 || 6 2 | 6 2 | 2 2 | 2 2 +S8C = 8 4 || 8 4 | 8 4 | 4 4 | 4 4 +S9 = 4 2 || 4 2 | 4 2 | 4 2 | 4 2 +S11 = 1 1 || 0 0 | 4 1 | 0 1 | 0 1 +S12 = 4 4 || 4 4 | 4 4 | 4 4 | 4 4 +S13 = 8 4 || 8 4 | 8 4 | 8 4 | 8 4 +S14 = 8 4 || 8 4 | 8 4 | 8 4 | 8 4 +S15 = 8 4 || 8 4 | 8 4 | 4 4 | 4 4 +S16 = 4 4 || 0 0 | 4 4 | 4 1 | 4 1 +S17 = 4 4 || 4 4 | 4 4 | 4 4 | 4 4 +S18 = 2 1 || 2 1 | 2 1 | 5 1 | 9 1 +A0 = 16 8 || 16 8 | 16 8 | 12 4 | 16 8 +A1 = 12 4 || * * | 12 4 +A2 = 12 4 || * * | 12 4 +A3 = 16 4 || * * | 16 4 +A4 = 12 4 || * * | 12 4 +A5 = 2 1 || * * | 2 1 +A6 = 4 2 || * * | 4 2 +A7 = 16 4 || * * | 16 4 +A8 = 12 4 || * * | 12 4 +A9 = 32 8 || * * | 32 8 +A10 = 4 2 || * * | 4 2 +A11 = 16 4 || * * | 16 4 +S9 = x30200 +S14 = x300000201 +S15 = x201 +S18 = 1 +A0 = x1 +--- + */ + +import core.stdc.stdio; + +int is64bit() { return size_t.sizeof == 8; } // otherwise assume 32 bit + +/*************************************************************/ + +struct T0 { ubyte x:1; }; // +struct T1 { short x:1; }; // +struct T2 { int x:1; }; // +struct T3 { ubyte a,b,c,d; long x:1; }; // +struct T4 { ubyte a,b,c,d,e,f,g,h; long x:1; }; // +struct T5 { ubyte a,b,c,d,e,f,g; long x:1; }; // +struct S1 { long f:1; }; // +struct S2 { int x:1; int y:1; }; // +struct S3 { short c; int x:1; uint y:1; }; // +struct S4 { int x:1; short y:1; }; // +struct S5 { short x:1; int y:1; }; // +struct S6 { short x:1; short y:1; }; // +struct S7 { short x:1; int y:1; long z:1; }; // +struct S8 { ubyte a; ubyte b:1; short c:2; }; // +struct S8A { ubyte b:1; short c:2; }; // +struct S8B { ubyte a; short b:1; ubyte c:2; }; // +struct S8C { ubyte a; int b:1; }; // +struct S9 { ubyte a; ubyte b:2; short c:9; }; // +//struct S10 { }; // +struct S11 { int :0; }; // differs from C in that C sizeof is 4 +struct S12 { int :0; int x; }; // +struct S13 { uint x:12; uint x1:1; uint x2:1; uint x3:1; uint x4:1; int w; }; // +struct S14 { ubyte a; ubyte b:4; int c:30; }; // +struct S15 { ubyte a; ubyte b:2; int c:9; }; // +struct S16 { int :32; }; // +struct S17 { int a:32; }; // +struct S18 { ubyte a; long :0; ubyte b; }; // +struct A0 { int a; long b:34, c:4; }; // +struct A1 { int a; uint b:11; int c; }; // +struct A2 { int a; uint b:11, c:5, d:16; // + int e; }; +struct A3 { int a; uint b:11, c:5, :0, d:16; // + int e; }; +struct A4 { int a:8; short b:7; // + uint c:29; }; +struct A5 { ubyte a:7, b:2; }; // +struct A6 { ubyte a:7; short b:2; }; // +struct A7 { short a:8; int b:16; int c; // + ubyte d:7; }; +struct A8 { short a:8; int b:16; int :0; // + ubyte c:7; }; +struct A9 { ushort a:8; int b:16; // + uint c:29; long d:9; + uint e:2, f:31; }; +struct A10 { ushort a:8; ubyte b; }; // +struct A11 { ubyte a; int b:5, c:11, :0, d:8; // + struct { int ee:8; } }; + +int main() +{ + /* MS produces identical results for 32 and 64 bit compiles, + * DM is 32 bit only + */ + printf(" DM | MS | P32 | P64\n"); + printf("T0 = %2d %d || 1 1 | 1 1 | 1 1 | 1 1\n", cast(int)T0.sizeof, cast(int)T0.alignof); + printf("T1 = %2d %d || 2 2 | 2 2 | 2 2 | 2 2\n", cast(int)T1.sizeof, cast(int)T1.alignof); + printf("T2 = %2d %d || 4 4 | 4 4 | 4 4 | 4 4\n", cast(int)T2.sizeof, cast(int)T2.alignof); + printf("T3 = %2d %d || 16 8 | 16 8 | 8 4 | 8 8\n", cast(int)T3.sizeof, cast(int)T3.alignof); + printf("T4 = %2d %d || 16 8 | 16 8 | 12 4 | 16 8\n", cast(int)T4.sizeof, cast(int)T4.alignof); + printf("T5 = %2d %d || 16 8 | 16 8 | 8 4 | 8 8\n", cast(int)T5.sizeof, cast(int)T5.alignof); + printf("S1 = %2d %d || 8 8 | 8 8 | 4 4 | 8 8\n", cast(int)S1.sizeof, cast(int)S1.alignof); + printf("S2 = %2d %d || 4 4 | 4 4 | 4 4 | 4 4\n", cast(int)S2.sizeof, cast(int)S2.alignof); + printf("S3 = %2d %d || 8 4 | 8 4 | 4 4 | 4 4\n", cast(int)S3.sizeof, cast(int)S3.alignof); + printf("S4 = %2d %d || 8 4 | 8 4 | 4 4 | 4 4\n", cast(int)S4.sizeof, cast(int)S4.alignof); + printf("S5 = %2d %d || 8 4 | 8 4 | 4 4 | 4 4\n", cast(int)S5.sizeof, cast(int)S5.alignof); + printf("S6 = %2d %d || 2 2 | 2 2 | 2 2 | 2 2\n", cast(int)S6.sizeof, cast(int)S6.alignof); + printf("S7 = %2d %d || 16 8 | 16 8 | 4 4 | 8 8\n", cast(int)S7.sizeof, cast(int)S7.alignof); + printf("S8 = %2d %d || 4 2 | 4 2 | 2 2 | 2 2\n", cast(int)S8.sizeof, cast(int)S8.alignof); + printf("S8A = %2d %d || 4 2 | 4 2 | 2 2 | 2 2\n", cast(int)S8A.sizeof, cast(int)S8A.alignof); + printf("S8B = %2d %d || 6 2 | 6 2 | 2 2 | 2 2\n", cast(int)S8B.sizeof, cast(int)S8B.alignof); + printf("S8C = %2d %d || 8 4 | 8 4 | 4 4 | 4 4\n", cast(int)S8C.sizeof, cast(int)S8C.alignof); + printf("S9 = %2d %d || 4 2 | 4 2 | 4 2 | 4 2\n", cast(int)S9.sizeof, cast(int)S9.alignof); +// printf("S10 = %2d %d || 0 0 | * * | 0 1 | 0 1\n", cast(int)S10.sizeof, cast(int)S10.alignof); // MS doesn't compile + printf("S11 = %2d %d || 0 0 | 4 1 | 0 1 | 0 1\n", cast(int)S11.sizeof, cast(int)S11.alignof); + printf("S12 = %2d %d || 4 4 | 4 4 | 4 4 | 4 4\n", cast(int)S12.sizeof, cast(int)S12.alignof); + printf("S13 = %2d %d || 8 4 | 8 4 | 8 4 | 8 4\n", cast(int)S13.sizeof, cast(int)S13.alignof); + printf("S14 = %2d %d || 8 4 | 8 4 | 8 4 | 8 4\n", cast(int)S14.sizeof, cast(int)S14.alignof); + printf("S15 = %2d %d || 8 4 | 8 4 | 4 4 | 4 4\n", cast(int)S15.sizeof, cast(int)S15.alignof); + printf("S16 = %2d %d || 0 0 | 4 4 | 4 1 | 4 1\n", cast(int)S16.sizeof, cast(int)S16.alignof); + printf("S17 = %2d %d || 4 4 | 4 4 | 4 4 | 4 4\n", cast(int)S17.sizeof, cast(int)S17.alignof); + printf("S18 = %2d %d || 2 1 | 2 1 | 5 1 | 9 1\n", cast(int)S18.sizeof, cast(int)S18.alignof); + printf("A0 = %2d %d || 16 8 | 16 8 | 12 4 | 16 8\n", cast(int)A0.sizeof, cast(int)A0.alignof); + printf("A1 = %2d %d || * * | 12 4\n", cast(int)A1.sizeof, cast(int)A1.alignof); + printf("A2 = %2d %d || * * | 12 4\n", cast(int)A2.sizeof, cast(int)A2.alignof); + printf("A3 = %2d %d || * * | 16 4\n", cast(int)A3.sizeof, cast(int)A3.alignof); + printf("A4 = %2d %d || * * | 12 4\n", cast(int)A4.sizeof, cast(int)A4.alignof); + printf("A5 = %2d %d || * * | 2 1\n", cast(int)A5.sizeof, cast(int)A5.alignof); + printf("A6 = %2d %d || * * | 4 2\n", cast(int)A6.sizeof, cast(int)A6.alignof); + printf("A7 = %2d %d || * * | 16 4\n", cast(int)A7.sizeof, cast(int)A7.alignof); + printf("A8 = %2d %d || * * | 12 4\n", cast(int)A8.sizeof, cast(int)A8.alignof); + printf("A9 = %2d %d || * * | 32 8\n", cast(int)A9.sizeof, cast(int)A9.alignof); + printf("A10 = %2d %d || * * | 4 2\n", cast(int)A10.sizeof, cast(int)A10.alignof); + printf("A11 = %2d %d || * * | 16 4\n", cast(int)A11.sizeof, cast(int)A11.alignof); + + { + S9 s; + uint x; + *cast(uint *)&s = 0; + s.b = 2; s.c = 3; + x = *cast(uint *)&s; + printf("S9 = x%x\n", x); + } + { + S14 s = { 1, 2, 3 }; + ulong v; + *cast(long *)&s = 0; + s.a = 1; + s.b = 2; + s.c = 3; + v = *cast(ulong *)&s; + printf("S14 = x%llx\n", v); + } + { + S15 s = { 1,2,3 }; + uint x; + *cast(uint *)&s = 0; + s.a = 1; s.b = 2; s.c = 3; + x = *cast(uint *)&s; + printf("S15 = x%x\n", x); + } + { + S18 s; + printf("S18 = %d\n", cast(int)(&s.b - &s.a)); + } + { + A0 s; + long x; + *cast(long *)&s = 0; + s.a = 1; s.b = 15; + x = *cast(long *)&s; + printf("A0 = x%llx\n", x); + } + + return 0; +} diff --git a/test/runnable/dbitfieldsposix32.d b/test/runnable/dbitfieldsposix32.d new file mode 100644 index 000000000000..5af9b6127ea7 --- /dev/null +++ b/test/runnable/dbitfieldsposix32.d @@ -0,0 +1,185 @@ +/* test bitfields + * REQUIRED_ARGS: -preview=bitfields + * DISABLED: win32 win64 linux64 freebsd64 osx64 + * RUN_OUTPUT: +--- +T0 = 1 1 | 1 1 +T1 = 2 2 | 2 2 +T2 = 4 4 | 4 4 +T3 = 8 4 | 8 4 +T4 = 12 4 | 12 4 +T5 = 8 4 | 8 4 +S1 = 4 4 | 8 8 +S2 = 4 4 | 4 4 +S3 = 4 4 | 4 4 +S4 = 4 4 | 4 4 +S5 = 4 4 | 4 4 +S6 = 2 2 | 2 2 +S7 = 4 4 | 8 8 +S8 = 2 2 | 2 2 +S8A = 2 2 | 2 2 +S8B = 2 2 | 2 2 +S8C = 4 4 | 4 4 +S9 = 4 2 | 4 2 +S10 = 1 1 | 0 1 +S11 = 1 1 | 0 1 +S12 = 4 4 | 4 4 +S13 = 8 4 | 8 4 +S14 = 8 4 | 8 4 +S15 = 4 4 | 4 4 +S16 = 4 1 | 4 1 +S17 = 4 4 | 4 4 +S18 = 5 1 | 5 1 +A0 = 12 4 | 12 4 +A1 = 12 4 | 12 4 +A2 = 12 4 | 12 4 +A3 = 16 4 | 16 4 +A4 = 8 4 | 8 4 +A5 = 2 1 | 2 1 +A6 = 2 2 | 2 2 +A7 = 12 4 | 12 4 +A8 = 8 4 | 8 4 +A9 = 16 4 | 16 4 +A10 = 2 2 | 2 2 +A11 = 12 4 | 12 4 +S9 = x30200 +S14 = x300000201 +S15 = xe01 +S18 = 4 should be 4 +A0 = xf00000001 +--- + */ + +import core.stdc.stdio; + +int is64bit() { return size_t.sizeof == 8; } // otherwise assume 32 bit + +/*************************************************************/ + +struct T0 { ubyte x:1; }; // 1 1 +struct T1 { short x:1; }; // 2 2 +struct T2 { int x:1; }; // 4 4 +struct T3 { ubyte a,b,c,d; long x:1; }; // 8 4 (32 bit) 8 8 (64 bit) +struct T4 { ubyte a,b,c,d,e,f,g,h; long x:1; }; // 12 4 (32 bit) 16 8 (64 bit) +struct T5 { ubyte a,b,c,d,e,f,g; long x:1; }; // 8 4 (32 bit) 8 8 (64 bit) +struct S1 { long f:1; }; // 4 4 (32 bit) 8 8 (64 bit) +struct S2 { int x:1; int y:1; }; // 4 4 +struct S3 { short c; int x:1; uint y:1; }; // 4 4 +struct S4 { int x:1; short y:1; }; // 4 4 +struct S5 { short x:1; int y:1; }; // 4 4 +struct S6 { short x:1; short y:1; }; // 2 2 +struct S7 { short x:1; int y:1; long z:1; }; // 4 4 (32 bit) 8 8 (64 bit) +struct S8 { ubyte a; ubyte b:1; short c:2; }; // 2 2 +struct S8A { ubyte b:1; short c:2; }; // 2 2 +struct S8B { ubyte a; short b:1; ubyte c:2; }; // 2 2 +struct S8C { ubyte a; int b:1; }; // 4 4 +struct S9 { ubyte a; ubyte b:2; short c:9; }; // 4 2 x30201 +struct S10 { }; // differs from C sizeof +struct S11 { int :0; }; // differs from C sizeof +struct S12 { int :0; int x; }; // 4 4 +struct S13 { uint x:12; uint x1:1; uint x2:1; uint x3:1; uint x4:1; int w; }; // 8 4 +struct S14 { ubyte a; ubyte b:4; int c:30; }; // 8 4 +struct S15 { ubyte a; ubyte b:2; int c:9; }; // 4 4 xe01 +struct S16 { int :32; }; // 4 1 +struct S17 { int a:32; }; // 4 4 +struct S18 { ubyte a; long :0; ubyte b; }; // 5 1 (32 bit) 9 1 (64 bit) +struct A0 { int a; long b:34, c:4; }; // 12 4 (32 bit) 16 8 (64 bit) +struct A1 { int a; uint b:11; int c; }; // 12 4 +struct A2 { int a; uint b:11, c:5, d:16; // 12 4 + int e; }; +struct A3 { int a; uint b:11, c:5, :0, d:16; // 16 4 + int e; }; +struct A4 { int a:8; short b:7; // 8 4 + uint c:29; }; +struct A5 { ubyte a:7, b:2; }; // 2 1 +struct A6 { ubyte a:7; short b:2; }; // 2 2 +struct A7 { short a:8; int b:16; int c; // 12 4 (32 bit) 16 8 (64 bit) + ubyte d:7; }; +struct A8 { short a:8; int b:16; int :0; // 8 4 (32 bit) 8 8 (64 bit) + ubyte c:7; }; +struct A9 { ushort a:8; int b:16; // 16 4 (32 bit) 16 8 (64 bit) + uint c:29; long d:9; + uint e:2, f:31; }; +struct A10 { ushort a:8; ubyte b; }; // 2 2 +struct A11 { ubyte a; int b:5, c:11, :0, d:8; // 12 4 + struct { int ee:8; } }; + +int main() +{ + printf("T0 = %d %d | 1 1\n", cast(int)T0.sizeof, cast(int)T0.alignof); + printf("T1 = %d %d | 2 2\n", cast(int)T1.sizeof, cast(int)T1.alignof); + printf("T2 = %d %d | 4 4\n", cast(int)T2.sizeof, cast(int)T2.alignof); + printf("T3 = %d %d | 8 4\n", cast(int)T3.sizeof, cast(int)T3.alignof); + printf("T4 = %d %d | 12 4\n", cast(int)T4.sizeof, cast(int)T4.alignof); + printf("T5 = %d %d | 8 4\n", cast(int)T5.sizeof, cast(int)T5.alignof); + printf("S1 = %d %d | 8 8\n", cast(int)S1.sizeof, cast(int)S1.alignof); + printf("S2 = %d %d | 4 4\n", cast(int)S2.sizeof, cast(int)S2.alignof); + printf("S3 = %d %d | 4 4\n", cast(int)S3.sizeof, cast(int)S3.alignof); + printf("S4 = %d %d | 4 4\n", cast(int)S4.sizeof, cast(int)S4.alignof); + printf("S5 = %d %d | 4 4\n", cast(int)S5.sizeof, cast(int)S5.alignof); + printf("S6 = %d %d | 2 2\n", cast(int)S6.sizeof, cast(int)S6.alignof); + printf("S7 = %d %d | 8 8\n", cast(int)S7.sizeof, cast(int)S7.alignof); + printf("S8 = %d %d | 2 2\n", cast(int)S8.sizeof, cast(int)S8.alignof); + printf("S8A = %d %d | 2 2\n", cast(int)S8A.sizeof, cast(int)S8A.alignof); + printf("S8B = %d %d | 2 2\n", cast(int)S8B.sizeof, cast(int)S8B.alignof); + printf("S8C = %d %d | 4 4\n", cast(int)S8C.sizeof, cast(int)S8C.alignof); + printf("S9 = %d %d | 4 2\n", cast(int)S9.sizeof, cast(int)S9.alignof); + printf("S10 = %d %d | 0 1\n", cast(int)S10.sizeof, cast(int)S10.alignof); + printf("S11 = %d %d | 0 1\n", cast(int)S11.sizeof, cast(int)S11.alignof); + printf("S12 = %d %d | 4 4\n", cast(int)S12.sizeof, cast(int)S12.alignof); + printf("S13 = %d %d | 8 4\n", cast(int)S13.sizeof, cast(int)S13.alignof); + printf("S14 = %d %d | 8 4\n", cast(int)S14.sizeof, cast(int)S14.alignof); + printf("S15 = %d %d | 4 4\n", cast(int)S15.sizeof, cast(int)S15.alignof); + printf("S16 = %d %d | 4 1\n", cast(int)S16.sizeof, cast(int)S16.alignof); + printf("S17 = %d %d | 4 4\n", cast(int)S17.sizeof, cast(int)S17.alignof); + printf("S18 = %d %d | 5 1\n", cast(int)S18.sizeof, cast(int)S18.alignof); + printf("A0 = %d %d | 12 4\n", cast(int)A0.sizeof, cast(int)A0.alignof); + printf("A1 = %d %d | 12 4\n", cast(int)A1.sizeof, cast(int)A1.alignof); + printf("A2 = %d %d | 12 4\n", cast(int)A2.sizeof, cast(int)A2.alignof); + printf("A3 = %d %d | 16 4\n", cast(int)A3.sizeof, cast(int)A3.alignof); + printf("A4 = %d %d | 8 4\n", cast(int)A4.sizeof, cast(int)A4.alignof); + printf("A5 = %d %d | 2 1\n", cast(int)A5.sizeof, cast(int)A5.alignof); + printf("A6 = %d %d | 2 2\n", cast(int)A6.sizeof, cast(int)A6.alignof); + printf("A7 = %d %d | 12 4\n", cast(int)A7.sizeof, cast(int)A7.alignof); + printf("A8 = %d %d | 8 4\n", cast(int)A8.sizeof, cast(int)A8.alignof); + printf("A9 = %d %d | 16 4\n", cast(int)A9.sizeof, cast(int)A9.alignof); + printf("A10 = %d %d | 2 2\n", cast(int)A10.sizeof, cast(int)A10.alignof); + printf("A11 = %d %d | 12 4\n", cast(int)A11.sizeof, cast(int)A11.alignof); + + { + S9 s; + *cast(uint *)&s = 0; + s.b = 2; s.c = 3; + uint x = *cast(uint *)&s; + printf("S9 = x%x\n", x); + } + { + S14 s = { 1, 2, 3 }; + *cast(long *)&s = 0; + s.a = 1; + s.b = 2; + s.c = 3; + ulong v = *cast(ulong *)&s; + printf("S14 = x%llx\n", v); + } + { + S15 s = { 1,2,3 }; + *cast(uint *)&s = 0; + s.a = 1; s.b = 2; s.c = 3; + uint x = *cast(uint *)&s; + printf("S15 = x%x\n", x); + } + { + S18 s; + printf("S18 = %d should be %d\n", cast(int)(&s.b - &s.a), is64bit() ? 8 : 4); + } + { + A0 s; + *cast(long *)&s = 0; + s.a = 1; s.b = 15; + long x = *cast(long *)&s; + printf("A0 = x%llx\n", x); + } + + return 0; +} diff --git a/test/runnable/dbitfieldsposix64.d b/test/runnable/dbitfieldsposix64.d new file mode 100644 index 000000000000..4633b757245c --- /dev/null +++ b/test/runnable/dbitfieldsposix64.d @@ -0,0 +1,185 @@ +/* test bitfields + * REQUIRED_ARGS: -preview=bitfields + * DISABLED: win32 win64 linux32 freebsd32 osx32 + * RUN_OUTPUT: +--- +T0 = 1 1 | 1 1 +T1 = 2 2 | 2 2 +T2 = 4 4 | 4 4 +T3 = 8 8 | 8 8 +T4 = 16 8 | 16 8 +T5 = 8 8 | 8 8 +S1 = 8 8 | 8 8 +S2 = 4 4 | 4 4 +S3 = 4 4 | 4 4 +S4 = 4 4 | 4 4 +S5 = 4 4 | 4 4 +S6 = 2 2 | 2 2 +S7 = 8 8 | 8 8 +S8 = 2 2 | 2 2 +S8A = 2 2 | 2 2 +S8B = 2 2 | 2 2 +S8C = 4 4 | 4 4 +S9 = 4 2 | 4 2 +S10 = 1 1 | 0 1 +S11 = 1 1 | 0 1 +S12 = 4 4 | 4 4 +S13 = 8 4 | 8 4 +S14 = 8 4 | 8 4 +S15 = 4 4 | 4 4 +S16 = 4 1 | 4 1 +S17 = 4 4 | 4 4 +S18 = 9 1 | 9 1 +A0 = 16 8 | 16 8 +A1 = 12 4 | 12 4 +A2 = 12 4 | 12 4 +A3 = 16 4 | 16 4 +A4 = 8 4 | 8 4 +A5 = 2 1 | 2 1 +A6 = 2 2 | 2 2 +A7 = 16 8 | 16 8 +A8 = 8 8 | 8 8 +A9 = 16 8 | 16 8 +A10 = 2 2 | 2 2 +A11 = 12 4 | 12 4 +S9 = x30200 +S14 = x300000201 +S15 = xe01 +S18 = 8 should be 8 +A0 = x1 +--- + */ + +import core.stdc.stdio; + +int is64bit() { return size_t.sizeof == 8; } // otherwise assume 32 bit + +/*************************************************************/ + +struct T0 { ubyte x:1; }; // 1 1 +struct T1 { short x:1; }; // 2 2 +struct T2 { int x:1; }; // 4 4 +struct T3 { ubyte a,b,c,d; long x:1; }; // 8 4 (32 bit) 8 8 (64 bit) +struct T4 { ubyte a,b,c,d,e,f,g,h; long x:1; }; // 12 4 (32 bit) 16 8 (64 bit) +struct T5 { ubyte a,b,c,d,e,f,g; long x:1; }; // 8 4 (32 bit) 8 8 (64 bit) +struct S1 { long f:1; }; // 4 4 (32 bit) 8 8 (64 bit) +struct S2 { int x:1; int y:1; }; // 4 4 +struct S3 { short c; int x:1; uint y:1; }; // 4 4 +struct S4 { int x:1; short y:1; }; // 4 4 +struct S5 { short x:1; int y:1; }; // 4 4 +struct S6 { short x:1; short y:1; }; // 2 2 +struct S7 { short x:1; int y:1; long z:1; }; // 4 4 (32 bit) 8 8 (64 bit) +struct S8 { ubyte a; ubyte b:1; short c:2; }; // 2 2 +struct S8A { ubyte b:1; short c:2; }; // 2 2 +struct S8B { ubyte a; short b:1; ubyte c:2; }; // 2 2 +struct S8C { ubyte a; int b:1; }; // 4 4 +struct S9 { ubyte a; ubyte b:2; short c:9; }; // 4 2 x30201 +struct S10 { }; // differs from C +struct S11 { int :0; }; // differs from CG +struct S12 { int :0; int x; }; // 4 4 +struct S13 { uint x:12; uint x1:1; uint x2:1; uint x3:1; uint x4:1; int w; }; // 8 4 +struct S14 { ubyte a; ubyte b:4; int c:30; }; // 8 4 +struct S15 { ubyte a; ubyte b:2; int c:9; }; // 4 4 xe01 +struct S16 { int :32; }; // 4 1 +struct S17 { int a:32; }; // 4 4 +struct S18 { ubyte a; long :0; ubyte b; }; // 5 1 (32 bit) 9 1 (64 bit) +struct A0 { int a; long b:34, c:4; }; // 12 4 (32 bit) 16 8 (64 bit) +struct A1 { int a; uint b:11; int c; }; // 12 4 +struct A2 { int a; uint b:11, c:5, d:16; // 12 4 + int e; }; +struct A3 { int a; uint b:11, c:5, :0, d:16; // 16 4 + int e; }; +struct A4 { int a:8; short b:7; // 8 4 + uint c:29; }; +struct A5 { ubyte a:7, b:2; }; // 2 1 +struct A6 { ubyte a:7; short b:2; }; // 2 2 +struct A7 { short a:8; long b:16; int c; // 12 4 (32 bit) 16 8 (64 bit) + ubyte d:7; }; +struct A8 { short a:8; long b:16; int :0; // 8 4 (32 bit) 8 8 (64 bit) + ubyte c:7; }; +struct A9 { ushort a:8; int b:16; // 16 4 (32 bit) 16 8 (64 bit) + uint c:29; long d:9; + uint e:2, f:31; }; +struct A10 { ushort a:8; ubyte b; }; // 2 2 +struct A11 { ubyte a; int b:5, c:11, :0, d:8; // 12 4 + struct { int ee:8; } }; + +int main() +{ + printf("T0 = %d %d | 1 1\n", cast(int)T0.sizeof, cast(int)T0.alignof); + printf("T1 = %d %d | 2 2\n", cast(int)T1.sizeof, cast(int)T1.alignof); + printf("T2 = %d %d | 4 4\n", cast(int)T2.sizeof, cast(int)T2.alignof); + printf("T3 = %d %d | 8 8\n", cast(int)T3.sizeof, cast(int)T3.alignof); + printf("T4 = %d %d | 16 8\n", cast(int)T4.sizeof, cast(int)T4.alignof); + printf("T5 = %d %d | 8 8\n", cast(int)T5.sizeof, cast(int)T5.alignof); + printf("S1 = %d %d | 8 8\n", cast(int)S1.sizeof, cast(int)S1.alignof); + printf("S2 = %d %d | 4 4\n", cast(int)S2.sizeof, cast(int)S2.alignof); + printf("S3 = %d %d | 4 4\n", cast(int)S3.sizeof, cast(int)S3.alignof); + printf("S4 = %d %d | 4 4\n", cast(int)S4.sizeof, cast(int)S4.alignof); + printf("S5 = %d %d | 4 4\n", cast(int)S5.sizeof, cast(int)S5.alignof); + printf("S6 = %d %d | 2 2\n", cast(int)S6.sizeof, cast(int)S6.alignof); + printf("S7 = %d %d | 8 8\n", cast(int)S7.sizeof, cast(int)S7.alignof); + printf("S8 = %d %d | 2 2\n", cast(int)S8.sizeof, cast(int)S8.alignof); + printf("S8A = %d %d | 2 2\n", cast(int)S8A.sizeof, cast(int)S8A.alignof); + printf("S8B = %d %d | 2 2\n", cast(int)S8B.sizeof, cast(int)S8B.alignof); + printf("S8C = %d %d | 4 4\n", cast(int)S8C.sizeof, cast(int)S8C.alignof); + printf("S9 = %d %d | 4 2\n", cast(int)S9.sizeof, cast(int)S9.alignof); + printf("S10 = %d %d | 0 1\n", cast(int)S10.sizeof, cast(int)S10.alignof); + printf("S11 = %d %d | 0 1\n", cast(int)S11.sizeof, cast(int)S11.alignof); + printf("S12 = %d %d | 4 4\n", cast(int)S12.sizeof, cast(int)S12.alignof); + printf("S13 = %d %d | 8 4\n", cast(int)S13.sizeof, cast(int)S13.alignof); + printf("S14 = %d %d | 8 4\n", cast(int)S14.sizeof, cast(int)S14.alignof); + printf("S15 = %d %d | 4 4\n", cast(int)S15.sizeof, cast(int)S15.alignof); + printf("S16 = %d %d | 4 1\n", cast(int)S16.sizeof, cast(int)S16.alignof); + printf("S17 = %d %d | 4 4\n", cast(int)S17.sizeof, cast(int)S17.alignof); + printf("S18 = %d %d | 9 1\n", cast(int)S18.sizeof, cast(int)S18.alignof); + printf("A0 = %d %d | 16 8\n", cast(int)A0.sizeof, cast(int)A0.alignof); + printf("A1 = %d %d | 12 4\n", cast(int)A1.sizeof, cast(int)A1.alignof); + printf("A2 = %d %d | 12 4\n", cast(int)A2.sizeof, cast(int)A2.alignof); + printf("A3 = %d %d | 16 4\n", cast(int)A3.sizeof, cast(int)A3.alignof); + printf("A4 = %d %d | 8 4\n", cast(int)A4.sizeof, cast(int)A4.alignof); + printf("A5 = %d %d | 2 1\n", cast(int)A5.sizeof, cast(int)A5.alignof); + printf("A6 = %d %d | 2 2\n", cast(int)A6.sizeof, cast(int)A6.alignof); + printf("A7 = %d %d | 16 8\n", cast(int)A7.sizeof, cast(int)A7.alignof); + printf("A8 = %d %d | 8 8\n", cast(int)A8.sizeof, cast(int)A8.alignof); + printf("A9 = %d %d | 16 8\n", cast(int)A9.sizeof, cast(int)A9.alignof); + printf("A10 = %d %d | 2 2\n", cast(int)A10.sizeof, cast(int)A10.alignof); + printf("A11 = %d %d | 12 4\n", cast(int)A11.sizeof, cast(int)A11.alignof); + + { + S9 s; + *cast(uint *)&s = 0; + s.b = 2; s.c = 3; + uint x = *cast(uint *)&s; + printf("S9 = x%x\n", x); + } + { + S14 s = { 1, 2, 3 }; + *cast(long *)&s = 0; + s.a = 1; + s.b = 2; + s.c = 3; + ulong v = *cast(ulong *)&s; + printf("S14 = x%llx\n", v); + } + { + S15 s = { 1,2,3 }; + *cast(uint *)&s = 0; + s.a = 1; s.b = 2; s.c = 3; + uint x = *cast(uint *)&s; + printf("S15 = x%x\n", x); + } + { + S18 s; + printf("S18 = %d should be %d\n", cast(int)(&s.b - &s.a), is64bit() ? 8 : 4); + } + { + A0 s; + *cast(long *)&s = 0; + s.a = 1; s.b = 15; + long x = *cast(long *)&s; + printf("A0 = x%llx\n", x); + } + + return 0; +}