Mercurial > projects > ldc
comparison gen/asmstmt.cpp @ 220:ccc2e6898a78 trunk
[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
work!
author | lindquist |
---|---|
date | Fri, 06 Jun 2008 20:14:51 +0200 |
parents | 761c8352f494 |
children | 68687d8c3e9a |
comparison
equal
deleted
inserted
replaced
219:761c8352f494 | 220:ccc2e6898a78 |
---|---|
1 // Taken from GDC source tree, licence unclear? | 1 // Taken from GDC source tree, licence unclear? |
2 // | 2 // |
3 // Taken from an earlier version of DMD -- why is it missing from 0.79? | 3 // Taken from an earlier version of DMD -- why is it missing from 0.79? |
4 | |
5 #include "gen/llvm.h" | |
6 #include "llvm/InlineAsm.h" | |
4 | 7 |
5 //#include "d-gcc-includes.h" | 8 //#include "d-gcc-includes.h" |
6 //#include "total.h" | 9 //#include "total.h" |
7 #include "dmd/statement.h" | 10 #include "dmd/statement.h" |
8 #include "dmd/scope.h" | 11 #include "dmd/scope.h" |
9 #include "dmd/declaration.h" | 12 #include "dmd/declaration.h" |
10 #include "dmd/dsymbol.h" | 13 #include "dmd/dsymbol.h" |
11 | 14 |
12 #include "llvm/InlineAsm.h" | |
13 | |
14 #include <cassert> | 15 #include <cassert> |
15 #include <deque> | 16 #include <deque> |
16 #include <iostream> | 17 #include <iostream> |
17 #include <sstream> | 18 #include <sstream> |
18 | 19 |
19 //#include "d-lang.h" | 20 //#include "d-lang.h" |
20 //#include "d-codegen.h" | 21 //#include "d-codegen.h" |
22 | |
23 #include "gen/irstate.h" | |
24 #include "gen/dvalue.h" | |
25 #include "gen/tollvm.h" | |
26 #include "gen/logger.h" | |
21 | 27 |
22 typedef enum { | 28 typedef enum { |
23 Arg_Integer, | 29 Arg_Integer, |
24 Arg_Pointer, | 30 Arg_Pointer, |
25 Arg_Memory, | 31 Arg_Memory, |
62 }; | 68 }; |
63 | 69 |
64 llvm::InlineAsm* | 70 llvm::InlineAsm* |
65 d_build_asm_stmt(std::string code, std::deque<DValue*> const& output_values, std::deque<DValue*> const& input_values, std::string constraints) | 71 d_build_asm_stmt(std::string code, std::deque<DValue*> const& output_values, std::deque<DValue*> const& input_values, std::string constraints) |
66 { | 72 { |
67 //FIXME: Return InlineAsm::get(..) here. | 73 std::vector<const LLType*> params; |
68 return NULL; | 74 |
75 // outputs | |
76 const LLType* ret = LLType::VoidTy; | |
77 if (!output_values.empty()) | |
78 { | |
79 std::cout << "memory outputs" << std::endl; | |
80 assert(output_values.size() == 1); | |
81 const LLType* llty = DtoType(output_values[0]->getType()); | |
82 params.push_back(llty); | |
83 } | |
84 | |
85 // inputs | |
86 if (!input_values.empty()) | |
87 { | |
88 std::cout << "inputs" << std::endl; | |
89 assert(input_values.size() == 1); | |
90 const LLType* llty = DtoType(input_values[0]->getType()); | |
91 params.push_back(llty); | |
92 } | |
93 | |
94 llvm::FunctionType* asmfnty = llvm::FunctionType::get(ret, params, false); | |
95 | |
96 std::cout << "function type: " << std::endl; | |
97 std::cout << *asmfnty << std::endl; | |
98 | |
99 return llvm::InlineAsm::get(asmfnty, code, constraints, true); | |
69 } | 100 } |
70 | 101 |
71 AsmStatement::AsmStatement(Loc loc, Token *tokens) : | 102 AsmStatement::AsmStatement(Loc loc, Token *tokens) : |
72 Statement(loc) | 103 Statement(loc) |
73 { | 104 { |
212 } | 243 } |
213 | 244 |
214 void | 245 void |
215 AsmStatement::toIR(IRState * irs) | 246 AsmStatement::toIR(IRState * irs) |
216 { | 247 { |
248 Logger::println("AsmStatement::toIR(): %s", loc.toChars()); | |
249 LOG_SCOPE; | |
250 | |
217 // FIXME | 251 // FIXME |
218 // gen.doLineNote( loc ); | 252 // gen.doLineNote( loc ); |
219 | 253 |
220 if (! asmcode) | 254 if (! asmcode) |
221 return; | 255 return; |
246 | 280 |
247 for (unsigned i = 0; i < code->args.dim; i++) { | 281 for (unsigned i = 0; i < code->args.dim; i++) { |
248 AsmArg * arg = (AsmArg *) code->args.data[i]; | 282 AsmArg * arg = (AsmArg *) code->args.data[i]; |
249 | 283 |
250 bool is_input = true; | 284 bool is_input = true; |
251 DValue* arg_val; | 285 DValue* arg_val = 0; |
252 std::string cns; | 286 std::string cns; |
253 | 287 |
288 std::cout << std::endl; | |
289 | |
254 switch (arg->type) { | 290 switch (arg->type) { |
255 case Arg_Integer: | 291 case Arg_Integer: |
256 arg_val = arg->expr->toElem(irs); | 292 arg_val = arg->expr->toElem(irs); |
257 do_integer: | 293 do_integer: |
258 cns = i_cns; | 294 cns = i_cns; |
259 break; | 295 break; |
260 case Arg_Pointer: | 296 case Arg_Pointer: |
261 // FIXME | 297 // FIXME |
262 /* if (arg->expr->op == TOKvar) | 298 std::cout << "asm fixme Arg_Pointer" << std::endl; |
263 arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree; | 299 if (arg->expr->op == TOKvar) |
264 else if (arg->expr->op == TOKdsymbol) { | 300 arg_val = arg->expr->toElem(irs); |
265 arg_val = irs->getLabelTree( (LabelDsymbol *) ((DsymbolExp *) arg->expr)->s ); | 301 else if (arg->expr->op == TOKdsymbol) |
266 } else | 302 arg_val = arg->expr->toElem(irs); |
267 assert(0); | 303 else |
268 arg_val = irs->addressOf(arg_val);*/ | 304 assert(0); |
305 | |
269 cns = p_cns; | 306 cns = p_cns; |
270 break; | 307 break; |
271 case Arg_Memory: | 308 case Arg_Memory: |
272 // FIXME | 309 // FIXME |
273 /* if (arg->expr->op == TOKvar) | 310 std::cout << "asm fixme Arg_Memory" << std::endl; |
274 arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree; | 311 if (arg->expr->op == TOKvar) |
275 else | 312 arg_val = arg->expr->toElem(irs); |
276 arg_val = arg->expr->toElem(irs); | 313 else |
277 if (DECL_P( arg_val )) | 314 arg_val = arg->expr->toElem(irs); |
278 TREE_ADDRESSABLE( arg_val ) = 1;*/ | 315 |
279 switch (arg->mode) { | 316 switch (arg->mode) { |
280 case Mode_Input: cns = m_cns; break; | 317 case Mode_Input: cns = m_cns; break; |
281 case Mode_Output: cns = mw_cns; is_input = false; break; | 318 case Mode_Output: cns = mw_cns; is_input = false; break; |
282 case Mode_Update: cns = mrw_cns; is_input = false; break; | 319 case Mode_Update: cns = mrw_cns; is_input = false; break; |
283 default: assert(0); break; | 320 default: assert(0); break; |
284 } | 321 } |
285 break; | 322 break; |
286 case Arg_FrameRelative: | 323 case Arg_FrameRelative: |
287 // FIXME | 324 // FIXME |
325 std::cout << "asm fixme Arg_FrameRelative" << std::endl; | |
288 /* if (arg->expr->op == TOKvar) | 326 /* if (arg->expr->op == TOKvar) |
289 arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree; | 327 arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree; |
290 else | 328 else |
291 assert(0);*/ | 329 assert(0);*/ |
292 if ( getFrameRelativeValue(arg_val, & var_frame_offset) ) { | 330 if ( getFrameRelativeValue(arg_val, & var_frame_offset) ) { |
299 if (arg->mode != Mode_Input) | 337 if (arg->mode != Mode_Input) |
300 clobbers_mem = true; | 338 clobbers_mem = true; |
301 break; | 339 break; |
302 case Arg_LocalSize: | 340 case Arg_LocalSize: |
303 // FIXME | 341 // FIXME |
342 std::cout << "asm fixme Arg_LocalSize" << std::endl; | |
304 /* var_frame_offset = cfun->x_frame_offset; | 343 /* var_frame_offset = cfun->x_frame_offset; |
305 if (var_frame_offset < 0) | 344 if (var_frame_offset < 0) |
306 var_frame_offset = - var_frame_offset; | 345 var_frame_offset = - var_frame_offset; |
307 arg_val = irs->integerConstant( var_frame_offset );*/ | 346 arg_val = irs->integerConstant( var_frame_offset );*/ |
308 goto do_integer; | 347 goto do_integer; |
370 } else if (*p == '$') | 409 } else if (*p == '$') |
371 pct = true; | 410 pct = true; |
372 ++p; | 411 ++p; |
373 } | 412 } |
374 | 413 |
375 //printf("final: %.*s\n", code->insnTemplateLen, code->insnTemplate); | 414 printf("final: %.*s\n", code->insnTemplateLen, code->insnTemplate); |
376 | 415 |
377 std::string insnt(code->insnTemplate, code->insnTemplateLen); | 416 std::string insnt(code->insnTemplate, code->insnTemplateLen); |
378 | 417 |
379 // rewrite GCC-style constraints to LLVM-style constraints | 418 // rewrite GCC-style constraints to LLVM-style constraints |
380 std::string llvmConstraints; | 419 std::string llvmConstraints; |
405 llvmConstraints.resize(llvmConstraints.size()-1); | 444 llvmConstraints.resize(llvmConstraints.size()-1); |
406 | 445 |
407 std::cout << "Inline Asm code: " << std::endl; | 446 std::cout << "Inline Asm code: " << std::endl; |
408 std::cout << insnt << std::endl; | 447 std::cout << insnt << std::endl; |
409 std::cout << "LLVM constraints: " << llvmConstraints << std::endl; | 448 std::cout << "LLVM constraints: " << llvmConstraints << std::endl; |
410 std::cout << std::endl; | |
411 | 449 |
412 llvm::InlineAsm* t = d_build_asm_stmt(insnt, output_values, input_values, llvmConstraints); | 450 llvm::InlineAsm* t = d_build_asm_stmt(insnt, output_values, input_values, llvmConstraints); |
451 | |
452 std::cout << "llvm::InlineAsm: " << std::endl; | |
453 std::cout << *t << std::endl; | |
454 | |
455 LLSmallVector<LLValue*, 2> callargs; | |
456 | |
457 size_t cn = output_values.size(); | |
458 for (size_t i=0; i<cn; ++i) | |
459 { | |
460 LLValue* val = output_values[i]->getLVal(); | |
461 callargs.push_back(val); | |
462 } | |
463 | |
464 cn = input_values.size(); | |
465 for (size_t i=0; i<cn; ++i) | |
466 { | |
467 // FIXME: these should not be allowed to intermix with asm calls. they should somehow | |
468 // be outputted before any asm from a block, or the asm's should be moved after ... | |
469 LLValue* val = input_values[i]->getRVal(); | |
470 callargs.push_back(val); | |
471 } | |
472 | |
473 llvm::CallInst* call = irs->ir->CreateCall(t, callargs.begin(), callargs.end(), ""); | |
474 | |
475 /* | |
413 // FIXME | 476 // FIXME |
414 //ASM_VOLATILE_P( t ) = 1; | 477 //ASM_VOLATILE_P( t ) = 1; |
415 //irs->addExp( t ); | 478 //irs->addExp( t ); |
416 if (code->dollarLabel) | 479 if (code->dollarLabel) |
417 d_expand_priv_asm_label(irs, code->dollarLabel); | 480 d_expand_priv_asm_label(irs, code->dollarLabel); |
418 } | 481 */ |
482 } |