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 }