diff mbox series

[committed] d: Merge upstream dmd 5fc1806cd.

Message ID 20200625153828.2304469-6-ibuclaw@gdcproject.org
State New
Headers show
Series [committed] d: Merge upstream dmd 5fc1806cd. | expand

Commit Message

Iain Buclaw June 25, 2020, 3:38 p.m. UTC
Hi,

This patch merges the D front-end implementation with upstream dmd
5fc1806cd.  Backports the OutBuffer interface from upstream dmd master,
removing another difference this and the self-hosted D branch that is
purely refactoring, and doesn't introduce any mechanical changes.

Bootstrapped and regression tested on x86_64-linux-gnu, and committed to
mainline.

Regards
Iain.

---
gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd 5fc1806cd.
	* d-lang.cc (d_parse_file): Use peekChars to get string representation
	of OutBuffer data.
---
 gcc/d/d-lang.cc            |   4 +-
 gcc/d/dmd/MERGE            |   2 +-
 gcc/d/dmd/dcast.c          |   8 +--
 gcc/d/dmd/dmacro.c         |  24 +++----
 gcc/d/dmd/dmangle.c        |  16 ++---
 gcc/d/dmd/dmodule.c        |   6 +-
 gcc/d/dmd/doc.c            | 144 ++++++++++++++++++-------------------
 gcc/d/dmd/dsymbol.h        |   2 +-
 gcc/d/dmd/expression.c     |   2 +-
 gcc/d/dmd/hdrgen.c         |   6 +-
 gcc/d/dmd/json.c           |  32 ++++-----
 gcc/d/dmd/lexer.c          |  54 +++++++-------
 gcc/d/dmd/macro.h          |   2 +-
 gcc/d/dmd/mtype.c          |   6 +-
 gcc/d/dmd/root/filename.c  |   6 +-
 gcc/d/dmd/root/outbuffer.c | 118 +++++++++++++++---------------
 gcc/d/dmd/root/outbuffer.h |  19 +++--
 17 files changed, 224 insertions(+), 227 deletions(-)
diff mbox series

Patch

diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index 24a1125ef8d..e4d0a24c65c 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -1043,7 +1043,7 @@  d_parse_file (void)
 	      buf.writestring (s);
 	    }
 
-	  message ("%.*s", (int) buf.offset, (char *) buf.data);
+	  message ("%s", buf.peekChars ());
 	}
     }
 
@@ -1361,7 +1361,7 @@  d_parse_file (void)
 	  buf.doindent = 1;
 
 	  moduleToBuffer (&buf, m);
-	  message ("%.*s", (int) buf.offset, (char *) buf.data);
+	  message ("%s", buf.peekChars ());
 	}
     }
 
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index a13b5c1fae5..0e48f42a0e2 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@ 
-4f1046222f3a15a746ad2455e1099ed31e39b554
+5fc1806cd7dd281e944022df2e11ef6b04ee4339
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/dcast.c b/gcc/d/dmd/dcast.c
index ad91a65f6ad..1fc9d936bbd 100644
--- a/gcc/d/dmd/dcast.c
+++ b/gcc/d/dmd/dcast.c
@@ -1758,7 +1758,7 @@  Expression *castTo(Expression *e, Scope *sc, Type *t)
                         else
                             buffer.writeUTF16(c);
                     }
-                    newlen = buffer.offset / 2;
+                    newlen = buffer.length() / 2;
                     buffer.writeUTF16(0);
                     goto L1;
 
@@ -1785,7 +1785,7 @@  Expression *castTo(Expression *e, Scope *sc, Type *t)
                         else
                             buffer.writeUTF8(c);
                     }
-                    newlen = buffer.offset;
+                    newlen = buffer.length();
                     buffer.writeUTF8(0);
                     goto L1;
 
@@ -1812,7 +1812,7 @@  Expression *castTo(Expression *e, Scope *sc, Type *t)
                             buffer.writeUTF8(c);
                         newlen++;
                     }
-                    newlen = buffer.offset;
+                    newlen = buffer.length();
                     buffer.writeUTF8(0);
                     goto L1;
 
@@ -1826,7 +1826,7 @@  Expression *castTo(Expression *e, Scope *sc, Type *t)
                             buffer.writeUTF16(c);
                         newlen++;
                     }
-                    newlen = buffer.offset / 2;
+                    newlen = buffer.length() / 2;
                     buffer.writeUTF16(0);
                     goto L1;
 
diff --git a/gcc/d/dmd/dmacro.c b/gcc/d/dmd/dmacro.c
index a7558b73ef1..07187612616 100644
--- a/gcc/d/dmd/dmacro.c
+++ b/gcc/d/dmd/dmacro.c
@@ -237,14 +237,14 @@  void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
 
     size_t end = *pend;
     assert(start <= end);
-    assert(end <= buf->offset);
+    assert(end <= buf->length());
 
     /* First pass - replace $0
      */
     arg = memdup(arg, arglen);
     for (size_t u = start; u + 1 < end; )
     {
-        utf8_t *p = (utf8_t *)buf->data;   // buf->data is not loop invariant
+        utf8_t *p = (utf8_t *)buf->slice().ptr;   // buf->slice().ptr is not loop invariant
 
         /* Look for $0, but not $$0, and replace it with arg.
          */
@@ -294,8 +294,8 @@  void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
             {
                 // Replace '$1' with '\xFF{arg\xFF}'
                 //printf("Replacing '$%c' with '\xFF{%.*s\xFF}'\n", p[u + 1], marglen, marg);
-                buf->data[u] = 0xFF;
-                buf->data[u + 1] = '{';
+                buf->slice().ptr[u] = 0xFF;
+                buf->slice().ptr[u + 1] = '{';
                 buf->insert(u + 2, marg, marglen);
                 buf->insert(u + 2 + marglen, (const char *)"\xFF}", 2);
                 end += -2 + 2 + marglen + 2;
@@ -307,7 +307,7 @@  void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
                 u = mend;
             }
             //printf("u = %d, end = %d\n", u, end);
-            //printf("#%.*s#\n", end, &buf->data[0]);
+            //printf("#%.*s#\n", end, &buf->slice().ptr[0]);
             continue;
         }
 
