]>
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 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"
17 #include "statement.h"
19 Expression
*semantic(Expression
*e
, Scope
*sc
);
20 Statement
*semantic(Statement
*s
, Scope
*sc
);
22 /***********************************
23 * Parse list of extended asm input or output operands.
26 * | SymbolicName(opt) StringLiteral AssignExpression
27 * | SymbolicName(opt) StringLiteral AssignExpression , Operands
33 * s = asm statement to parse
35 * number of operands added to the gcc asm statement
37 static int parseExtAsmOperands(Parser
*p
, GccAsmStatement
*s
)
43 Expression
*arg
= NULL
;
44 Identifier
*name
= NULL
;
45 Expression
*constraint
= NULL
;
47 switch (p
->token
.value
)
55 if (p
->peekNext() == TOKidentifier
)
58 name
= p
->token
.ident
;
63 p
->error(s
->loc
, "expected identifier after `[`");
66 p
->check(TOKrbracket
);
70 constraint
= p
->parsePrimaryExp();
71 arg
= p
->parseAssignExp();
75 s
->names
= new Identifiers();
76 s
->constraints
= new Expressions();
77 s
->args
= new Expressions();
81 s
->constraints
->push(constraint
);
84 if (p
->token
.value
== TOKcomma
)
89 p
->error("expected constant string constraint for operand, not `%s`",
95 while (p
->token
.value
!= TOKrcurly
&&
96 p
->token
.value
!= TOKsemicolon
&&
97 p
->token
.value
!= TOKeof
)
103 /***********************************
104 * Parse list of extended asm clobbers.
108 * | StringLiteral , Clobbers
112 * array of parsed clobber expressions
114 static Expressions
*parseExtAsmClobbers(Parser
*p
)
116 Expressions
*clobbers
= NULL
;
122 switch (p
->token
.value
)
130 clobber
= p
->parsePrimaryExp();
132 clobbers
= new Expressions();
133 clobbers
->push(clobber
);
135 if (p
->token
.value
== TOKcomma
)
140 p
->error("expected constant string constraint for clobber name, not `%s`",
146 while (p
->token
.value
!= TOKrcurly
&&
147 p
->token
.value
!= TOKsemicolon
&&
148 p
->token
.value
!= TOKeof
)
154 /***********************************
155 * Parse list of extended asm goto labels.
159 * | Identifier , GotoLabels
163 * array of parsed goto labels
165 static Identifiers
*parseExtAsmGotoLabels(Parser
*p
)
167 Identifiers
*labels
= NULL
;
171 switch (p
->token
.value
)
179 labels
= new Identifiers();
180 labels
->push(p
->token
.ident
);
182 if (p
->nextToken() == TOKcomma
)
187 p
->error("expected identifier for goto label name, not `%s`",
193 while (p
->token
.value
!= TOKrcurly
&&
194 p
->token
.value
!= TOKsemicolon
&&
195 p
->token
.value
!= TOKeof
)
201 /***********************************
202 * Parse a gcc asm statement.
203 * There are three forms of inline asm statements, basic, extended, and goto.
206 * | BasicAsmInstruction
207 * | ExtAsmInstruction
208 * | GotoAsmInstruction
210 * | BasicAsmInstruction:
213 * | ExtAsmInstruction:
214 * | Expression : Operands(opt) : Operands(opt) : Clobbers(opt)
216 * | GotoAsmInstruction:
217 * | Expression : : Operands(opt) : Clobbers(opt) : GotoLabels(opt)
220 * s = asm statement to parse
222 * the parsed gcc asm statement
224 static GccAsmStatement
*parseGccAsm(Parser
*p
, GccAsmStatement
*s
)
226 s
->insn
= p
->parseExpression();
227 if (p
->token
.value
== TOKsemicolon
)
230 // No semicolon followed after instruction template, treat as extended asm.
231 for (int section
= 0; section
< 4; ++section
)
238 s
->outputargs
= parseExtAsmOperands(p
, s
);
242 parseExtAsmOperands(p
, s
);
246 s
->clobbers
= parseExtAsmClobbers(p
);
250 s
->labels
= parseExtAsmGotoLabels(p
);
257 if (p
->token
.value
== TOKsemicolon
)
261 p
->check(TOKsemicolon
);
266 /***********************************
267 * Parse and run semantic analysis on a GccAsmStatement.
269 * s = gcc asm statement being parsed
270 * sc = the scope where the asm statement is located
272 * the completed gcc asm statement, or null if errors occurred
274 Statement
*gccAsmSemantic(GccAsmStatement
*s
, Scope
*sc
)
276 //printf("GccAsmStatement::semantic()\n");
277 Parser
p(sc
->_module
, (const utf8_t
*)";", 1, false);
279 // Make a safe copy of the token list before parsing.
280 Token
*toklist
= NULL
;
281 Token
**ptoklist
= &toklist
;
283 for (Token
*token
= s
->tokens
; token
; token
= token
->next
)
285 *ptoklist
= Token::alloc();
286 memcpy(*ptoklist
, token
, sizeof(Token
));
287 ptoklist
= &(*ptoklist
)->next
;
292 // Parse the gcc asm statement.
293 s
= parseGccAsm(&p
, s
);
298 // Fold the instruction template string.
299 s
->insn
= semantic(s
->insn
, sc
);
300 s
->insn
= s
->insn
->ctfeInterpret();
302 if (s
->insn
->op
!= TOKstring
|| ((StringExp
*) s
->insn
)->sz
!= 1)
303 s
->insn
->error("asm instruction template must be a constant char string");
305 if (s
->labels
&& s
->outputargs
)
306 s
->error("extended asm statements with labels cannot have output constraints");
308 // Analyse all input and output operands.
311 for (size_t i
= 0; i
< s
->args
->dim
; i
++)
313 Expression
*e
= (*s
->args
)[i
];
315 // Check argument is a valid lvalue/rvalue.
316 if (i
< s
->outputargs
)
317 e
= e
->modifiableLvalue(sc
, NULL
);
318 else if (e
->checkValue())
322 e
= (*s
->constraints
)[i
];
324 assert(e
->op
== TOKstring
&& ((StringExp
*) e
)->sz
== 1);
325 (*s
->constraints
)[i
] = e
;
329 // Analyse all clobbers.
332 for (size_t i
= 0; i
< s
->clobbers
->dim
; i
++)
334 Expression
*e
= (*s
->clobbers
)[i
];
336 assert(e
->op
== TOKstring
&& ((StringExp
*) e
)->sz
== 1);
337 (*s
->clobbers
)[i
] = e
;
341 // Analyse all goto labels.
344 for (size_t i
= 0; i
< s
->labels
->dim
; i
++)
346 Identifier
*ident
= (*s
->labels
)[i
];
347 GotoStatement
*gs
= new GotoStatement(s
->loc
, ident
);
349 s
->gotos
= new GotoStatements();