]>
git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/iasmgcc.c
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 2018-2020 by The D Language Foundation, All Rights Reserved
4 * written by Iain Buclaw
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/iasmgcc.c
11 /* Inline assembler for the GCC D compiler.
15 #include "declaration.h"
18 #include "statement.h"
20 Expression
*semantic(Expression
*e
, Scope
*sc
);
21 Statement
*semantic(Statement
*s
, Scope
*sc
);
23 /***********************************
24 * Parse list of extended asm input or output operands.
27 * | SymbolicName(opt) StringLiteral ( AssignExpression )
28 * | SymbolicName(opt) StringLiteral ( AssignExpression ), Operands
34 * s = asm statement to parse
36 * number of operands added to the gcc asm statement
38 static int parseExtAsmOperands(Parser
*p
, GccAsmStatement
*s
)
44 Expression
*arg
= NULL
;
45 Identifier
*name
= NULL
;
46 Expression
*constraint
= NULL
;
48 switch (p
->token
.value
)
56 if (p
->peekNext() == TOKidentifier
)
58 // Skip over openings `[`
60 // Store the symbolic name
61 name
= p
->token
.ident
;
66 p
->error(s
->loc
, "expected identifier after `[`");
69 // Look for closing `]`
70 p
->check(TOKrbracket
);
71 // Look for the string literal and fall through
72 if (p
->token
.value
!= TOKstring
)
77 constraint
= p
->parsePrimaryExp();
79 // Old parser allowed omitting parentheses around the expression.
80 // Deprecated in 2.091. Can be made permanent error after 2.100
81 if (p
->token
.value
!= TOKlparen
)
83 arg
= p
->parseAssignExp();
84 deprecation(arg
->loc
, "`%s` must be surrounded by parentheses", arg
->toChars());
88 // Look for the opening `(`
90 // Parse the assign expression
91 arg
= p
->parseAssignExp();
92 // Look for the closing `)`
98 s
->names
= new Identifiers();
99 s
->constraints
= new Expressions();
100 s
->args
= new Expressions();
102 s
->names
->push(name
);
104 s
->constraints
->push(constraint
);
107 if (p
->token
.value
== TOKcomma
)
113 p
->error("expected constant string constraint for operand, not `%s`",
119 while (p
->token
.value
!= TOKrcurly
&&
120 p
->token
.value
!= TOKsemicolon
&&
121 p
->token
.value
!= TOKeof
)
127 /***********************************
128 * Parse list of extended asm clobbers.
132 * | StringLiteral , Clobbers
136 * array of parsed clobber expressions
138 static Expressions
*parseExtAsmClobbers(Parser
*p
)
140 Expressions
*clobbers
= NULL
;
146 switch (p
->token
.value
)
154 clobber
= p
->parsePrimaryExp();
156 clobbers
= new Expressions();
157 clobbers
->push(clobber
);
159 if (p
->token
.value
== TOKcomma
)
164 p
->error("expected constant string constraint for clobber name, not `%s`",
170 while (p
->token
.value
!= TOKrcurly
&&
171 p
->token
.value
!= TOKsemicolon
&&
172 p
->token
.value
!= TOKeof
)
178 /***********************************
179 * Parse list of extended asm goto labels.
183 * | Identifier , GotoLabels
187 * array of parsed goto labels
189 static Identifiers
*parseExtAsmGotoLabels(Parser
*p
)
191 Identifiers
*labels
= NULL
;
195 switch (p
->token
.value
)
203 labels
= new Identifiers();
204 labels
->push(p
->token
.ident
);
206 if (p
->nextToken() == TOKcomma
)
211 p
->error("expected identifier for goto label name, not `%s`",
217 while (p
->token
.value
!= TOKrcurly
&&
218 p
->token
.value
!= TOKsemicolon
&&
219 p
->token
.value
!= TOKeof
)
225 /***********************************
226 * Parse a gcc asm statement.
227 * There are three forms of inline asm statements, basic, extended, and goto.
230 * | BasicAsmInstruction
231 * | ExtAsmInstruction
232 * | GotoAsmInstruction
234 * | BasicAsmInstruction:
237 * | ExtAsmInstruction:
238 * | Expression : Operands(opt) : Operands(opt) : Clobbers(opt)
240 * | GotoAsmInstruction:
241 * | Expression : : Operands(opt) : Clobbers(opt) : GotoLabels(opt)
244 * s = asm statement to parse
246 * the parsed gcc asm statement
248 static GccAsmStatement
*parseGccAsm(Parser
*p
, GccAsmStatement
*s
)
250 s
->insn
= p
->parseExpression();
251 if (p
->token
.value
== TOKsemicolon
|| p
->token
.value
== TOKeof
)
254 // No semicolon followed after instruction template, treat as extended asm.
255 for (int section
= 0; section
< 4; ++section
)
262 s
->outputargs
= parseExtAsmOperands(p
, s
);
266 parseExtAsmOperands(p
, s
);
270 s
->clobbers
= parseExtAsmClobbers(p
);
274 s
->labels
= parseExtAsmGotoLabels(p
);
281 if (p
->token
.value
== TOKsemicolon
|| p
->token
.value
== TOKeof
)
285 p
->check(TOKsemicolon
);
290 /***********************************
291 * Parse and run semantic analysis on a GccAsmStatement.
293 * s = gcc asm statement being parsed
294 * sc = the scope where the asm statement is located
296 * the completed gcc asm statement, or null if errors occurred
298 Statement
*gccAsmSemantic(GccAsmStatement
*s
, Scope
*sc
)
300 //printf("GccAsmStatement::semantic()\n");
301 Parser
p(sc
->_module
, (const utf8_t
*)";", 1, false);
303 // Make a safe copy of the token list before parsing.
304 Token
*toklist
= NULL
;
305 Token
**ptoklist
= &toklist
;
307 for (Token
*token
= s
->tokens
; token
; token
= token
->next
)
309 *ptoklist
= Token::alloc();
310 memcpy(*ptoklist
, token
, sizeof(Token
));
311 ptoklist
= &(*ptoklist
)->next
;
317 // Parse the gcc asm statement.
318 s
= parseGccAsm(&p
, s
);
323 // Fold the instruction template string.
324 s
->insn
= semantic(s
->insn
, sc
);
325 s
->insn
= s
->insn
->ctfeInterpret();
327 if (s
->insn
->op
!= TOKstring
|| ((StringExp
*) s
->insn
)->sz
!= 1)
328 s
->insn
->error("asm instruction template must be a constant char string");
330 if (s
->labels
&& s
->outputargs
)
331 s
->error("extended asm statements with labels cannot have output constraints");
333 // Analyse all input and output operands.
336 for (size_t i
= 0; i
< s
->args
->length
; i
++)
338 Expression
*e
= (*s
->args
)[i
];
340 // Check argument is a valid lvalue/rvalue.
341 if (i
< s
->outputargs
)
342 e
= e
->modifiableLvalue(sc
, NULL
);
343 else if (e
->checkValue())
347 e
= (*s
->constraints
)[i
];
349 assert(e
->op
== TOKstring
&& ((StringExp
*) e
)->sz
== 1);
350 (*s
->constraints
)[i
] = e
;
354 // Analyse all clobbers.
357 for (size_t i
= 0; i
< s
->clobbers
->length
; i
++)
359 Expression
*e
= (*s
->clobbers
)[i
];
361 assert(e
->op
== TOKstring
&& ((StringExp
*) e
)->sz
== 1);
362 (*s
->clobbers
)[i
] = e
;
366 // Analyse all goto labels.
369 for (size_t i
= 0; i
< s
->labels
->length
; i
++)
371 Identifier
*ident
= (*s
->labels
)[i
];
372 GotoStatement
*gs
= new GotoStatement(s
->loc
, ident
);
374 s
->gotos
= new GotoStatements();