@@ -318,7 +318,7 @@  void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
      */
     for (size_t u = start; u + 4 < end; )
     {
-        utf8_t *p = (utf8_t *)buf->data;   // buf->data is not loop invariant
+        utf8_t *p = (utf8_t *)buf->slice().ptr;   // buf->slice().ptr is not loop invariant
 
         /* A valid start of macro expansion is $(c, where c is
          * an id start character, and not $$(c.
@@ -418,11 +418,11 @@  void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
                         marg = memdup(marg, marglen);
                         // Insert replacement text
                         buf->spread(v + 1, 2 + m->textlen + 2);
-                        buf->data[v + 1] = 0xFF;
-                        buf->data[v + 2] = '{';
-                        memcpy(buf->data + v + 3, m->text, m->textlen);
-                        buf->data[v + 3 + m->textlen] = 0xFF;
-                        buf->data[v + 3 + m->textlen + 1] = '}';
+                        buf->slice().ptr[v + 1] = 0xFF;
+                        buf->slice().ptr[v + 2] = '{';
+                        memcpy(buf->slice().ptr + v + 3, m->text, m->textlen);
+                        buf->slice().ptr[v + 3 + m->textlen] = 0xFF;
+                        buf->slice().ptr[v + 3 + m->textlen + 1] = '}';
 
                         end += 2 + m->textlen + 2;
 
@@ -438,7 +438,7 @@  void Macro::expand(OutBuffer *buf, size_t start, size_t *pend,
                         u += mend - (v + 1);
                         mem.xfree(const_cast<utf8_t *>(marg));
                         //printf("u = %d, end = %d\n", u, end);
-                        //printf("#%.*s#\n", end - u, &buf->data[u]);
+                        //printf("#%.*s#\n", end - u, &buf->slice().ptr[u]);
                         continue;
                     }
                 }
diff --git a/gcc/d/dmd/dmangle.c b/gcc/d/dmd/dmangle.c
index daa0e8c3bdc..ea63bf3acf0 100644
--- a/gcc/d/dmd/dmangle.c
+++ b/gcc/d/dmd/dmangle.c
@@ -262,7 +262,7 @@  public:
 
         // Write argument types
         paramsToDecoBuffer(t->parameterList.parameters);
-        //if (buf->data[buf->offset - 1] == '@') halt();
+        //if (buf->slice().ptr[buf->length() - 1] == '@') halt();
         buf->writeByte('Z' - t->parameterList.varargs);   // mark end of arg list
         if (tret != NULL)
             visitWithMask(tret, 0);
@@ -308,7 +308,7 @@  public:
         Mangler v(&buf2);
         v.paramsToDecoBuffer(t->arguments);
         const char *s = buf2.peekChars();
-        int len = (int)buf2.offset;
+        int len = (int)buf2.length();
         buf->printf("%d%.*s", len, len, s);
     }
 
@@ -716,8 +716,8 @@  public:
                     else
                         tmp.writeUTF8(c);
                 }
-                q = (utf8_t *)tmp.data;
-                qlen = tmp.offset;
+                q = (utf8_t *)tmp.slice().ptr;
+                qlen = tmp.length();
                 break;
 
             case 4:
@@ -730,8 +730,8 @@  public:
                     else
                         tmp.writeUTF8(c);
                 }
-                q = (utf8_t *)tmp.data;
-                qlen = tmp.offset;
+                q = (utf8_t *)tmp.slice().ptr;
+                qlen = tmp.length();
                 break;
 
             default:
@@ -741,7 +741,7 @@  public:
         buf->writeByte(m);
         buf->printf("%d_", (int)qlen); // nbytes <= 11
 
-        for (utf8_t *p = (utf8_t *)buf->data + buf->offset, *pend = p + 2 * qlen;
+        for (utf8_t *p = (utf8_t *)buf->slice().ptr + buf->length(), *pend = p + 2 * qlen;
              p < pend; p += 2, ++q)
         {
             utf8_t hi = *q >> 4 & 0xF;
@@ -749,7 +749,7 @@  public:
             utf8_t lo = *q & 0xF;
             p[1] = (utf8_t)(lo < 10 ? lo + '0' : lo - 10 + 'a');
         }
-        buf->offset += 2 * qlen;
+        buf->setsize(buf->length() + 2 * qlen);
     }
 
     void visit(ArrayLiteralExp *e)
diff --git a/gcc/d/dmd/dmodule.c b/gcc/d/dmd/dmodule.c
index 102bcdc32b6..8f09f2db856 100644
--- a/gcc/d/dmd/dmodule.c
+++ b/gcc/d/dmd/dmodule.c
@@ -202,7 +202,7 @@  static void checkModFileAlias(OutBuffer *buf, OutBuffer *dotmods,
         const char *m = (*ms)[j];
         const char *q = strchr(m, '=');
         assert(q);
-        if (dotmods->offset <= (size_t)(q - m) && memcmp(dotmods->peekChars(), m, q - m) == 0)
+        if (dotmods->length() <= (size_t)(q - m) && memcmp(dotmods->peekChars(), m, q - m) == 0)
         {
             buf->reset();
             size_t qlen = strlen(q + 1);
@@ -398,7 +398,7 @@  Module *Module::parse()
                         dbuf.writeByte(u);
                 }
                 dbuf.writeByte(0);              // add 0 as sentinel for scanner
-                buflen = dbuf.offset - 1;       // don't include sentinel in count
+                buflen = dbuf.length() - 1;     // don't include sentinel in count
                 buf = (utf8_t *) dbuf.extractData();
             }
             else
@@ -451,7 +451,7 @@  Module *Module::parse()
                         dbuf.writeByte(u);
                 }
                 dbuf.writeByte(0);              // add 0 as sentinel for scanner
-                buflen = dbuf.offset - 1;       // don't include sentinel in count
+                buflen = dbuf.length() - 1;     // don't include sentinel in count
                 buf = (utf8_t *) dbuf.extractData();
             }
         }
diff --git a/gcc/d/dmd/doc.c b/gcc/d/dmd/doc.c
index 35ce2f6b7f8..92783b89ab3 100644
--- a/gcc/d/dmd/doc.c
+++ b/gcc/d/dmd/doc.c
@@ -365,7 +365,7 @@  void gendocfile(Module *m)
             mbuf.write(file.buffer, file.len);
         }
     }
-    DocComment::parseMacros(&m->escapetable, &m->macrotable, (utf8_t *)mbuf.data, mbuf.offset);
+    DocComment::parseMacros(&m->escapetable, &m->macrotable, (utf8_t *)mbuf.slice().ptr, mbuf.length());
 
     Scope *sc = Scope::createGlobal(m);      // create root scope
 
@@ -427,12 +427,12 @@  void gendocfile(Module *m)
         emitMemberComments(m, &buf, sc);
     }
 
-    //printf("BODY= '%.*s'\n", buf.offset, buf.data);
-    Macro::define(&m->macrotable, (const utf8_t *)"BODY", 4, (const utf8_t *)buf.data, buf.offset);
+    //printf("BODY= '%.*s'\n", buf.length(), buf.slice().ptr);
+    Macro::define(&m->macrotable, (const utf8_t *)"BODY", 4, (const utf8_t *)buf.slice().ptr, buf.length());
 
     OutBuffer buf2;
     buf2.writestring("$(DDOC)\n");
-    size_t end = buf2.offset;
+    size_t end = buf2.length();
     m->macrotable->expand(&buf2, 0, &end, NULL, 0);
 
     /* Remove all the escape sequences from buf2,
@@ -440,12 +440,12 @@  void gendocfile(Module *m)
      */
     {
         buf.setsize(0);
-        buf.reserve(buf2.offset);
-        utf8_t *p = (utf8_t *)buf2.data;
-        for (size_t j = 0; j < buf2.offset; j++)
+        buf.reserve(buf2.length());
+        utf8_t *p = (utf8_t *)buf2.slice().ptr;
+        for (size_t j = 0; j < buf2.length(); j++)
         {
             utf8_t c = p[j];
-            if (c == 0xFF && j + 1 < buf2.offset)
+            if (c == 0xFF && j + 1 < buf2.length())
             {
                 j++;
                 continue;
@@ -455,7 +455,7 @@  void gendocfile(Module *m)
             else if (c == '\r')
             {
                 buf.writestring("\r\n");
-                if (j + 1 < buf2.offset && p[j + 1] == '\n')
+                if (j + 1 < buf2.length() && p[j + 1] == '\n')
                 {
                     j++;
                 }
@@ -467,7 +467,7 @@  void gendocfile(Module *m)
 
     // Transfer image to file
     assert(m->docfile);
-    m->docfile->setbuffer(buf.data, buf.offset);
+    m->docfile->setbuffer(buf.slice().ptr, buf.length());
     m->docfile->ref = 1;
     ensurePathToNameExists(Loc(), m->docfile->toChars());
     writeFile(m->loc, m->docfile);
@@ -482,9 +482,9 @@  void gendocfile(Module *m)
  */
 void escapeDdocString(OutBuffer *buf, size_t start)
 {
-    for (size_t u = start; u < buf->offset; u++)
+    for (size_t u = start; u < buf->length(); u++)
     {
-        utf8_t c = buf->data[u];
+        utf8_t c = buf->slice().ptr[u];
         switch(c)
         {
             case '$':
@@ -518,9 +518,9 @@  void escapeStrayParenthesis(Loc loc, OutBuffer *buf, size_t start)
 {
     unsigned par_open = 0;
 
-    for (size_t u = start; u < buf->offset; u++)
+    for (size_t u = start; u < buf->length(); u++)
     {
-        utf8_t c = buf->data[u];
+        utf8_t c = buf->slice().ptr[u];
         switch(c)
         {
             case '(':
@@ -546,10 +546,10 @@  void escapeStrayParenthesis(Loc loc, OutBuffer *buf, size_t start)
     if (par_open)                       // if any unmatched lparens
     {
         par_open = 0;
-        for (size_t u = buf->offset; u > start;)
+        for (size_t u = buf->length(); u > start;)
         {
             u--;
-            utf8_t c = buf->data[u];
+            utf8_t c = buf->slice().ptr[u];
             switch(c)
             {
                 case ')':
@@ -699,9 +699,9 @@  void emitMemberComments(ScopeDsymbol *sds, OutBuffer *buf, Scope *sc)
     else if (sds->isModule())
         m = "$(DDOC_MODULE_MEMBERS ";
 
-    size_t offset1 = buf->offset;         // save starting offset
+    size_t offset1 = buf->length();         // save starting offset
     buf->writestring(m);
-    size_t offset2 = buf->offset;         // to see if we write anything
+    size_t offset2 = buf->length();         // to see if we write anything
 
     sc = sc->push(sds);
 
@@ -720,11 +720,11 @@  void emitMemberComments(ScopeDsymbol *sds, OutBuffer *buf, Scope *sc)
 
     sc->pop();
 
-    if (buf->offset == offset2)
+    if (buf->length() == offset2)
     {
         /* Didn't write out any members, so back out last write
          */
-        buf->offset = offset1;
+        buf->setsize(offset1);
     }
     else
         buf->writestring(")\n");
@@ -780,7 +780,7 @@  void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
 
                     if (i == 0)
                     {
-                        size_t o = buf->offset;
+                        size_t o = buf->length();
                         toDocBuffer(sx, buf, sc);
                         highlightCode(sc, sx, buf, o);
                         continue;
@@ -788,7 +788,7 @@  void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
 
                     buf->writestring("$(DDOC_DITTO ");
                     {
-                        size_t o = buf->offset;
+                        size_t o = buf->length();
                         toDocBuffer(sx, buf, sc);
                         highlightCode(sc, sx, buf, o);
                     }
@@ -804,7 +804,7 @@  void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
                         emitMemberComments(sds, buf, sc);
                 }
                 buf->writestring(ddoc_decl_dd_e);
-                //printf("buf.2 = [[%.*s]]\n", buf->offset - o0, buf->data + o0);
+                //printf("buf.2 = [[%.*s]]\n", buf->length() - o0, buf->slice().ptr + o0);
             }
 
             if (s)
@@ -1454,9 +1454,9 @@  void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
             loc = m->md->loc;
     }
 
-    size_t offset1 = buf->offset;
+    size_t offset1 = buf->length();
     buf->writestring("$(DDOC_SECTIONS ");
-    size_t offset2 = buf->offset;
+    size_t offset2 = buf->length();
 
     for (size_t i = 0; i < sections.length; i++)
     {
@@ -1468,7 +1468,7 @@  void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
         if (!sec->namelen && i == 0)
         {
             buf->writestring("$(DDOC_SUMMARY ");
-            size_t o = buf->offset;
+            size_t o = buf->length();
             buf->write(sec->body, sec->bodylen);
             escapeStrayParenthesis(loc, buf, o);
             highlightText(sc, a, buf, o);
@@ -1495,7 +1495,7 @@  void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
 
             buf->writestring("$(DDOC_EXAMPLES ");
 
-            size_t o = buf->offset;
+            size_t o = buf->length();
             buf->writestring((const char *)c);
 
             if (utd->codedoc)
@@ -1512,11 +1512,11 @@  void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
         }
     }
 
-    if (buf->offset == offset2)
+    if (buf->length() == offset2)
     {
         /* Didn't write out any sections, so back out last write
          */
-        buf->offset = offset1;
+        buf->setsize(offset1);
         buf->writestring("$(DDOC_BLANKLINE)\n");
     }
     else
@@ -1553,7 +1553,7 @@  void Section::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffer *bu
 
             // Replace _ characters with spaces
             buf->writestring("$(DDOC_SECTION_H ");
-            size_t o = buf->offset;
+            size_t o = buf->length();
             for (size_t u = 0; u < namelen; u++)
             {
                 utf8_t c = name[u];
@@ -1567,7 +1567,7 @@  void Section::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffer *bu
         buf->writestring("$(DDOC_DESCRIPTION ");
     }
   L1:
-    size_t o = buf->offset;
+    size_t o = buf->length();
     buf->write(body, bodylen);
     escapeStrayParenthesis(loc, buf, o);
     highlightText(sc, a, buf, o);
@@ -1655,7 +1655,7 @@  void ParamSection::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffe
             {
                 buf->writestring("$(DDOC_PARAM_ID ");
                 {
-                    size_t o = buf->offset;
+                    size_t o = buf->length();
                     Parameter *fparam = isFunctionParameter(a, namestart, namelen);
                     if (!fparam)
                     {
@@ -1692,7 +1692,7 @@  void ParamSection::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffe
 
                 buf->writestring("$(DDOC_PARAM_DESC ");
                 {
-                    size_t o = buf->offset;
+                    size_t o = buf->length();
                     buf->write(textstart, textlen);
                     escapeStrayParenthesis(loc, buf, o);
                     highlightText(sc, a, buf, o);
@@ -1999,12 +1999,12 @@  const utf8_t *skipwhitespace(const utf8_t *p)
 
 size_t skiptoident(OutBuffer *buf, size_t i)
 {
-    while (i < buf->offset)
+    while (i < buf->length())
     {
         dchar_t c;
 
         size_t oi = i;
-        if (utf_decodeChar((utf8_t *)buf->data, buf->offset, &i, &c))
+        if (utf_decodeChar((utf8_t *)buf->slice().ptr, buf->length(), &i, &c))
         {
             /* Ignore UTF errors, but still consume input
              */
@@ -2029,12 +2029,12 @@  size_t skiptoident(OutBuffer *buf, size_t i)
 
 size_t skippastident(OutBuffer *buf, size_t i)
 {
-    while (i < buf->offset)
+    while (i < buf->length())
     {
         dchar_t c;
 
         size_t oi = i;
-        if (utf_decodeChar((utf8_t *)buf->data, buf->offset, &i, &c))
+        if (utf_decodeChar((utf8_t *)buf->slice().ptr, buf->length(), &i, &c))
         {
             /* Ignore UTF errors, but still consume input
              */
@@ -2064,8 +2064,8 @@  size_t skippastident(OutBuffer *buf, size_t i)
 
 size_t skippastURL(OutBuffer *buf, size_t i)
 {
-    size_t length = buf->offset - i;
-    utf8_t *p = (utf8_t *)&buf->data[i];
+    size_t length = buf->length() - i;
+    utf8_t *p = (utf8_t *)&buf->slice().ptr[i];
     size_t j;
     unsigned sawdot = 0;
 
@@ -2236,9 +2236,9 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 
     size_t iLineStart = offset;
 
-    for (size_t i = offset; i < buf->offset; i++)
+    for (size_t i = offset; i < buf->length(); i++)
     {
-        utf8_t c = buf->data[i];
+        utf8_t c = buf->slice().ptr[i];
 
      Lcont:
         switch (c)
@@ -2265,7 +2265,7 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                 }
 
                 if (!sc->_module->isDocFile &&
-                    !inCode && i == iLineStart && i + 1 < buf->offset)    // if "\n\n"
+                    !inCode && i == iLineStart && i + 1 < buf->length())    // if "\n\n"
                 {
                     static const char blankline[] = "$(DDOC_BLANKLINE)\n";
 
@@ -2280,7 +2280,7 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                 leadingBlank = 0;
                 if (inCode)
                     break;
-                utf8_t *p = (utf8_t *)&buf->data[i];
+                utf8_t *p = (utf8_t *)&buf->slice().ptr[i];
                 const char *se = sc->_module->escapetable->escapeChar('<');
                 if (se && strcmp(se, "&lt;") == 0)
                 {
@@ -2292,7 +2292,7 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                         p += 4;
                         while (1)
                         {
-                            if (j == buf->offset)
+                            if (j == buf->length())
                                 goto L1;
                             if (p[0] == '-' && p[1] == '-' && p[2] == '>')
                             {
@@ -2312,7 +2312,7 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                         p += 2;
                         while (1)
                         {
-                            if (j == buf->offset)
+                            if (j == buf->length())
                                 break;
                             if (p[0] == '>')
                             {
@@ -2357,7 +2357,7 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                 leadingBlank = 0;
                 if (inCode)
                     break;
-                utf8_t *p = (utf8_t *)&buf->data[i];
+                utf8_t *p = (utf8_t *)&buf->slice().ptr[i];
                 if (p[1] == '#' || isalpha(p[1]))
                     break;                      // already a character entity
                 // Replace '&' with '&amp;' character entity
@@ -2380,7 +2380,7 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 
                     OutBuffer codebuf;
 
-                    codebuf.write(buf->data + iCodeStart + 1, i - (iCodeStart + 1));
+                    codebuf.write(buf->slice().ptr + iCodeStart + 1, i - (iCodeStart + 1));
 
                     // escape the contents, but do not perform highlighting except for DDOC_PSYMBOL
                     highlightCode(sc, a, &codebuf, 0);
@@ -2389,7 +2389,7 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 
                     static const char pre[] = "$(DDOC_BACKQUOTED ";
                     i = buf->insert(iCodeStart, pre, strlen(pre));
-                    i = buf->insert(i, (char *)codebuf.data, codebuf.offset);
+                    i = buf->insert(i, (char *)codebuf.slice().ptr, codebuf.length());
                     i = buf->insert(i, ")", 1);
 
                     i--; // point to the ending ) so when the for loop does i++, it will see the next character
@@ -2425,9 +2425,9 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                     while (1)
                     {
                         ++i;
-                        if (i >= buf->offset)
+                        if (i >= buf->length())
                             break;
-                        c = buf->data[i];
+                        c = buf->slice().ptr[i];
                         if (c == '\n')
                         {
                             eollen = 1;
@@ -2436,9 +2436,9 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                         if (c == '\r')
                         {
                             eollen = 1;
-                            if (i + 1 >= buf->offset)
+                            if (i + 1 >= buf->length())
                                 break;
-                            if (buf->data[i + 1] == '\n')
+                            if (buf->slice().ptr[i + 1] == '\n')
                             {
                                 eollen = 2;
                                 break;
@@ -2470,13 +2470,13 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                         // The code section is from iCodeStart to i
                         OutBuffer codebuf;
 
-                        codebuf.write(buf->data + iCodeStart, i - iCodeStart);
+                        codebuf.write(buf->slice().ptr + iCodeStart, i - iCodeStart);
                         codebuf.writeByte(0);
 
                         // Remove leading indentations from all lines
                         bool lineStart = true;
-                        utf8_t *endp = (utf8_t *)codebuf.data + codebuf.offset;
-                        for (utf8_t *p = (utf8_t *)codebuf.data; p < endp; )
+                        utf8_t *endp = (utf8_t *)codebuf.slice().ptr + codebuf.length();
+                        for (utf8_t *p = (utf8_t *)codebuf.slice().ptr; p < endp; )
                         {
                             if (lineStart)
                             {
@@ -2484,11 +2484,11 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                                 utf8_t *q = p;
                                 while (j-- > 0 && q < endp && isIndentWS(q))
                                     ++q;
-                                codebuf.remove(p - (utf8_t *)codebuf.data, q - p);
-                                assert((utf8_t *)codebuf.data <= p);
-                                assert(p < (utf8_t *)codebuf.data + codebuf.offset);
+                                codebuf.remove(p - (utf8_t *)codebuf.slice().ptr, q - p);
+                                assert((utf8_t *)codebuf.slice().ptr <= p);
+                                assert(p < (utf8_t *)codebuf.slice().ptr + codebuf.length());
                                 lineStart = false;
-                                endp = (utf8_t *)codebuf.data + codebuf.offset; // update
+                                endp = (utf8_t *)codebuf.slice().ptr + codebuf.length(); // update
                                 continue;
                             }
                             if (*p == '\n')
@@ -2498,7 +2498,7 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 
                         highlightCode2(sc, a, &codebuf, 0);
                         buf->remove(iCodeStart, i - iCodeStart);
-                        i = buf->insert(iCodeStart, codebuf.data, codebuf.offset);
+                        i = buf->insert(iCodeStart, codebuf.slice().ptr, codebuf.length());
                         i = buf->insert(i, (const char *)")\n", 2);
                         i -= 2; // in next loop, c should be '\n'
                     }
@@ -2521,7 +2521,7 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                 if (sc->_module->isDocFile || inCode)
                     break;
 
-                utf8_t *start = (utf8_t *)buf->data + i;
+                utf8_t *start = (utf8_t *)buf->slice().ptr + i;
                 if (isIdStart(start))
                 {
                     size_t j = skippastident(buf, i);
@@ -2541,7 +2541,7 @@  void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                     // leading '_' means no highlight unless it's a reserved symbol name
                     if (c == '_' &&
                         (i == 0 || !isdigit(*(start - 1))) &&
-                        (i == buf->offset - 1 || !isReservedName(start, len)))
+                        (i == buf->length() - 1 || !isReservedName(start, len)))
                     {
                         buf->remove(i, 1);
                         i = j - 1;
@@ -2582,8 +2582,8 @@  void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
     //printf("highlightCode(s = %s '%s')\n", s->kind(), s->toChars());
     OutBuffer ancbuf;
     emitAnchor(&ancbuf, s, sc);
-    buf->insert(offset, (char *)ancbuf.data, ancbuf.offset);
-    offset += ancbuf.offset;
+    buf->insert(offset, (char *)ancbuf.slice().ptr, ancbuf.length());
+    offset += ancbuf.length();
 
     Dsymbols a;
     a.push(s);
@@ -2597,9 +2597,9 @@  void highlightCode(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 {
     //printf("highlightCode(a = '%s')\n", a->toChars());
 
-    for (size_t i = offset; i < buf->offset; i++)
+    for (size_t i = offset; i < buf->length(); i++)
     {
-        utf8_t c = buf->data[i];
+        utf8_t c = buf->slice().ptr[i];
         const char *se = sc->_module->escapetable->escapeChar(c);
         if (se)
         {
@@ -2610,7 +2610,7 @@  void highlightCode(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
             continue;
         }
 
-        utf8_t *start = (utf8_t *)buf->data + i;
+        utf8_t *start = (utf8_t *)buf->slice().ptr + i;
         if (isIdStart(start))
         {
             size_t j = skippastident(buf, i);
@@ -2656,12 +2656,12 @@  void highlightCode3(Scope *sc, OutBuffer *buf, const utf8_t *p, const utf8_t *pe
 void highlightCode2(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 {
     unsigned errorsave = global.errors;
-    Lexer lex(NULL, (utf8_t *)buf->data, 0, buf->offset - 1, 0, 1);
+    Lexer lex(NULL, (utf8_t *)buf->slice().ptr, 0, buf->length() - 1, 0, 1);
     OutBuffer res;
-    const utf8_t *lastp = (utf8_t *)buf->data;
+    const utf8_t *lastp = (utf8_t *)buf->slice().ptr;
 
-    //printf("highlightCode2('%.*s')\n", buf->offset - 1, buf->data);
-    res.reserve(buf->offset);
+    //printf("highlightCode2('%.*s')\n", buf->length() - 1, buf->slice().ptr);
+    res.reserve(buf->length());
     while (1)
     {
         Token tok;
@@ -2705,7 +2705,7 @@  void highlightCode2(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
         if (highlight)
         {
             res.writestring(highlight);
-            size_t o = res.offset;
+            size_t o = res.length();
             highlightCode3(sc, &res, tok.ptr, lex.p);
             if (tok.value == TOKcomment || tok.value == TOKstring)
                 escapeDdocString(&res, o);  // Bugzilla 7656, 7715, and 10519
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 6e37f9bd1af..5fa509be9ca 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -10,7 +10,7 @@ 
 
 #pragma once
 
-#include "root/root.h"
+#include "root/port.h"
 #include "root/stringtable.h"
 #include "ast_node.h"
 #include "globals.h"
diff --git a/gcc/d/dmd/expression.c b/gcc/d/dmd/expression.c
index baa6f5f5a0d..2ad75edb27c 100644
--- a/gcc/d/dmd/expression.c
+++ b/gcc/d/dmd/expression.c
@@ -4430,7 +4430,7 @@  StringExp *ArrayLiteralExp::toStringExp()
         else if (sz == 2) { prefix = 'w'; buf.writeword(0); }
         else              { prefix = 'd'; buf.write4(0); }
 
-        const size_t len = buf.offset / sz - 1;
+        const size_t len = buf.length() / sz - 1;
         StringExp *se = new StringExp(loc, buf.extractData(), len, prefix);
         se->sz = sz;
         se->type = type;
diff --git a/gcc/d/dmd/hdrgen.c b/gcc/d/dmd/hdrgen.c
index 33a804fdba1..22ae9c8253e 100644
--- a/gcc/d/dmd/hdrgen.c
+++ b/gcc/d/dmd/hdrgen.c
@@ -58,7 +58,7 @@  void genhdrfile(Module *m)
     toCBuffer(m, &buf, &hgs);
 
     // Transfer image to file
-    m->hdrfile->setbuffer(buf.data, buf.offset);
+    m->hdrfile->setbuffer(buf.slice().ptr, buf.length());
     buf.extractData();
 
     ensurePathToNameExists(Loc(), m->hdrfile->toChars());
@@ -2303,7 +2303,7 @@  public:
                     /* fall through */
                 case Tchar:
                 {
-                    size_t o = buf->offset;
+                    size_t o = buf->length();
                     if (v == '\'')
                         buf->writestring("'\\''");
                     else if (isprint((int)v) && v != '\\')
@@ -2478,7 +2478,7 @@  public:
     void visit(StringExp *e)
     {
         buf->writeByte('"');
-        size_t o = buf->offset;
+        size_t o = buf->length();
         for (size_t i = 0; i < e->len; i++)
         {
             unsigned c = e->charAt(i);
diff --git a/gcc/d/dmd/json.c b/gcc/d/dmd/json.c
index b1b90d67334..7da127eab54 100644
--- a/gcc/d/dmd/json.c
+++ b/gcc/d/dmd/json.c
@@ -43,18 +43,18 @@  public:
 
     void indent()
     {
-        if (buf->offset >= 1 &&
-            buf->data[buf->offset - 1] == '\n')
+        if (buf->length() >= 1 &&
+            buf->slice().ptr[buf->length() - 1] == '\n')
             for (int i = 0; i < indentLevel; i++)
                 buf->writeByte(' ');
     }
 
     void removeComma()
     {
-        if (buf->offset >= 2 &&
-            buf->data[buf->offset - 2] == ',' &&
-            (buf->data[buf->offset - 1] == '\n' || buf->data[buf->offset - 1] == ' '))
-            buf->offset -= 2;
+        if (buf->length() >= 2 &&
+            buf->slice().ptr[buf->length() - 2] == ',' &&
+            (buf->slice().ptr[buf->length() - 1] == '\n' || buf->slice().ptr[buf->length() - 1] == ' '))
+            buf->setsize(buf->length() - 2);
     }
 
     void comma()
@@ -181,12 +181,12 @@  public:
     {
         indentLevel--;
         removeComma();
-        if (buf->offset >= 2 &&
-            buf->data[buf->offset - 2] == '[' &&
-            buf->data[buf->offset - 1] == '\n')
-            buf->offset -= 1;
-        else if (!(buf->offset >= 1 &&
-            buf->data[buf->offset - 1] == '['))
+        if (buf->length() >= 2 &&
+            buf->slice().ptr[buf->length() - 2] == '[' &&
+            buf->slice().ptr[buf->length() - 1] == '\n')
+            buf->setsize(buf->length() - 1);
+        else if (!(buf->length() >= 1 &&
+            buf->slice().ptr[buf->length() - 1] == '['))
         {
             buf->writestring("\n");
             indent();
@@ -209,10 +209,10 @@  public:
     {
         indentLevel--;
         removeComma();
-        if (buf->offset >= 2 &&
-            buf->data[buf->offset - 2] == '{' &&
-            buf->data[buf->offset - 1] == '\n')
-            buf->offset -= 1;
+        if (buf->length() >= 2 &&
+            buf->slice().ptr[buf->length() - 2] == '{' &&
+            buf->slice().ptr[buf->length() - 1] == '\n')
+            buf->setsize(buf->length() - 1);
         else
         {
             buf->writestring("\n");
diff --git a/gcc/d/dmd/lexer.c b/gcc/d/dmd/lexer.c
index 777842beff4..db989b0b528 100644
--- a/gcc/d/dmd/lexer.c
+++ b/gcc/d/dmd/lexer.c
@@ -1111,10 +1111,10 @@  TOK Lexer::wysiwygStringConstant(Token *t, int tc)
             case '`':
                 if (c == tc)
                 {
-                    t->len = (unsigned)stringbuffer.offset;
+                    t->len = (unsigned)stringbuffer.length();
                     stringbuffer.writeByte(0);
-                    t->ustring = (utf8_t *)mem.xmalloc(stringbuffer.offset);
-                    memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
+                    t->ustring = (utf8_t *)mem.xmalloc(stringbuffer.length());
+                    memcpy(t->ustring, stringbuffer.slice().ptr, stringbuffer.length());
                     stringPostfix(t);
                     return TOKstring;
                 }
@@ -1183,10 +1183,10 @@  TOK Lexer::hexStringConstant(Token *t)
                 {   error("odd number (%d) of hex characters in hex string", n);
                     stringbuffer.writeByte(v);
                 }
-                t->len = (unsigned)stringbuffer.offset;
+                t->len = (unsigned)stringbuffer.length();
                 stringbuffer.writeByte(0);
-                t->ustring = (utf8_t *)mem.xmalloc(stringbuffer.offset);
-                memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
+                t->ustring = (utf8_t *)mem.xmalloc(stringbuffer.length());
+                memcpy(t->ustring, stringbuffer.slice().ptr, stringbuffer.length());
                 stringPostfix(t);
                 return TOKxstring;
 
@@ -1371,10 +1371,10 @@  Ldone:
         error("delimited string must end in %s\"", hereid->toChars());
     else
         error("delimited string must end in %c\"", delimright);
-    t->len = (unsigned)stringbuffer.offset;
+    t->len = (unsigned)stringbuffer.length();
     stringbuffer.writeByte(0);
-    t->ustring = (utf8_t *)mem.xmalloc(stringbuffer.offset);
-    memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
+    t->ustring = (utf8_t *)mem.xmalloc(stringbuffer.length());
+    memcpy(t->ustring, stringbuffer.slice().ptr, stringbuffer.length());
     stringPostfix(t);
     return TOKstring;
 }
@@ -1473,10 +1473,10 @@  TOK Lexer::escapeStringConstant(Token *t)
                 break;
 
             case '"':
-                t->len = (unsigned)stringbuffer.offset;
+                t->len = (unsigned)stringbuffer.length();
                 stringbuffer.writeByte(0);
-                t->ustring = (utf8_t *)mem.xmalloc(stringbuffer.offset);
-                memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
+                t->ustring = (utf8_t *)mem.xmalloc(stringbuffer.length());
+                memcpy(t->ustring, stringbuffer.slice().ptr, stringbuffer.length());
                 stringPostfix(t);
                 return TOKstring;
 
@@ -1997,7 +1997,7 @@  TOK Lexer::inreal(Token *t)
     }
 
     stringbuffer.writeByte(0);
-    const char *sbufptr = (char *)stringbuffer.data;
+    const char *sbufptr = (char *)stringbuffer.slice().ptr;
     TOK result;
     bool isOutOfRange = false;
     t->floatvalue = (isWellformedString ? CTFloat::parse(sbufptr, &isOutOfRange) : CTFloat::zero);
@@ -2049,7 +2049,7 @@  TOK Lexer::inreal(Token *t)
     if (isOutOfRange && !isLong)
     {
         const char *suffix = (result == TOKfloat32v || result == TOKimaginary32v) ? "f" : "";
-        error(scanloc, "number '%s%s' is not representable", (char *)stringbuffer.data, suffix);
+        error(scanloc, "number '%s%s' is not representable", (char *)stringbuffer.slice().ptr, suffix);
     }
     return result;
 }
@@ -2138,7 +2138,7 @@  void Lexer::poundLine()
 
                         case '"':
                             stringbuffer.writeByte(0);
-                            filespec = mem.xstrdup((char *)stringbuffer.data);
+                            filespec = mem.xstrdup((char *)stringbuffer.slice().ptr);
                             p++;
                             break;
 
@@ -2203,6 +2203,14 @@  unsigned Lexer::decodeUTF()
     return u;
 }
 
+static void trimTrailingWhitespace(OutBuffer &buf)
+{
+    const unsigned char *s = buf.slice().ptr;
+    size_t len = buf.length();
+    while (len && (s[len - 1] == ' ' || s[len - 1] == '\t'))
+        --len;
+    buf.setsize(len);
+}
 
 /***************************************************
  * Parse doc comment embedded between t->ptr and p.
@@ -2287,8 +2295,7 @@  void Lexer::getDocComment(Token *t, unsigned lineComment)
                 {   linestart = 0;
                     /* Trim preceding whitespace up to preceding \n
                      */
-                    while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
-                        buf.offset--;
+                    trimTrailingWhitespace(buf);
                     continue;
                 }
                 break;
@@ -2324,9 +2331,7 @@  void Lexer::getDocComment(Token *t, unsigned lineComment)
 
                 /* Trim trailing whitespace
                  */
-                while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
-                    buf.offset--;
-
+                trimTrailingWhitespace(buf);
                 break;
         }
         buf.writeByte(c);
@@ -2334,14 +2339,13 @@  void Lexer::getDocComment(Token *t, unsigned lineComment)
 
     /* Trim trailing whitespace (if the last line does not have newline)
      */
-    if (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
+    if (buf.length() && (buf.slice().ptr[buf.length() - 1] == ' ' || buf.slice().ptr[buf.length() - 1] == '\t'))
     {
-        while (buf.offset && (buf.data[buf.offset - 1] == ' ' || buf.data[buf.offset - 1] == '\t'))
-            buf.offset--;
+        trimTrailingWhitespace(buf);
     }
 
     // Always end with a newline
-    if (!buf.offset || buf.data[buf.offset - 1] != '\n')
+    if (!buf.length() || buf.slice().ptr[buf.length() - 1] != '\n')
         buf.writeByte('\n');
 
     buf.writeByte(0);
@@ -2354,7 +2358,7 @@  void Lexer::getDocComment(Token *t, unsigned lineComment)
 
     // Combine with previous doc comment, if any
     if (*dc)
-        *dc = combineComments(*dc, (utf8_t *)buf.data);
+        *dc = combineComments(*dc, (utf8_t *)buf.slice().ptr);
     else
         *dc = (utf8_t *)buf.extractData();
 }
diff --git a/gcc/d/dmd/macro.h b/gcc/d/dmd/macro.h
index 07ecfe3a387..26710b4771b 100644
--- a/gcc/d/dmd/macro.h
+++ b/gcc/d/dmd/macro.h
@@ -11,7 +11,7 @@ 
 #pragma once
 
 #include "root/dsystem.h"
-#include "root/root.h"
+#include "root/port.h"
 
 
 struct Macro
diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c
index b07ce159912..de39ecb02b2 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -1628,7 +1628,7 @@  Type *Type::merge()
 
         mangleToBuffer(this, &buf);
 
-        StringValue *sv = stringtable.update((char *)buf.data, buf.offset);
+        StringValue *sv = stringtable.update((char *)buf.slice().ptr, buf.length());
         if (sv->ptrvalue)
         {
             t = (Type *) sv->ptrvalue;
@@ -2304,7 +2304,7 @@  Identifier *Type::getTypeInfoIdent()
     buf.reserve(32);
     mangleToBuffer(this, &buf);
 
-    size_t len = buf.offset;
+    size_t len = buf.length();
     buf.writeByte(0);
 
     // Allocate buffer on stack, fail over to using malloc()
@@ -2312,7 +2312,7 @@  Identifier *Type::getTypeInfoIdent()
     size_t namelen = 19 + sizeof(len) * 3 + len + 1;
     char *name = namelen <= sizeof(namebuf) ? namebuf : (char *)mem.xmalloc(namelen);
 
-    int length = sprintf(name, "_D%lluTypeInfo_%s6__initZ", (unsigned long long) 9 + len, buf.data);
+    int length = sprintf(name, "_D%lluTypeInfo_%s6__initZ", (unsigned long long) 9 + len, buf.slice().ptr);
     //printf("%p, deco = %s, name = %s\n", this, deco, name);
     assert(0 < length && (size_t)length < namelen);     // don't overflow the buffer
 
diff --git a/gcc/d/dmd/root/filename.c b/gcc/d/dmd/root/filename.c
index 667efb941b7..50b67404062 100644
--- a/gcc/d/dmd/root/filename.c
+++ b/gcc/d/dmd/root/filename.c
@@ -8,7 +8,7 @@ 
 
 #include "dsystem.h"
 #include "filename.h"
-
+#include "port.h"
 #include "outbuffer.h"
 #include "array.h"
 #include "file.h"
@@ -111,7 +111,7 @@  Strings *FileName::splitPath(const char *path)
                     {
                         char *home = getenv("HOME");
                         // Expand ~ only if it is prefixing the rest of the path.
-                        if (!buf.offset && p[1] == '/' && home)
+                        if (!buf.length() && p[1] == '/' && home)
                             buf.writestring(home);
                         else
                             buf.writestring("~");
@@ -125,7 +125,7 @@  Strings *FileName::splitPath(const char *path)
                 }
                 break;
             }
-            if (buf.offset)             // if path is not empty
+            if (buf.length())             // if path is not empty
             {
                 array->push(buf.extractChars());
             }
diff --git a/gcc/d/dmd/root/outbuffer.c b/gcc/d/dmd/root/outbuffer.c
index d25a14b4872..8544697a3d5 100644
--- a/gcc/d/dmd/root/outbuffer.c
+++ b/gcc/d/dmd/root/outbuffer.c
@@ -14,21 +14,20 @@  char *OutBuffer::extractData()
 {
     char *p;
 
-    p = (char *)data;
-    data = NULL;
+    p = (char *)data.ptr;
+    data = DArray<unsigned char>();
     offset = 0;
-    size = 0;
     return p;
 }
 
 void OutBuffer::reserve(size_t nbytes)
 {
-    //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
-    if (size - offset < nbytes)
+    //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", data.length, offset, nbytes);
+    if (data.length - offset < nbytes)
     {
-        size = (offset + nbytes) * 2;
-        size = (size + 15) & ~15;
-        data = (unsigned char *)mem.xrealloc(data, size);
+        data.length = (offset + nbytes) * 2;
+        data.length = (data.length + 15) & ~15;
+        data.ptr = (unsigned char *)mem.xrealloc(data.ptr, data.length);
     }
 }
 
@@ -51,22 +50,17 @@  void OutBuffer::write(const void *data, size_t nbytes)
             reserve(level);
             for (int i = 0; i < level; i++)
             {
-                this->data[offset] = '\t';
+                this->data.ptr[offset] = '\t';
                 offset++;
             }
         }
         notlinehead = 1;
     }
     reserve(nbytes);
-    memcpy(this->data + offset, data, nbytes);
+    memcpy(this->data.ptr + offset, data, nbytes);
     offset += nbytes;
 }
 
-void OutBuffer::writebstring(utf8_t *string)
-{
-    write(string,*string + 1);
-}
-
 void OutBuffer::writestring(const char *string)
 {
     write(string,strlen(string));
@@ -76,8 +70,8 @@  void OutBuffer::prependstring(const char *string)
 {
     size_t len = strlen(string);
     reserve(len);
-    memmove(data + len, data, offset);
-    memcpy(data, string, len);
+    memmove(data.ptr + len, data.ptr, offset);
+    memcpy(data.ptr, string, len);
     offset += len;
 }
 
@@ -102,14 +96,14 @@  void OutBuffer::writeByte(unsigned b)
             reserve(level);
             for (int i = 0; i < level; i++)
             {
-                this->data[offset] = '\t';
+                this->data.ptr[offset] = '\t';
                 offset++;
             }
         }
         notlinehead = 1;
     }
     reserve(1);
-    this->data[offset] = (unsigned char)b;
+    this->data.ptr[offset] = (unsigned char)b;
     offset++;
 }
 
@@ -118,47 +112,47 @@  void OutBuffer::writeUTF8(unsigned b)
     reserve(6);
     if (b <= 0x7F)
     {
-        this->data[offset] = (unsigned char)b;
+        this->data.ptr[offset] = (unsigned char)b;
         offset++;
     }
     else if (b <= 0x7FF)
     {
-        this->data[offset + 0] = (unsigned char)((b >> 6) | 0xC0);
-        this->data[offset + 1] = (unsigned char)((b & 0x3F) | 0x80);
+        this->data.ptr[offset + 0] = (unsigned char)((b >> 6) | 0xC0);
+        this->data.ptr[offset + 1] = (unsigned char)((b & 0x3F) | 0x80);
         offset += 2;
     }
     else if (b <= 0xFFFF)
     {
-        this->data[offset + 0] = (unsigned char)((b >> 12) | 0xE0);
-        this->data[offset + 1] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-        this->data[offset + 2] = (unsigned char)((b & 0x3F) | 0x80);
+        this->data.ptr[offset + 0] = (unsigned char)((b >> 12) | 0xE0);
+        this->data.ptr[offset + 1] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+        this->data.ptr[offset + 2] = (unsigned char)((b & 0x3F) | 0x80);
         offset += 3;
     }
     else if (b <= 0x1FFFFF)
     {
-        this->data[offset + 0] = (unsigned char)((b >> 18) | 0xF0);
-        this->data[offset + 1] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
-        this->data[offset + 2] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-        this->data[offset + 3] = (unsigned char)((b & 0x3F) | 0x80);
+        this->data.ptr[offset + 0] = (unsigned char)((b >> 18) | 0xF0);
+        this->data.ptr[offset + 1] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
+        this->data.ptr[offset + 2] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+        this->data.ptr[offset + 3] = (unsigned char)((b & 0x3F) | 0x80);
         offset += 4;
     }
     else if (b <= 0x3FFFFFF)
     {
-        this->data[offset + 0] = (unsigned char)((b >> 24) | 0xF8);
-        this->data[offset + 1] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
-        this->data[offset + 2] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
-        this->data[offset + 3] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-        this->data[offset + 4] = (unsigned char)((b & 0x3F) | 0x80);
+        this->data.ptr[offset + 0] = (unsigned char)((b >> 24) | 0xF8);
+        this->data.ptr[offset + 1] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
+        this->data.ptr[offset + 2] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
+        this->data.ptr[offset + 3] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+        this->data.ptr[offset + 4] = (unsigned char)((b & 0x3F) | 0x80);
         offset += 5;
     }
     else if (b <= 0x7FFFFFFF)
     {
-        this->data[offset + 0] = (unsigned char)((b >> 30) | 0xFC);
-        this->data[offset + 1] = (unsigned char)(((b >> 24) & 0x3F) | 0x80);
-        this->data[offset + 2] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
-        this->data[offset + 3] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
-        this->data[offset + 4] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
-        this->data[offset + 5] = (unsigned char)((b & 0x3F) | 0x80);
+        this->data.ptr[offset + 0] = (unsigned char)((b >> 30) | 0xFC);
+        this->data.ptr[offset + 1] = (unsigned char)(((b >> 24) & 0x3F) | 0x80);
+        this->data.ptr[offset + 2] = (unsigned char)(((b >> 18) & 0x3F) | 0x80);
+        this->data.ptr[offset + 3] = (unsigned char)(((b >> 12) & 0x3F) | 0x80);
+        this->data.ptr[offset + 4] = (unsigned char)(((b >> 6) & 0x3F) | 0x80);
+        this->data.ptr[offset + 5] = (unsigned char)((b & 0x3F) | 0x80);
         offset += 6;
     }
     else
@@ -168,8 +162,8 @@  void OutBuffer::writeUTF8(unsigned b)
 void OutBuffer::prependbyte(unsigned b)
 {
     reserve(1);
-    memmove(data + 1, data, offset);
-    data[0] = (unsigned char)b;
+    memmove(data.ptr + 1, data.ptr, offset);
+    data.ptr[0] = (unsigned char)b;
     offset++;
 }
 
@@ -197,14 +191,14 @@  void OutBuffer::writeword(unsigned w)
             reserve(level);
             for (int i = 0; i < level; i++)
             {
-                this->data[offset] = '\t';
+                this->data.ptr[offset] = '\t';
                 offset++;
             }
         }
         notlinehead = 1;
     }
     reserve(2);
-    *(unsigned short *)(this->data + offset) = (unsigned short)w;
+    *(unsigned short *)(this->data.ptr + offset) = (unsigned short)w;
     offset += 2;
 }
 
@@ -213,13 +207,13 @@  void OutBuffer::writeUTF16(unsigned w)
     reserve(4);
     if (w <= 0xFFFF)
     {
-        *(unsigned short *)(this->data + offset) = (unsigned short)w;
+        *(unsigned short *)(this->data.ptr + offset) = (unsigned short)w;
         offset += 2;
     }
     else if (w <= 0x10FFFF)
     {
-        *(unsigned short *)(this->data + offset) = (unsigned short)((w >> 10) + 0xD7C0);
-        *(unsigned short *)(this->data + offset + 2) = (unsigned short)((w & 0x3FF) | 0xDC00);
+        *(unsigned short *)(this->data.ptr + offset) = (unsigned short)((w >> 10) + 0xD7C0);
+        *(unsigned short *)(this->data.ptr + offset + 2) = (unsigned short)((w & 0x3FF) | 0xDC00);
         offset += 4;
     }
     else
@@ -240,14 +234,14 @@  void OutBuffer::write4(unsigned w)
             reserve(level);
             for (int i = 0; i < level; i++)
             {
-                this->data[offset] = '\t';
+                this->data.ptr[offset] = '\t';
                 offset++;
             }
         }
         notlinehead = 1;
     }
     reserve(4);
-    *(unsigned *)(this->data + offset) = w;
+    *(unsigned *)(this->data.ptr + offset) = w;
     offset += 4;
 }
 
@@ -255,7 +249,7 @@  void OutBuffer::write(OutBuffer *buf)
 {
     if (buf)
     {   reserve(buf->offset);
-        memcpy(data + offset, buf->data, buf->offset);
+        memcpy(data.ptr + offset, buf->data.ptr, buf->offset);
         offset += buf->offset;
     }
 }
@@ -271,7 +265,7 @@  void OutBuffer::write(RootObject *obj)
 void OutBuffer::fill0(size_t nbytes)
 {
     reserve(nbytes);
-    memset(data + offset,0,nbytes);
+    memset(data.ptr + offset,0,nbytes);
     offset += nbytes;
 }
 
@@ -286,7 +280,7 @@  void OutBuffer::vprintf(const char *format, va_list args)
     {
         reserve(psize);
 #if _WIN32
-        count = _vsnprintf((char *)data + offset,psize,format,args);
+        count = _vsnprintf((char *)data.ptr + offset,psize,format,args);
         if (count != -1)
             break;
         psize *= 2;
@@ -302,7 +296,7 @@  void OutBuffer::vprintf(const char *format, va_list args)
   of ap is undefined after the call. The application should call
   va_end(ap) itself afterwards.
  */
-        count = vsnprintf((char *)data + offset,psize,format,va);
+        count = vsnprintf((char *)data.ptr + offset,psize,format,va);
         va_end(va);
         if (count == -1)
             psize *= 2;
@@ -328,9 +322,9 @@  void OutBuffer::printf(const char *format, ...)
 void OutBuffer::bracket(char left, char right)
 {
     reserve(2);
-    memmove(data + 1, data, offset);
-    data[0] = left;
-    data[offset + 1] = right;
+    memmove(data.ptr + 1, data.ptr, offset);
+    data.ptr[0] = left;
+    data.ptr[offset + 1] = right;
     offset += 2;
 }
 
@@ -352,7 +346,7 @@  size_t OutBuffer::bracket(size_t i, const char *left, size_t j, const char *righ
 void OutBuffer::spread(size_t offset, size_t nbytes)
 {
     reserve(nbytes);
-    memmove(data + offset + nbytes, data + offset,
+    memmove(data.ptr + offset + nbytes, data.ptr + offset,
         this->offset - offset);
     this->offset += nbytes;
 }
@@ -364,29 +358,29 @@  void OutBuffer::spread(size_t offset, size_t nbytes)
 size_t OutBuffer::insert(size_t offset, const void *p, size_t nbytes)
 {
     spread(offset, nbytes);
-    memmove(data + offset, p, nbytes);
+    memmove(data.ptr + offset, p, nbytes);
     return offset + nbytes;
 }
 
 void OutBuffer::remove(size_t offset, size_t nbytes)
 {
-    memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes));
+    memmove(data.ptr + offset, data.ptr + offset + nbytes, this->offset - (offset + nbytes));
     this->offset -= nbytes;
 }
 
 char *OutBuffer::peekChars()
 {
-    if (!offset || data[offset-1] != '\0')
+    if (!offset || data.ptr[offset-1] != '\0')
     {
         writeByte(0);
         offset--; // allow appending more
     }
-    return (char *)data;
+    return (char *)data.ptr;
 }
 
 char *OutBuffer::extractChars()
 {
-    if (!offset || data[offset-1] != '\0')
+    if (!offset || data.ptr[offset-1] != '\0')
         writeByte(0);
     return extractData();
 }
diff --git a/gcc/d/dmd/root/outbuffer.h b/gcc/d/dmd/root/outbuffer.h
index fbc3f32d456..49b1c3e5bcf 100644
--- a/gcc/d/dmd/root/outbuffer.h
+++ b/gcc/d/dmd/root/outbuffer.h
@@ -9,28 +9,26 @@ 
 #pragma once
 
 #include "dsystem.h"
-#include "port.h"
+#include "dcompat.h"
 #include "rmem.h"
 
 class RootObject;
 
 struct OutBuffer
 {
-    unsigned char *data;
+private:
+    DArray<unsigned char> data;
     size_t offset;
-    size_t size;
+    bool notlinehead;
+public:
 
     int level;
     bool doindent;
-private:
-    bool notlinehead;
-public:
 
     OutBuffer()
     {
-        data = NULL;
+        data = DArray<unsigned char>();
         offset = 0;
-        size = 0;
 
         doindent = 0;
         level = 0;
@@ -38,15 +36,16 @@  public:
     }
     ~OutBuffer()
     {
-        mem.xfree(data);
+        mem.xfree(data.ptr);
     }
+    const DArray<unsigned char> slice() const { return data; }
+    d_size_t length() const { return offset; }
     char *extractData();
 
     void reserve(size_t nbytes);
     void setsize(size_t size);
     void reset();
     void write(const void *data, d_size_t nbytes);
-    void writebstring(utf8_t *string);
     void writestring(const char *string);
     void prependstring(const char *string);
     void writenl();                     // write newline