annotate gen/asmstmt.cpp @ 302:bef811104734 trunk

[svn r323] Branching out of inline asm works. Renamed emit_finallyblocks to DtoFinallyBlocks and moved to llvmhelpers. Added enclosingtryfinally to AsmBlockStatement, so branches out of asm blocks respect finallys. Refactored some GotoStatement code into DtoGoto.
author ChristianK
date Wed, 25 Jun 2008 20:39:09 +0200
parents f42a1090e895
children 4aa2b6753059
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
1 // Taken from GDC source tree, licence unclear?
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
2 //
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
3 // Taken from an earlier version of DMD -- why is it missing from 0.79?
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
4
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
5 #include "gen/llvm.h"
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
6 #include "llvm/InlineAsm.h"
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
7
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
8 //#include "d-gcc-includes.h"
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
9 //#include "total.h"
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
10 #include "dmd/statement.h"
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
11 #include "dmd/scope.h"
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
12 #include "dmd/declaration.h"
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
13 #include "dmd/dsymbol.h"
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
14
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
15 #include <cassert>
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
16 #include <deque>
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
17 #include <iostream>
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
18 #include <sstream>
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
19 #include <cstring>
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
20
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
21 //#include "d-lang.h"
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
22 //#include "d-codegen.h"
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
23
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
24 #include "gen/irstate.h"
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
25 #include "gen/dvalue.h"
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
26 #include "gen/tollvm.h"
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
27 #include "gen/logger.h"
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
28 #include "gen/todebug.h"
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
29 #include "gen/llvmhelpers.h"
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
30
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
31 typedef enum {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
32 Arg_Integer,
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
33 Arg_Pointer,
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
34 Arg_Memory,
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
35 Arg_FrameRelative,
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
36 Arg_LocalSize,
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
37 Arg_Dollar
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
38 } AsmArgType;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
39
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
40 typedef enum {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
41 Mode_Input,
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
42 Mode_Output,
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
43 Mode_Update
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
44 } AsmArgMode;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
45
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
46 struct AsmArg {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
47 AsmArgType type;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
48 Expression * expr;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
49 AsmArgMode mode;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
50 AsmArg(AsmArgType type, Expression * expr, AsmArgMode mode) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
51 this->type = type;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
52 this->expr = expr;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
53 this->mode = mode;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
54 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
55 };
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
56
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
57 struct AsmCode {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
58 char * insnTemplate;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
59 unsigned insnTemplateLen;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
60 Array args; // of AsmArg
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
61 unsigned moreRegs;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
62 unsigned dollarLabel;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
63 int clobbersMemory;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
64 AsmCode() {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
65 insnTemplate = NULL;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
66 insnTemplateLen = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
67 moreRegs = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
68 dollarLabel = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
69 clobbersMemory = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
70 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
71 };
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
72
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
73 AsmStatement::AsmStatement(Loc loc, Token *tokens) :
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
74 Statement(loc)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
75 {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
76 this->tokens = tokens; // Do I need to copy these?
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
77 asmcode = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
78 asmalign = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
79 refparam = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
80 naked = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
81 regs = 0;
299
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
82
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
83 isBranchToLabel = NULL;
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
84 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
85
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
86 Statement *AsmStatement::syntaxCopy()
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
87 {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
88 // copy tokens? copy 'code'?
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
89 AsmStatement * a_s = new AsmStatement(loc,tokens);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
90 a_s->asmcode = asmcode;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
91 a_s->refparam = refparam;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
92 a_s->naked = naked;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
93 a_s->regs = a_s->regs;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
94 return a_s;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
95 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
96
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
97 void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
98 {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
99 bool sep = 0, nsep = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
100 buf->writestring("asm { ");
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
101
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
102 for (Token * t = tokens; t; t = t->next) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
103 switch (t->value) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
104 case TOKlparen:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
105 case TOKrparen:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
106 case TOKlbracket:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
107 case TOKrbracket:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
108 case TOKcolon:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
109 case TOKsemicolon:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
110 case TOKcomma:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
111 case TOKstring:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
112 case TOKcharv:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
113 case TOKwcharv:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
114 case TOKdcharv:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
115 nsep = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
116 break;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
117 default:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
118 nsep = 1;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
119 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
120 if (sep + nsep == 2)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
121 buf->writeByte(' ');
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
122 sep = nsep;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
123 buf->writestring(t->toChars());
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
124 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
125 buf->writestring("; }");
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
126 buf->writenl();
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
127 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
128
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
129 int AsmStatement::comeFrom()
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
130 {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
131 return FALSE;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
132 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
133
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
134 /* GCC does not support jumps from asm statements. When optimization
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
135 is turned on, labels referenced only from asm statements will not
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
136 be output at the correct location. There are ways around this:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
137
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
138 1) Reference the label with a reachable goto statement
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
139 2) Have reachable computed goto in the function
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
140 3) Hack cfgbuild.c to act as though there is a computed goto.
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
141
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
142 These are all pretty bad, but if would be nice to be able to tell
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
143 GCC not to optimize in this case (even on per label/block basis).
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
144
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
145 The current solution is output our own private labels (as asm
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
146 statements) along with the "real" label. If the label happens to
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
147 be referred to by a goto statement, the "real" label will also be
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
148 output in the correct location.
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
149
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
150 Also had to add 'asmLabelNum' to LabelDsymbol to indicate it needs
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
151 special processing.
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
152
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
153 (junk) d-lang.cc:916:case LABEL_DECL: // C doesn't do this. D needs this for referencing labels in inline assembler since there may be not goto referencing it.
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
154
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
155 */
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
156
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
157 static unsigned d_priv_asm_label_serial = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
158
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
159 // may need to make this target-specific
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
160 static void d_format_priv_asm_label(char * buf, unsigned n)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
161 {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
162 //ASM_GENERATE_INTERNAL_LABEL(buf, "LDASM", n);//inserts a '*' for use with assemble_name
234
9760f54af0b7 [svn r250] Fixed the warning about dropping arguments to _Dmain when optimizing.
lindquist
parents: 233
diff changeset
163 assert(0);
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
164 sprintf(buf, ".LDASM%u", n);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
165 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
166
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
167 void
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
168 d_expand_priv_asm_label(IRState * irs, unsigned n)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
169 {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
170 /* char buf[64];
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
171 d_format_priv_asm_label(buf, n);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
172 strcat(buf, ":");
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
173 tree insnt = build_string(strlen(buf), buf);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
174 #if D_GCC_VER < 40
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
175 expand_asm(insnt, 1);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
176 #else
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
177 tree t = d_build_asm_stmt(insnt, NULL_TREE, NULL_TREE, NULL_TREE);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
178 ASM_VOLATILE_P( t ) = 1;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
179 ASM_INPUT_P( t) = 1; // what is this doing?
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
180 irs->addExp(t);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
181 #endif*/
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
182 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
183
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
184
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
185 // StringExp::toIR usually adds a NULL. We don't want that...
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
186
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
187 /*static tree
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
188 naturalString(Expression * e)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
189 {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
190 // don't fail, just an error?
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
191 assert(e->op == TOKstring);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
192 StringExp * s = (StringExp *) e;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
193 assert(s->sz == 1);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
194 return build_string(s->len, (char *) s->string);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
195 }*/
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
196
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
197
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
198 #include "d-asm-i386.h"
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
199
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
200 bool d_have_inline_asm() { return true; }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
201
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
202 Statement *AsmStatement::semantic(Scope *sc)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
203 {
237
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
204 bool err = false;
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
205 if (global.params.cpu != ARCHx86)
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
206 {
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
207 error("inline asm is not supported for the \"%s\" architecture", global.params.llvmArch);
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
208 err = true;
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
209 }
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
210 if (!global.params.useInlineAsm)
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
211 {
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
212 error("inline asm is not allowed when the -noasm switch is used");
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
213 err = true;
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
214 }
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
215 if (err)
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
216 fatal();
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
217
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
218 sc->func->inlineAsm = 1;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
219 sc->func->inlineStatus = ILSno; // %% not sure
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
220 // %% need to set DECL_UNINLINABLE too?
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
221 sc->func->hasReturnExp = 1; // %% DMD does this, apparently...
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
222
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
223 // empty statement -- still do the above things because they might be expected?
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
224 if (! tokens)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
225 return this;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
226
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
227 AsmProcessor ap(sc, this);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
228 ap.run();
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
229 return this;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
230 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
231
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
232 void
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
233 AsmStatement::toIR(IRState * irs)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
234 {
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
235 Logger::println("AsmStatement::toIR(): %s", loc.toChars());
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
236 LOG_SCOPE;
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
237
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
238 // get asm block
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
239 IRAsmBlock* asmblock = irs->asmBlock;
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
240 assert(asmblock);
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
241
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
242 // debug info
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
243 if (global.params.symdebug)
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
244 DtoDwarfStopPoint(loc.linnum);
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
245
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
246 if (! asmcode)
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
247 return;
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
248
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
249 static std::string i_cns = "i";
231
61aa721a6b7f [svn r247] fixed accessing global symbols from inline asm.
lindquist
parents: 229
diff changeset
250 static std::string p_cns = "i";
222
251548c1035d [svn r238] use *m for memory input constraints and pass in their address
ChristianK
parents: 221
diff changeset
251 static std::string m_cns = "*m";
221
68687d8c3e9a [svn r237] some inline asm output now seems to work, see tangotests/asm2.d
lindquist
parents: 220
diff changeset
252 static std::string mw_cns = "=*m";
223
5ffca623b5df [svn r239] also use indirect modifier for update constraints
ChristianK
parents: 222
diff changeset
253 static std::string mrw_cns = "+*m";
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
254 static std::string memory_name = "memory";
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
255
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
256 AsmCode * code = (AsmCode *) asmcode;
229
cac3d27ae481 [svn r245] initial support for labels in inline asm, broken :/
lindquist
parents: 227
diff changeset
257 std::deque<LLValue*> input_values;
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
258 std::deque<std::string> input_constraints;
229
cac3d27ae481 [svn r245] initial support for labels in inline asm, broken :/
lindquist
parents: 227
diff changeset
259 std::deque<LLValue*> output_values;
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
260 std::deque<std::string> output_constraints;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
261 std::deque<std::string> clobbers;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
262
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
263 // FIXME
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
264 #define HOST_WIDE_INT long
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
265 HOST_WIDE_INT var_frame_offset; // "frame_offset" is a macro
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
266 bool clobbers_mem = code->clobbersMemory;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
267 int input_idx = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
268 int n_outputs = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
269 int arg_map[10];
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
270
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
271 assert(code->args.dim <= 10);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
272
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
273 for (unsigned i = 0; i < code->args.dim; i++) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
274 AsmArg * arg = (AsmArg *) code->args.data[i];
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
275
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
276 bool is_input = true;
229
cac3d27ae481 [svn r245] initial support for labels in inline asm, broken :/
lindquist
parents: 227
diff changeset
277 LLValue* arg_val = 0;
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
278 std::string cns;
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
279
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
280 switch (arg->type) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
281 case Arg_Integer:
229
cac3d27ae481 [svn r245] initial support for labels in inline asm, broken :/
lindquist
parents: 227
diff changeset
282 arg_val = arg->expr->toElem(irs)->getRVal();
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
283 do_integer:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
284 cns = i_cns;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
285 break;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
286 case Arg_Pointer:
234
9760f54af0b7 [svn r250] Fixed the warning about dropping arguments to _Dmain when optimizing.
lindquist
parents: 233
diff changeset
287 assert(arg->expr->op == TOKvar);
9760f54af0b7 [svn r250] Fixed the warning about dropping arguments to _Dmain when optimizing.
lindquist
parents: 233
diff changeset
288 arg_val = arg->expr->toElem(irs)->getRVal();
9760f54af0b7 [svn r250] Fixed the warning about dropping arguments to _Dmain when optimizing.
lindquist
parents: 233
diff changeset
289 cns = p_cns;
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
290
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
291 break;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
292 case Arg_Memory:
229
cac3d27ae481 [svn r245] initial support for labels in inline asm, broken :/
lindquist
parents: 227
diff changeset
293 arg_val = arg->expr->toElem(irs)->getRVal();
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
294
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
295 switch (arg->mode) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
296 case Mode_Input: cns = m_cns; break;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
297 case Mode_Output: cns = mw_cns; is_input = false; break;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
298 case Mode_Update: cns = mrw_cns; is_input = false; break;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
299 default: assert(0); break;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
300 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
301 break;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
302 case Arg_FrameRelative:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
303 // FIXME
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
304 std::cout << "asm fixme Arg_FrameRelative" << std::endl;
229
cac3d27ae481 [svn r245] initial support for labels in inline asm, broken :/
lindquist
parents: 227
diff changeset
305 assert(0);
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
306 /* if (arg->expr->op == TOKvar)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
307 arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
308 else
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
309 assert(0);*/
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
310 if ( getFrameRelativeValue(arg_val, & var_frame_offset) ) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
311 // arg_val = irs->integerConstant(var_frame_offset);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
312 cns = i_cns;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
313 } else {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
314 this->error("%s", "argument not frame relative");
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
315 return;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
316 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
317 if (arg->mode != Mode_Input)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
318 clobbers_mem = true;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
319 break;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
320 case Arg_LocalSize:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
321 // FIXME
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
322 std::cout << "asm fixme Arg_LocalSize" << std::endl;
229
cac3d27ae481 [svn r245] initial support for labels in inline asm, broken :/
lindquist
parents: 227
diff changeset
323 assert(0);
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
324 /* var_frame_offset = cfun->x_frame_offset;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
325 if (var_frame_offset < 0)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
326 var_frame_offset = - var_frame_offset;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
327 arg_val = irs->integerConstant( var_frame_offset );*/
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
328 goto do_integer;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
329 default:
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
330 assert(0);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
331 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
332
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
333 if (is_input) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
334 arg_map[i] = --input_idx;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
335 //inputs.cons(tree_cons(NULL_TREE, cns, NULL_TREE), arg_val);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
336 input_values.push_back(arg_val);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
337 input_constraints.push_back(cns);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
338 } else {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
339 arg_map[i] = n_outputs++;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
340 //outputs.cons(tree_cons(NULL_TREE, cns, NULL_TREE), arg_val);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
341 output_values.push_back(arg_val);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
342 output_constraints.push_back(cns);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
343 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
344 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
345
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
346 // Telling GCC that callee-saved registers are clobbered makes it preserve
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
347 // those registers. This changes the stack from what a naked function
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
348 // expects.
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
349
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
350 // FIXME
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
351 // if (! irs->func->naked) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
352 for (int i = 0; i < 32; i++) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
353 if (regs & (1 << i)) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
354 //clobbers.cons(NULL_TREE, regInfo[i].gccName);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
355 clobbers.push_back(regInfo[i].gccName);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
356 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
357 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
358 for (int i = 0; i < 32; i++) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
359 if (code->moreRegs & (1 << (i-32))) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
360 //clobbers.cons(NULL_TREE, regInfo[i].gccName);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
361 clobbers.push_back(regInfo[i].gccName);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
362 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
363 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
364 if (clobbers_mem)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
365 clobbers.push_back(memory_name);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
366 //clobbers.cons(NULL_TREE, memory_name);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
367 // }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
368
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
369
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
370 // Remap argument numbers
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
371 for (unsigned i = 0; i < code->args.dim; i++) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
372 if (arg_map[i] < 0)
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
373 arg_map[i] = -arg_map[i] - 1 + n_outputs;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
374 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
375
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
376 bool pct = false;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
377 char * p = code->insnTemplate;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
378 char * q = p + code->insnTemplateLen;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
379 //printf("start: %.*s\n", code->insnTemplateLen, code->insnTemplate);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
380 while (p < q) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
381 if (pct) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
382 if (*p >= '0' && *p <= '9') {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
383 // %% doesn't check against nargs
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
384 *p = '0' + arg_map[*p - '0'];
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
385 pct = false;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
386 } else if (*p == '$') {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
387 pct = false;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
388 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
389 //assert(*p == '%');// could be 'a', etc. so forget it..
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
390 } else if (*p == '$')
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
391 pct = true;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
392 ++p;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
393 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
394
237
a168a2c3ea48 [svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents: 234
diff changeset
395 Logger::println("final asm: %.*s", code->insnTemplateLen, code->insnTemplate);
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
396
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
397 std::string insnt(code->insnTemplate, code->insnTemplateLen);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
398
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
399 // rewrite GCC-style constraints to LLVM-style constraints
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
400 std::string llvmOutConstraints;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
401 std::string llvmInConstraints;
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
402 int n = 0;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
403 typedef std::deque<std::string>::iterator it;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
404 for(it i = output_constraints.begin(), e = output_constraints.end(); i != e; ++i, ++n) {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
405 // rewrite update constraint to in and out constraints
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
406 if((*i)[0] == '+') {
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
407 (*i)[0] = '=';
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
408 std::string input_constraint;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
409 std::stringstream ss;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
410 ss << n;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
411 ss >> input_constraint;
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
412 //FIXME: I think multiple inout constraints will mess up the order!
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
413 input_constraints.push_front(input_constraint);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
414 input_values.push_front(output_values[n]);
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
415 }
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
416 llvmOutConstraints += *i;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
417 llvmOutConstraints += ",";
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
418 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
419 for(it i = input_constraints.begin(), e = input_constraints.end(); i != e; ++i) {
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
420 llvmInConstraints += *i;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
421 llvmInConstraints += ",";
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
422 }
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
423
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
424 std::string clobstr;
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
425 for(it i = clobbers.begin(), e = clobbers.end(); i != e; ++i) {
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
426 clobstr = "~{" + *i + "},";
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
427 asmblock->clobs.insert(clobstr);
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
428 }
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
429
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
430 // excessive commas are removed later...
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
431
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
432 // push asm statement
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
433 IRAsmStmt* asmStmt = new IRAsmStmt;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
434 asmStmt->code = insnt;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
435 asmStmt->out_c = llvmOutConstraints;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
436 asmStmt->in_c = llvmInConstraints;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
437 asmStmt->out.insert(asmStmt->out.begin(), output_values.begin(), output_values.end());
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
438 asmStmt->in.insert(asmStmt->in.begin(), input_values.begin(), input_values.end());
299
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
439 asmStmt->isBranchToLabel = isBranchToLabel;
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
440 asmblock->s.push_back(asmStmt);
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
441 }
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
442
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
443 //////////////////////////////////////////////////////////////////////////////
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
444
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
445 AsmBlockStatement::AsmBlockStatement(Loc loc, Statements* s)
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
446 : CompoundStatement(loc, s)
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
447 {
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
448 enclosingtryfinally = NULL;
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
449 }
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
450
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
451 // rewrite argument indices to the block scope indices
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
452 static void remap_outargs(std::string& insnt, size_t nargs, size_t& idx)
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
453 {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
454 static const std::string digits[10] =
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
455 {
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
456 "0","1","2","3","4",
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
457 "5","6","7","8","9"
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
458 };
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
459 assert(nargs <= 10);
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
460
234
9760f54af0b7 [svn r250] Fixed the warning about dropping arguments to _Dmain when optimizing.
lindquist
parents: 233
diff changeset
461 static const std::string prefix("<<out");
9760f54af0b7 [svn r250] Fixed the warning about dropping arguments to _Dmain when optimizing.
lindquist
parents: 233
diff changeset
462 static const std::string suffix(">>");
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
463 std::string argnum;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
464 std::string needle;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
465 char buf[10];
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
466 for (unsigned i = 0; i < nargs; i++) {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
467 needle = prefix + digits[i] + suffix;
300
7b1040c76dd2 [svn r321] Fix bug in argument remapping functions.
ChristianK
parents: 299
diff changeset
468 size_t pos = insnt.find(needle);
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
469 if(std::string::npos != pos)
300
7b1040c76dd2 [svn r321] Fix bug in argument remapping functions.
ChristianK
parents: 299
diff changeset
470 sprintf(buf, "%u", idx++);
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
471 while(std::string::npos != (pos = insnt.find(needle)))
300
7b1040c76dd2 [svn r321] Fix bug in argument remapping functions.
ChristianK
parents: 299
diff changeset
472 insnt.replace(pos, needle.size(), buf);
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
473 }
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
474 }
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
475
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
476 // rewrite argument indices to the block scope indices
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
477 static void remap_inargs(std::string& insnt, size_t nargs, size_t& idx)
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
478 {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
479 static const std::string digits[10] =
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
480 {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
481 "0","1","2","3","4",
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
482 "5","6","7","8","9"
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
483 };
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
484 assert(nargs <= 10);
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
485
234
9760f54af0b7 [svn r250] Fixed the warning about dropping arguments to _Dmain when optimizing.
lindquist
parents: 233
diff changeset
486 static const std::string prefix("<<in");
9760f54af0b7 [svn r250] Fixed the warning about dropping arguments to _Dmain when optimizing.
lindquist
parents: 233
diff changeset
487 static const std::string suffix(">>");
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
488 std::string argnum;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
489 std::string needle;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
490 char buf[10];
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
491 for (unsigned i = 0; i < nargs; i++) {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
492 needle = prefix + digits[i] + suffix;
300
7b1040c76dd2 [svn r321] Fix bug in argument remapping functions.
ChristianK
parents: 299
diff changeset
493 size_t pos = insnt.find(needle);
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
494 if(std::string::npos != pos)
300
7b1040c76dd2 [svn r321] Fix bug in argument remapping functions.
ChristianK
parents: 299
diff changeset
495 sprintf(buf, "%u", idx++);
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
496 while(std::string::npos != (pos = insnt.find(needle)))
300
7b1040c76dd2 [svn r321] Fix bug in argument remapping functions.
ChristianK
parents: 299
diff changeset
497 insnt.replace(pos, needle.size(), buf);
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
498 }
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
499 }
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
500
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
501 void AsmBlockStatement::toIR(IRState* p)
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
502 {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
503 Logger::println("AsmBlockStatement::toIR(): %s", loc.toChars());
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
504 LOG_SCOPE;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
505 Logger::println("BEGIN ASM");
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
506
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
507 // create asm block structure
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
508 assert(!p->asmBlock);
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
509 IRAsmBlock* asmblock = new IRAsmBlock;
239
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
510 assert(asmblock);
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
511 p->asmBlock = asmblock;
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
512
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
513 // do asm statements
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
514 for (int i=0; i<statements->dim; i++)
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
515 {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
516 Statement* s = (Statement*)statements->data[i];
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
517 if (s) {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
518 s->toIR(p);
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
519 }
220
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
520 }
ccc2e6898a78 [svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents: 219
diff changeset
521
299
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
522 // build forwarder for in-asm branches to external labels
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
523 // this additional asm code sets the __llvm_jump_target variable
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
524 // to a unique value that will identify the jump target in
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
525 // a post-asm switch
300
7b1040c76dd2 [svn r321] Fix bug in argument remapping functions.
ChristianK
parents: 299
diff changeset
526
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
527 // maps each special value to a goto destination
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
528 std::map<int, LabelDsymbol*> valToGoto;
300
7b1040c76dd2 [svn r321] Fix bug in argument remapping functions.
ChristianK
parents: 299
diff changeset
529
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
530 // location of the value containing the index into the valToGoto map
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
531 // will be set if post-asm dispatcher block is needed
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
532 llvm::AllocaInst* jump_target;
301
f42a1090e895 [svn r322] More asm-to-outside jumping work. Unfinished.
ChristianK
parents: 300
diff changeset
533
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
534 {
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
535 // initialize the setter statement we're going to build
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
536 IRAsmStmt* outSetterStmt = new IRAsmStmt;
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
537 std::string asmGotoEnd = "jmp __llvm_asm_end ; ";
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
538 std::ostringstream code;
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
539 code << asmGotoEnd;
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
540
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
541 int n_goto = 1;
299
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
542
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
543 size_t n = asmblock->s.size();
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
544 for(size_t i=0; i<n; ++i)
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
545 {
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
546 IRAsmStmt* a = asmblock->s[i];
299
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
547
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
548 // skip non-branch statements
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
549 if(!a->isBranchToLabel)
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
550 continue;
299
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
551
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
552 // if internal, no special handling is necessary, skip
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
553 std::vector<Identifier*>::const_iterator it, end;
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
554 end = asmblock->internalLabels.end();
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
555 bool skip = false;
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
556 for(it = asmblock->internalLabels.begin(); it != end; ++it)
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
557 if((*it)->equals(a->isBranchToLabel->ident))
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
558 skip = true;
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
559 if(skip)
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
560 continue;
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
561
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
562 // record that the jump needs to be handled in the post-asm dispatcher
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
563 valToGoto[n_goto] = a->isBranchToLabel;
299
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
564
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
565 // provide an in-asm target for the branch and set value
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
566 Logger::println("statement '%s' references outer label '%s': creating forwarder", a->code.c_str(), a->isBranchToLabel->ident->string);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
567 code << a->isBranchToLabel->ident->string << ": ; ";
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
568 code << "movl $<<in" << n_goto << ">>, $<<out0>> ; ";
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
569 //FIXME: Store the value -> label mapping somewhere, so it can be referenced later
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
570 outSetterStmt->in.push_back(llvm::ConstantInt::get(llvm::IntegerType::get(32), n_goto));
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
571 outSetterStmt->in_c += "i,";
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
572 code << asmGotoEnd;
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
573
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
574 ++n_goto;
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
575 }
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
576 if(code.str() != asmGotoEnd)
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
577 {
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
578 // finalize code
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
579 outSetterStmt->code = code.str();
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
580 outSetterStmt->code += "__llvm_asm_end: ; ";
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
581
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
582 // create storage for and initialize the temporary
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
583 jump_target = new llvm::AllocaInst(llvm::IntegerType::get(32), "__llvm_jump_target", p->topallocapoint());
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
584 gIR->ir->CreateStore(llvm::ConstantInt::get(llvm::IntegerType::get(32), 0), jump_target);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
585 // setup variable for output from asm
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
586 outSetterStmt->out_c = "=*m,";
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
587 outSetterStmt->out.push_back(jump_target);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
588
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
589 asmblock->s.push_back(outSetterStmt);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
590 }
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
591 else
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
592 delete outSetterStmt;
299
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
593 }
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
594
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
595
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
596 // build asm block
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
597 std::vector<LLValue*> outargs;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
598 std::vector<LLValue*> inargs;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
599 std::vector<const LLType*> outtypes;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
600 std::vector<const LLType*> intypes;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
601 std::string out_c;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
602 std::string in_c;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
603 std::string clobbers;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
604 std::string code;
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
605 size_t asmIdx = 0;
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
606
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
607 size_t n = asmblock->s.size();
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
608 for (size_t i=0; i<n; ++i)
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
609 {
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
610 IRAsmStmt* a = asmblock->s[i];
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
611 assert(a);
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
612 size_t onn = a->out.size();
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
613 for (size_t j=0; j<onn; ++j)
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
614 {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
615 outargs.push_back(a->out[j]);
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
616 outtypes.push_back(a->out[j]->getType());
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
617 }
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
618 if (!a->out_c.empty())
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
619 {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
620 out_c += a->out_c;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
621 }
300
7b1040c76dd2 [svn r321] Fix bug in argument remapping functions.
ChristianK
parents: 299
diff changeset
622 remap_outargs(a->code, onn+a->in.size(), asmIdx);
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
623 }
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
624 for (size_t i=0; i<n; ++i)
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
625 {
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
626 IRAsmStmt* a = asmblock->s[i];
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
627 assert(a);
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
628 size_t inn = a->in.size();
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
629 for (size_t j=0; j<inn; ++j)
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
630 {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
631 inargs.push_back(a->in[j]);
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
632 intypes.push_back(a->in[j]->getType());
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
633 }
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
634 if (!a->in_c.empty())
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
635 {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
636 in_c += a->in_c;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
637 }
300
7b1040c76dd2 [svn r321] Fix bug in argument remapping functions.
ChristianK
parents: 299
diff changeset
638 remap_inargs(a->code, inn+a->out.size(), asmIdx);
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
639 if (!code.empty())
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
640 code += " ; ";
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
641 code += a->code;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
642 }
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
643 asmblock->s.clear();
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
644
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
645 // append inputs
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
646 out_c += in_c;
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
647
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
648 // append clobbers
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
649 typedef std::set<std::string>::iterator clobs_it;
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
650 for (clobs_it i=asmblock->clobs.begin(); i!=asmblock->clobs.end(); ++i)
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
651 {
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
652 out_c += *i;
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
653 }
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
654
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
655 // remove excessive comma
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
656 if (!out_c.empty())
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
657 out_c.resize(out_c.size()-1);
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
658
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
659 Logger::println("code = \"%s\"", code.c_str());
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
660 Logger::println("constraints = \"%s\"", out_c.c_str());
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
661
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
662 std::vector<const LLType*> types;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
663 types.insert(types.end(), outtypes.begin(), outtypes.end());
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
664 types.insert(types.end(), intypes.begin(), intypes.end());
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
665 llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, types, false);
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
666 Logger::cout() << "function type = " << *fty << '\n';
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
667 llvm::InlineAsm* ia = llvm::InlineAsm::get(fty, code, out_c, true);
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
668
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
669 std::vector<LLValue*> args;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
670 args.insert(args.end(), outargs.begin(), outargs.end());
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
671 args.insert(args.end(), inargs.begin(), inargs.end());
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
672 llvm::CallInst* call = p->ir->CreateCall(ia, args.begin(), args.end(), "");
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
673
233
76ee1bbe487e [svn r249] Changed inline asm clobbers to a set instead of a list so we don't get duplicate clobbers.
lindquist
parents: 232
diff changeset
674 p->asmBlock = NULL;
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
675 Logger::println("END ASM");
299
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
676
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
677 // if asm contained external branches, emit goto forwarder code
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
678 if(!valToGoto.empty())
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
679 {
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
680 assert(jump_target);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
681
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
682 // make new blocks
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
683 llvm::BasicBlock* oldend = gIR->scopeend();
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
684 llvm::BasicBlock* bb = llvm::BasicBlock::Create("afterasmgotoforwarder", p->topfunc(), oldend);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
685
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
686 llvm::LoadInst* val = p->ir->CreateLoad(jump_target, "__llvm_jump_target_value");
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
687 llvm::SwitchInst* sw = p->ir->CreateSwitch(val, bb, valToGoto.size());
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
688
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
689 // add all cases
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
690 std::map<int, LabelDsymbol*>::iterator it, end = valToGoto.end();
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
691 for(it = valToGoto.begin(); it != end; ++it)
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
692 {
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
693 llvm::BasicBlock* casebb = llvm::BasicBlock::Create("case", p->topfunc(), bb);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
694 sw->addCase(llvm::ConstantInt::get(llvm::IntegerType::get(32), it->first), casebb);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
695
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
696 p->scope() = IRScope(casebb,bb);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
697 DtoGoto(&loc, it->second, enclosingtryfinally);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
698 }
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
699
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
700 p->scope() = IRScope(bb,oldend);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
701 }
219
761c8352f494 [svn r235] rough port of GDC's inline assembler code, unfinished
ChristianK
parents:
diff changeset
702 }
232
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
703
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
704 // the whole idea of this statement is to avoid the flattening
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
705 Statements* AsmBlockStatement::flatten(Scope* sc)
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
706 {
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
707 return NULL;
092468448d25 [svn r248] Fixed: labels in inline asm block now work for the normal case.
lindquist
parents: 231
diff changeset
708 }
239
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
709
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
710 Statement *AsmBlockStatement::syntaxCopy()
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
711 {
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
712 Statements *a = new Statements();
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
713 a->setDim(statements->dim);
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
714 for (size_t i = 0; i < statements->dim; i++)
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
715 {
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
716 Statement *s = (Statement *)statements->data[i];
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
717 if (s)
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
718 s = s->syntaxCopy();
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
719 a->data[i] = s;
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
720 }
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
721 AsmBlockStatement *cs = new AsmBlockStatement(loc, a);
fa691b1c0498 [svn r256] AsmBlockStatement was still being flattened in some cases.
lindquist
parents: 237
diff changeset
722 return cs;
299
df8a7b8d5929 [svn r320] Begun work on branches out of asm blocks. Unfinished.
ChristianK
parents: 239
diff changeset
723 }
302
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
724
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
725 // necessary for in-asm branches
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
726 Statement *AsmBlockStatement::semantic(Scope *sc)
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
727 {
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
728 enclosingtryfinally = sc->tfOfTry;
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
729
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
730 return CompoundStatement::semantic(sc);
bef811104734 [svn r323] Branching out of inline asm works.
ChristianK
parents: 301
diff changeset
731 }