@@ -5973,6 +5973,20 @@ final class Parser(AST) : Lexer
59735973 error(" matching `}` expected, not end of file" );
59745974 goto Lerror;
59755975
5976+ static if (IN_GCC )
5977+ {
5978+ case TOKlparen:
5979+ case TOKstring:
5980+ // If the first token is a string or '(', parse as extended asm.
5981+ if (! toklist)
5982+ {
5983+ s = parseExtAsm(stc);
5984+ statements.push(s);
5985+ continue ;
5986+ }
5987+ goto Ldefault;
5988+ }
5989+
59765990 default :
59775991 Ldefault:
59785992 * ptoklist = Token .alloc();
@@ -6019,6 +6033,228 @@ final class Parser(AST) : Lexer
60196033 return s;
60206034 }
60216035
6036+ static if (IN_GCC )
6037+ {
6038+ /* **********************************
6039+ * Parse list of extended asm input or output operands.
6040+ * ExtAsmOperand:
6041+ * [Identifier] StringLiteral (Identifier), ...
6042+ */
6043+ int parseExtAsmOperands (AST .Expressions* args, AST .Identifiers* names, AST .Expressions* constraints)
6044+ {
6045+ int numargs = 0 ;
6046+
6047+ while (1 )
6048+ {
6049+ AST .Expression arg;
6050+ Identifier name;
6051+ AST .Expression constraint;
6052+
6053+ switch (token.value)
6054+ {
6055+ case TOKsemicolon:
6056+ case TOKcolon:
6057+ case TOKeof:
6058+ return numargs;
6059+
6060+ case TOKlbracket:
6061+ nextToken();
6062+ if (token.value == TOKidentifier)
6063+ {
6064+ name = token.ident;
6065+ nextToken();
6066+ }
6067+ else
6068+ {
6069+ error(" expected identifier after '['" );
6070+ return numargs;
6071+ }
6072+ check(TOKrbracket);
6073+ // fall through
6074+
6075+ default :
6076+ constraint = parsePrimaryExp();
6077+ if (constraint.op != TOKstring)
6078+ {
6079+ error(constraint.loc, " expected constant string constraint for operand, not '%s'" , constraint.toChars());
6080+ goto Lerror;
6081+ }
6082+ arg = parseAssignExp();
6083+
6084+ args.push(arg);
6085+ names.push(name);
6086+ constraints.push(constraint);
6087+ numargs++ ;
6088+
6089+ if (token.value == TOKcomma)
6090+ nextToken();
6091+ break ;
6092+
6093+ }
6094+ }
6095+ Lerror:
6096+ while (token.value != TOKrcurly &&
6097+ token.value != TOKsemicolon &&
6098+ token.value != TOKeof)
6099+ nextToken();
6100+
6101+ return numargs;
6102+ }
6103+
6104+ /* **********************************
6105+ * Parse list of extended asm clobbers.
6106+ * ExtAsmClobbers:
6107+ * StringLiteral, ...
6108+ */
6109+ AST .Expressions * parseExtAsmClobbers()
6110+ {
6111+ AST .Expressions * clobbers;
6112+
6113+ while (1 )
6114+ {
6115+ AST .Expression clobber;
6116+
6117+ switch (token.value)
6118+ {
6119+ case TOKsemicolon:
6120+ case TOKcolon:
6121+ case TOKeof:
6122+ return clobbers;
6123+
6124+ case TOKstring:
6125+ clobber = parseAssignExp();
6126+ if (! clobbers)
6127+ clobbers = new AST .Expressions();
6128+ clobbers.push(clobber);
6129+
6130+ if (token.value == TOKcomma)
6131+ nextToken();
6132+ break ;
6133+
6134+ default :
6135+ error(" expected constant string constraint for clobber name, not '%s'" , token.toChars());
6136+ goto Lerror;
6137+ }
6138+ }
6139+ Lerror:
6140+ while (token.value != TOKrcurly &&
6141+ token.value != TOKsemicolon &&
6142+ token.value != TOKeof)
6143+ nextToken();
6144+
6145+ return clobbers;
6146+ }
6147+
6148+ /* **********************************
6149+ * Parse list of extended asm goto labels.
6150+ * ExtAsmGotoLabels:
6151+ * Identifier, ...
6152+ */
6153+ AST .Identifiers * parseExtAsmGotoLabels()
6154+ {
6155+ AST .Identifiers * labels;
6156+
6157+ while (1 )
6158+ {
6159+ switch (token.value)
6160+ {
6161+ case TOKsemicolon:
6162+ case TOKeof:
6163+ return labels;
6164+
6165+ case TOKidentifier:
6166+ if (! labels)
6167+ labels = new AST .Identifiers();
6168+ labels.push(token.ident);
6169+
6170+ if (nextToken() == TOKcomma)
6171+ nextToken();
6172+ break ;
6173+
6174+ default :
6175+ error(" expected identifier for goto label name, not '%s'" , token.toChars());
6176+ goto Lerror;
6177+ }
6178+ }
6179+ Lerror:
6180+ while (token.value != TOKrcurly &&
6181+ token.value != TOKsemicolon &&
6182+ token.value != TOKeof)
6183+ nextToken();
6184+
6185+ return labels;
6186+ }
6187+
6188+ /* **********************************
6189+ * Parse an extended asm statement.
6190+ * ExtAsmStatement:
6191+ * asm { StringLiterals [ : InputOperands [ : OutputOperands [ : Clobbers [ : GotoLabels ] ] ] ] }
6192+ */
6193+
6194+ AST .Statement parseExtAsm (StorageClass stc)
6195+ {
6196+ AST .Expressions * args;
6197+ AST .Identifiers * names;
6198+ AST .Expressions * constraints;
6199+ int outputargs = 0 ;
6200+ AST .Expressions * clobbers;
6201+ AST .Identifiers * labels;
6202+ Loc loc = token.loc;
6203+
6204+ AST .Expression insn = parseExpression();
6205+ if (token.value == TOKsemicolon)
6206+ goto Ldone;
6207+
6208+ for (int section = 0 ; section < 4 ; ++ section)
6209+ {
6210+ check(TOKcolon);
6211+
6212+ final switch (section)
6213+ {
6214+ case 0 :
6215+ if (! args)
6216+ {
6217+ args = new AST .Expressions();
6218+ constraints = new AST .Expressions();
6219+ names = new AST .Identifiers();
6220+ }
6221+ outputargs = parseExtAsmOperands(args, names, constraints);
6222+ break ;
6223+
6224+ case 1 :
6225+ parseExtAsmOperands(args, names, constraints);
6226+ break ;
6227+
6228+ case 2 :
6229+ clobbers = parseExtAsmClobbers();
6230+ break ;
6231+
6232+ case 3 :
6233+ labels = parseExtAsmGotoLabels();
6234+ break ;
6235+ }
6236+
6237+ switch (token.value)
6238+ {
6239+ case TOKsemicolon:
6240+ goto Ldone;
6241+
6242+ case TOKeof:
6243+ error(" matching '}' expected, not end of file" );
6244+ goto Ldone;
6245+
6246+ default :
6247+ continue ;
6248+ }
6249+ }
6250+ Ldone:
6251+ check(TOKsemicolon);
6252+
6253+ return new AST .ExtAsmStatement(loc, stc, insn, args, names,
6254+ constraints, outputargs, clobbers, labels);
6255+ }
6256+ }
6257+
60226258 /* ****************************************
60236259 * Parse initializer for variable declaration.
60246260 */
0 commit comments