Mercurial > projects > ldc
comparison gen/asmstmt.cpp @ 1650:40bd4a0d4870
Update to work with LLVM 2.7.
Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).
Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.
Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | 8d086d552909 |
children |
comparison
equal
deleted
inserted
replaced
1649:36da40ecbbe0 | 1650:40bd4a0d4870 |
---|---|
92 | 92 |
93 void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 93 void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
94 { | 94 { |
95 bool sep = 0, nsep = 0; | 95 bool sep = 0, nsep = 0; |
96 buf->writestring("asm { "); | 96 buf->writestring("asm { "); |
97 | 97 |
98 for (Token * t = tokens; t; t = t->next) { | 98 for (Token * t = tokens; t; t = t->next) { |
99 switch (t->value) { | 99 switch (t->value) { |
100 case TOKlparen: | 100 case TOKlparen: |
101 case TOKrparen: | 101 case TOKrparen: |
102 case TOKlbracket: | 102 case TOKlbracket: |
103 case TOKrbracket: | 103 case TOKrbracket: |
159 | 159 |
160 sc->func->inlineAsm = 1; | 160 sc->func->inlineAsm = 1; |
161 sc->func->inlineStatus = ILSno; // %% not sure | 161 sc->func->inlineStatus = ILSno; // %% not sure |
162 // %% need to set DECL_UNINLINABLE too? | 162 // %% need to set DECL_UNINLINABLE too? |
163 sc->func->hasReturnExp = 1; // %% DMD does this, apparently... | 163 sc->func->hasReturnExp = 1; // %% DMD does this, apparently... |
164 | 164 |
165 // empty statement -- still do the above things because they might be expected? | 165 // empty statement -- still do the above things because they might be expected? |
166 if (! tokens) | 166 if (! tokens) |
167 return this; | 167 return this; |
168 | 168 |
169 if (!asmparser) | 169 if (!asmparser) |
170 if (global.params.cpu == ARCHx86) | 170 if (global.params.cpu == ARCHx86) |
171 asmparser = new AsmParserx8632::AsmParser; | 171 asmparser = new AsmParserx8632::AsmParser; |
172 else if (global.params.cpu == ARCHx86_64) | 172 else if (global.params.cpu == ARCHx86_64) |
173 asmparser = new AsmParserx8664::AsmParser; | 173 asmparser = new AsmParserx8664::AsmParser; |
194 | 194 |
195 // get asm block | 195 // get asm block |
196 IRAsmBlock* asmblock = irs->asmBlock; | 196 IRAsmBlock* asmblock = irs->asmBlock; |
197 assert(asmblock); | 197 assert(asmblock); |
198 | 198 |
199 #ifndef DISABLE_DEBUG_INFO | |
199 // debug info | 200 // debug info |
200 if (global.params.symdebug) | 201 if (global.params.symdebug) |
201 DtoDwarfStopPoint(loc.linnum); | 202 DtoDwarfStopPoint(loc.linnum); |
203 #endif | |
202 | 204 |
203 if (! asmcode) | 205 if (! asmcode) |
204 return; | 206 return; |
205 | 207 |
206 static std::string i_cns = "i"; | 208 static std::string i_cns = "i"; |
255 default: assert(0); break; | 257 default: assert(0); break; |
256 } | 258 } |
257 break; | 259 break; |
258 case Arg_FrameRelative: | 260 case Arg_FrameRelative: |
259 // FIXME | 261 // FIXME |
260 llvm::cout << "asm fixme Arg_FrameRelative" << std::endl; | 262 assert(0 && "asm fixme Arg_FrameRelative"); |
261 assert(0); | |
262 /* if (arg->expr->op == TOKvar) | 263 /* if (arg->expr->op == TOKvar) |
263 arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree; | 264 arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree; |
264 else | 265 else |
265 assert(0); | 266 assert(0); |
266 if ( getFrameRelativeValue(arg_val, & var_frame_offset) ) { | 267 if ( getFrameRelativeValue(arg_val, & var_frame_offset) ) { |
273 if (arg->mode != Mode_Input) | 274 if (arg->mode != Mode_Input) |
274 clobbers_mem = true; | 275 clobbers_mem = true; |
275 break;*/ | 276 break;*/ |
276 case Arg_LocalSize: | 277 case Arg_LocalSize: |
277 // FIXME | 278 // FIXME |
278 llvm::cout << "asm fixme Arg_LocalSize" << std::endl; | 279 assert(0 && "asm fixme Arg_LocalSize"); |
279 assert(0); | |
280 /* var_frame_offset = cfun->x_frame_offset; | 280 /* var_frame_offset = cfun->x_frame_offset; |
281 if (var_frame_offset < 0) | 281 if (var_frame_offset < 0) |
282 var_frame_offset = - var_frame_offset; | 282 var_frame_offset = - var_frame_offset; |
283 arg_val = irs->integerConstant( var_frame_offset );*/ | 283 arg_val = irs->integerConstant( var_frame_offset );*/ |
284 goto do_integer; | 284 goto do_integer; |
298 } | 298 } |
299 | 299 |
300 // Telling GCC that callee-saved registers are clobbered makes it preserve | 300 // Telling GCC that callee-saved registers are clobbered makes it preserve |
301 // those registers. This changes the stack from what a naked function | 301 // those registers. This changes the stack from what a naked function |
302 // expects. | 302 // expects. |
303 | 303 |
304 // FIXME | 304 // FIXME |
305 // if (! irs->func->naked) { | 305 // if (! irs->func->naked) { |
306 assert(asmparser); | 306 assert(asmparser); |
307 for (int i = 0; i < code->regs.size(); i++) { | 307 for (int i = 0; i < code->regs.size(); i++) { |
308 if (code->regs[i]) { | 308 if (code->regs[i]) { |
316 // Remap argument numbers | 316 // Remap argument numbers |
317 for (unsigned i = 0; i < code->args.size(); i++) { | 317 for (unsigned i = 0; i < code->args.size(); i++) { |
318 if (arg_map[i] < 0) | 318 if (arg_map[i] < 0) |
319 arg_map[i] = -arg_map[i] - 1 + n_outputs; | 319 arg_map[i] = -arg_map[i] - 1 + n_outputs; |
320 } | 320 } |
321 | 321 |
322 bool pct = false; | 322 bool pct = false; |
323 std::string::iterator | 323 std::string::iterator |
324 p = code->insnTemplate.begin(), | 324 p = code->insnTemplate.begin(), |
325 q = code->insnTemplate.end(); | 325 q = code->insnTemplate.end(); |
326 //printf("start: %.*s\n", code->insnTemplateLen, code->insnTemplate); | 326 //printf("start: %.*s\n", code->insnTemplateLen, code->insnTemplate); |
341 | 341 |
342 typedef std::vector<std::string>::iterator It; | 342 typedef std::vector<std::string>::iterator It; |
343 if (Logger::enabled()) { | 343 if (Logger::enabled()) { |
344 Logger::cout() << "final asm: " << code->insnTemplate << '\n'; | 344 Logger::cout() << "final asm: " << code->insnTemplate << '\n'; |
345 std::ostringstream ss; | 345 std::ostringstream ss; |
346 | 346 |
347 ss << "GCC-style output constraints: {"; | 347 ss << "GCC-style output constraints: {"; |
348 for (It i = output_constraints.begin(), e = output_constraints.end(); i != e; ++i) { | 348 for (It i = output_constraints.begin(), e = output_constraints.end(); i != e; ++i) { |
349 ss << " " << *i; | 349 ss << " " << *i; |
350 } | 350 } |
351 ss << " }"; | 351 ss << " }"; |
352 Logger::println("%s", ss.str().c_str()); | 352 Logger::println("%s", ss.str().c_str()); |
353 | 353 |
354 ss.str(""); | 354 ss.str(""); |
355 ss << "GCC-style input constraints: {"; | 355 ss << "GCC-style input constraints: {"; |
356 for (It i = input_constraints.begin(), e = input_constraints.end(); i != e; ++i) { | 356 for (It i = input_constraints.begin(), e = input_constraints.end(); i != e; ++i) { |
357 ss << " " << *i; | 357 ss << " " << *i; |
358 } | 358 } |
359 ss << " }"; | 359 ss << " }"; |
360 Logger::println("%s", ss.str().c_str()); | 360 Logger::println("%s", ss.str().c_str()); |
361 | 361 |
362 ss.str(""); | 362 ss.str(""); |
363 ss << "GCC-style clobbers: {"; | 363 ss << "GCC-style clobbers: {"; |
364 for (It i = clobbers.begin(), e = clobbers.end(); i != e; ++i) { | 364 for (It i = clobbers.begin(), e = clobbers.end(); i != e; ++i) { |
365 ss << " " << *i; | 365 ss << " " << *i; |
366 } | 366 } |
377 if((*i)[0] == '+') { | 377 if((*i)[0] == '+') { |
378 assert(*i == mrw_cns && "What else are we updating except memory?"); | 378 assert(*i == mrw_cns && "What else are we updating except memory?"); |
379 /* LLVM doesn't support updating operands, so split into an input | 379 /* LLVM doesn't support updating operands, so split into an input |
380 * and an output operand. | 380 * and an output operand. |
381 */ | 381 */ |
382 | 382 |
383 // Change update operand to pure output operand. | 383 // Change update operand to pure output operand. |
384 *i = mw_cns; | 384 *i = mw_cns; |
385 | 385 |
386 // Add input operand with same value, with original as "matching output". | 386 // Add input operand with same value, with original as "matching output". |
387 std::ostringstream ss; | 387 std::ostringstream ss; |
388 ss << '*' << (n + asmblock->outputcount); | 388 ss << '*' << (n + asmblock->outputcount); |
389 // Must be at the back; unused operands before used ones screw up numbering. | 389 // Must be at the back; unused operands before used ones screw up numbering. |
390 input_constraints.push_back(ss.str()); | 390 input_constraints.push_back(ss.str()); |
570 end = asmblock->internalLabels.end(); | 570 end = asmblock->internalLabels.end(); |
571 bool skip = false; | 571 bool skip = false; |
572 for(it = asmblock->internalLabels.begin(); it != end; ++it) | 572 for(it = asmblock->internalLabels.begin(); it != end; ++it) |
573 if((*it)->equals(a->isBranchToLabel)) | 573 if((*it)->equals(a->isBranchToLabel)) |
574 skip = true; | 574 skip = true; |
575 if(skip) | 575 if(skip) |
576 continue; | 576 continue; |
577 | 577 |
578 // if we already set things up for this branch target, skip | 578 // if we already set things up for this branch target, skip |
579 if(gotoToVal.find(a->isBranchToLabel) != gotoToVal.end()) | 579 if(gotoToVal.find(a->isBranchToLabel) != gotoToVal.end()) |
580 continue; | 580 continue; |