blob: 37aed43a738acd928d7750d1aec1b48b4bc140cc [file] [log] [blame]
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001//===-- MSILWriter.cpp - Library for converting LLVM code to MSIL ---------===//
2//
Anton Korobeynikovbed29462007-04-16 18:10:23 +00003// The LLVM Compiler Infrastructure
Anton Korobeynikov099883f2007-03-21 21:38:25 +00004//
5// This file was developed by Roman Samoilov and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This library converts LLVM code to MSIL code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "MSILWriter.h"
15#include "llvm/CallingConv.h"
16#include "llvm/DerivedTypes.h"
17#include "llvm/Intrinsics.h"
18#include "llvm/IntrinsicInst.h"
Reid Spencer5694b6e2007-04-09 06:17:21 +000019#include "llvm/ParameterAttributes.h"
Anton Korobeynikov099883f2007-03-21 21:38:25 +000020#include "llvm/TypeSymbolTable.h"
21#include "llvm/Analysis/ConstantsScanner.h"
22#include "llvm/Support/CallSite.h"
23#include "llvm/Support/InstVisitor.h"
24#include "llvm/Transforms/Scalar.h"
25#include "llvm/ADT/StringExtras.h"
26
27namespace {
28 // TargetMachine for the MSIL
29 struct VISIBILITY_HIDDEN MSILTarget : public TargetMachine {
30 const TargetData DataLayout; // Calculates type size & alignment
31
32 MSILTarget(const Module &M, const std::string &FS)
33 : DataLayout(&M) {}
34
35 virtual bool WantsWholeFile() const { return true; }
36 virtual bool addPassesToEmitWholeFile(PassManager &PM, std::ostream &Out,
37 CodeGenFileType FileType, bool Fast);
38
39 // This class always works, but shouldn't be the default in most cases.
40 static unsigned getModuleMatchQuality(const Module &M) { return 1; }
41
42 virtual const TargetData *getTargetData() const { return &DataLayout; }
43 };
44}
45
46
47RegisterTarget<MSILTarget> X("msil", " MSIL backend");
48
49bool MSILModule::runOnModule(Module &M) {
50 ModulePtr = &M;
51 TD = &getAnalysis<TargetData>();
52 bool Changed = false;
53 // Find named types.
54 TypeSymbolTable& Table = M.getTypeSymbolTable();
55 std::set<const Type *> Types = getAnalysis<FindUsedTypes>().getTypes();
56 for (TypeSymbolTable::iterator I = Table.begin(), E = Table.end(); I!=E; ) {
57 if (!isa<StructType>(I->second) && !isa<OpaqueType>(I->second))
58 Table.remove(I++);
59 else {
60 std::set<const Type *>::iterator T = Types.find(I->second);
61 if (T==Types.end())
62 Table.remove(I++);
63 else {
64 Types.erase(T);
65 ++I;
66 }
67 }
68 }
69 // Find unnamed types.
70 unsigned RenameCounter = 0;
71 for (std::set<const Type *>::const_iterator I = Types.begin(),
72 E = Types.end(); I!=E; ++I)
73 if (const StructType *STy = dyn_cast<StructType>(*I)) {
74 while (ModulePtr->addTypeName("unnamed$"+utostr(RenameCounter), STy))
75 ++RenameCounter;
76 Changed = true;
77 }
78 // Pointer for FunctionPass.
79 UsedTypes = &getAnalysis<FindUsedTypes>().getTypes();
80 return Changed;
81}
82
Devang Patel19974732007-05-03 01:11:54 +000083char MSILModule::ID = 0;
84char MSILWriter::ID = 0;
Anton Korobeynikov099883f2007-03-21 21:38:25 +000085
86bool MSILWriter::runOnFunction(Function &F) {
87 if (F.isDeclaration()) return false;
88 LInfo = &getAnalysis<LoopInfo>();
89 printFunction(F);
90 return false;
91}
92
93
94bool MSILWriter::doInitialization(Module &M) {
95 ModulePtr = &M;
96 Mang = new Mangler(M);
97 Out << ".assembly extern mscorlib {}\n";
98 Out << ".assembly MSIL {}\n\n";
99 Out << "// External\n";
100 printExternals();
101 Out << "// Declarations\n";
102 printDeclarations(M.getTypeSymbolTable());
103 Out << "// Definitions\n";
104 printGlobalVariables();
105 return false;
106}
107
108
109bool MSILWriter::doFinalization(Module &M) {
110 delete Mang;
111 return false;
112}
113
114
115bool MSILWriter::isZeroValue(const Value* V) {
116 if (const Constant *C = dyn_cast<Constant>(V))
117 return C->isNullValue();
118 return false;
119}
120
121
122std::string MSILWriter::getValueName(const Value* V) {
123 // Name into the quotes allow control and space characters.
124 return "'"+Mang->getValueName(V)+"'";
125}
126
127
128std::string MSILWriter::getLabelName(const std::string& Name) {
129 if (Name.find('.')!=std::string::npos) {
130 std::string Tmp(Name);
131 // Replace unaccepable characters in the label name.
132 for (std::string::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I)
133 if (*I=='.') *I = '@';
134 return Tmp;
135 }
136 return Name;
137}
138
139
140std::string MSILWriter::getLabelName(const Value* V) {
141 return getLabelName(Mang->getValueName(V));
142}
143
144
145std::string MSILWriter::getConvModopt(unsigned CallingConvID) {
146 switch (CallingConvID) {
147 case CallingConv::C:
148 case CallingConv::Cold:
149 case CallingConv::Fast:
150 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) ";
151 case CallingConv::X86_FastCall:
152 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvFastcall) ";
153 case CallingConv::X86_StdCall:
154 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) ";
155 default:
156 cerr << "CallingConvID = " << CallingConvID << '\n';
157 assert(0 && "Unsupported calling convention");
158 }
159}
160
161
162std::string MSILWriter::getArrayTypeName(Type::TypeID TyID, const Type* Ty) {
163 std::string Tmp = "";
164 const Type* ElemTy = Ty;
165 assert(Ty->getTypeID()==TyID && "Invalid type passed");
166 // Walk trought array element types.
167 for (;;) {
168 // Multidimensional array.
169 if (ElemTy->getTypeID()==TyID) {
170 if (const ArrayType* ATy = dyn_cast<ArrayType>(ElemTy))
171 Tmp += utostr(ATy->getNumElements());
172 else if (const VectorType* VTy = dyn_cast<VectorType>(ElemTy))
173 Tmp += utostr(VTy->getNumElements());
174 ElemTy = cast<SequentialType>(ElemTy)->getElementType();
175 }
176 // Base element type found.
177 if (ElemTy->getTypeID()!=TyID) break;
178 Tmp += ",";
179 }
180 return getTypeName(ElemTy)+"["+Tmp+"]";
181}
182
183
184std::string MSILWriter::getPrimitiveTypeName(const Type* Ty, bool isSigned) {
185 unsigned NumBits = 0;
186 switch (Ty->getTypeID()) {
187 case Type::VoidTyID:
188 return "void ";
189 case Type::IntegerTyID:
190 NumBits = getBitWidth(Ty);
191 if(NumBits==1)
192 return "bool ";
193 if (!isSigned)
194 return "unsigned int"+utostr(NumBits)+" ";
195 return "int"+utostr(NumBits)+" ";
196 case Type::FloatTyID:
197 return "float32 ";
198 case Type::DoubleTyID:
199 return "float64 ";
200 default:
201 cerr << "Type = " << *Ty << '\n';
202 assert(0 && "Invalid primitive type");
203 }
204}
205
206
207std::string MSILWriter::getTypeName(const Type* Ty, bool isSigned) {
208 if (Ty->isPrimitiveType() || Ty->isInteger())
209 return getPrimitiveTypeName(Ty,isSigned);
210 // FIXME: "OpaqueType" support
211 switch (Ty->getTypeID()) {
212 case Type::PointerTyID:
213 return "void* ";
214 case Type::StructTyID:
215 return "valuetype '"+ModulePtr->getTypeName(Ty)+"' ";
216 case Type::ArrayTyID:
217 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
218 case Type::VectorTyID:
219 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
220 default:
221 cerr << "Type = " << *Ty << '\n';
222 assert(0 && "Invalid type in getTypeName()");
223 }
224}
225
226
227MSILWriter::ValueType MSILWriter::getValueLocation(const Value* V) {
228 // Function argument
229 if (isa<Argument>(V))
230 return ArgumentVT;
231 // Function
232 else if (const Function* F = dyn_cast<Function>(V))
233 return F->hasInternalLinkage() ? InternalVT : GlobalVT;
234 // Variable
235 else if (const GlobalVariable* G = dyn_cast<GlobalVariable>(V))
236 return G->hasInternalLinkage() ? InternalVT : GlobalVT;
237 // Constant
238 else if (isa<Constant>(V))
239 return isa<ConstantExpr>(V) ? ConstExprVT : ConstVT;
240 // Local variable
241 return LocalVT;
242}
243
244
245std::string MSILWriter::getTypePostfix(const Type* Ty, bool Expand,
246 bool isSigned) {
247 unsigned NumBits = 0;
248 switch (Ty->getTypeID()) {
249 // Integer constant, expanding for stack operations.
250 case Type::IntegerTyID:
251 NumBits = getBitWidth(Ty);
252 // Expand integer value to "int32" or "int64".
253 if (Expand) return (NumBits<=32 ? "i4" : "i8");
254 if (NumBits==1) return "i1";
255 return (isSigned ? "i" : "u")+utostr(NumBits/8);
256 // Float constant.
257 case Type::FloatTyID:
258 return "r4";
259 case Type::DoubleTyID:
260 return "r8";
261 case Type::PointerTyID:
262 return "i"+utostr(TD->getTypeSize(Ty));
263 default:
264 cerr << "TypeID = " << Ty->getTypeID() << '\n';
265 assert(0 && "Invalid type in TypeToPostfix()");
266 }
267}
268
269
270void MSILWriter::printPtrLoad(uint64_t N) {
271 switch (ModulePtr->getPointerSize()) {
272 case Module::Pointer32:
273 printSimpleInstruction("ldc.i4",utostr(N).c_str());
274 // FIXME: Need overflow test?
275 assert(N<0xFFFFFFFF && "32-bit pointer overflowed");
276 break;
277 case Module::Pointer64:
278 printSimpleInstruction("ldc.i8",utostr(N).c_str());
279 break;
280 default:
281 assert(0 && "Module use not supporting pointer size");
282 }
283}
284
285
286void MSILWriter::printConstLoad(const Constant* C) {
287 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(C)) {
288 // Integer constant
289 Out << "\tldc." << getTypePostfix(C->getType(),true) << '\t';
290 if (CInt->isMinValue(true))
291 Out << CInt->getSExtValue();
292 else
293 Out << CInt->getZExtValue();
294 } else if (const ConstantFP* CFp = dyn_cast<ConstantFP>(C)) {
295 // Float constant
296 Out << "\tldc." << getTypePostfix(C->getType(),true) << '\t' <<
297 CFp->getValue();
298 } else {
299 cerr << "Constant = " << *C << '\n';
300 assert(0 && "Invalid constant value");
301 }
302 Out << '\n';
303}
304
305
306void MSILWriter::printValueLoad(const Value* V) {
307 switch (getValueLocation(V)) {
308 // Global variable or function address.
309 case GlobalVT:
310 case InternalVT:
311 if (const Function* F = dyn_cast<Function>(V)) {
312 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
313 printSimpleInstruction("ldftn",
314 getCallSignature(F->getFunctionType(),NULL,Name).c_str());
315 } else {
316 const Type* ElemTy = cast<PointerType>(V->getType())->getElementType();
317 std::string Tmp = getTypeName(ElemTy)+getValueName(V);
318 printSimpleInstruction("ldsflda",Tmp.c_str());
319 }
320 break;
321 // Function argument.
322 case ArgumentVT:
323 printSimpleInstruction("ldarg",getValueName(V).c_str());
324 break;
325 // Local function variable.
326 case LocalVT:
327 printSimpleInstruction("ldloc",getValueName(V).c_str());
328 break;
329 // Constant value.
330 case ConstVT:
331 if (isa<ConstantPointerNull>(V))
332 printPtrLoad(0);
333 else
334 printConstLoad(cast<Constant>(V));
335 break;
336 // Constant expression.
337 case ConstExprVT:
338 printConstantExpr(cast<ConstantExpr>(V));
339 break;
340 default:
341 cerr << "Value = " << *V << '\n';
342 assert(0 && "Invalid value location");
343 }
344}
345
346
347void MSILWriter::printValueSave(const Value* V) {
348 switch (getValueLocation(V)) {
349 case ArgumentVT:
350 printSimpleInstruction("starg",getValueName(V).c_str());
351 break;
352 case LocalVT:
353 printSimpleInstruction("stloc",getValueName(V).c_str());
354 break;
355 default:
356 cerr << "Value = " << *V << '\n';
357 assert(0 && "Invalid value location");
358 }
359}
360
361
362void MSILWriter::printBinaryInstruction(const char* Name, const Value* Left,
363 const Value* Right) {
364 printValueLoad(Left);
365 printValueLoad(Right);
366 Out << '\t' << Name << '\n';
367}
368
369
370void MSILWriter::printSimpleInstruction(const char* Inst, const char* Operand) {
371 if(Operand)
372 Out << '\t' << Inst << '\t' << Operand << '\n';
373 else
374 Out << '\t' << Inst << '\n';
375}
376
377
378void MSILWriter::printPHICopy(const BasicBlock* Src, const BasicBlock* Dst) {
379 for (BasicBlock::const_iterator I = Dst->begin(), E = Dst->end();
380 isa<PHINode>(I); ++I) {
381 const PHINode* Phi = cast<PHINode>(I);
382 const Value* Val = Phi->getIncomingValueForBlock(Src);
383 if (isa<UndefValue>(Val)) continue;
384 printValueLoad(Val);
385 printValueSave(Phi);
386 }
387}
388
389
390void MSILWriter::printBranchToBlock(const BasicBlock* CurrBB,
391 const BasicBlock* TrueBB,
392 const BasicBlock* FalseBB) {
393 if (TrueBB==FalseBB) {
394 // "TrueBB" and "FalseBB" destination equals
395 printPHICopy(CurrBB,TrueBB);
396 printSimpleInstruction("pop");
397 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
398 } else if (FalseBB==NULL) {
399 // If "FalseBB" not used the jump have condition
400 printPHICopy(CurrBB,TrueBB);
401 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
402 } else if (TrueBB==NULL) {
403 // If "TrueBB" not used the jump is unconditional
404 printPHICopy(CurrBB,FalseBB);
405 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
406 } else {
407 // Copy PHI instructions for each block
408 std::string TmpLabel;
409 // Print PHI instructions for "TrueBB"
410 if (isa<PHINode>(TrueBB->begin())) {
411 TmpLabel = getLabelName(TrueBB)+"$phi_"+utostr(getUniqID());
412 printSimpleInstruction("brtrue",TmpLabel.c_str());
413 } else {
414 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
415 }
416 // Print PHI instructions for "FalseBB"
417 if (isa<PHINode>(FalseBB->begin())) {
418 printPHICopy(CurrBB,FalseBB);
419 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
420 } else {
421 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
422 }
423 if (isa<PHINode>(TrueBB->begin())) {
424 // Handle "TrueBB" PHI Copy
425 Out << TmpLabel << ":\n";
426 printPHICopy(CurrBB,TrueBB);
427 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
428 }
429 }
430}
431
432
433void MSILWriter::printBranchInstruction(const BranchInst* Inst) {
434 if (Inst->isUnconditional()) {
435 printBranchToBlock(Inst->getParent(),NULL,Inst->getSuccessor(0));
436 } else {
437 printValueLoad(Inst->getCondition());
438 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(0),
439 Inst->getSuccessor(1));
440 }
441}
442
443
444void MSILWriter::printSelectInstruction(const Value* Cond, const Value* VTrue,
445 const Value* VFalse) {
446 std::string TmpLabel = std::string("select$true_")+utostr(getUniqID());
447 printValueLoad(VTrue);
448 printValueLoad(Cond);
449 printSimpleInstruction("brtrue",TmpLabel.c_str());
450 printSimpleInstruction("pop");
451 printValueLoad(VFalse);
452 Out << TmpLabel << ":\n";
453}
454
455
456void MSILWriter::printIndirectLoad(const Value* V) {
457 printValueLoad(V);
458 std::string Tmp = "ldind."+getTypePostfix(V->getType(),false);
459 printSimpleInstruction(Tmp.c_str());
460}
461
462
463void MSILWriter::printStoreInstruction(const Instruction* Inst) {
464 const Value* Val = Inst->getOperand(0);
465 const Value* Ptr = Inst->getOperand(1);
466 // Load destination address.
467 printValueLoad(Ptr);
468 // Load value.
469 printValueLoad(Val);
470 // Instruction need signed postfix for any type.
471 std::string postfix = getTypePostfix(Val->getType(),false);
472 if (*postfix.begin()=='u') *postfix.begin() = 'i';
473 postfix = "stind."+postfix;
474 printSimpleInstruction(postfix.c_str());
475}
476
477
478void MSILWriter::printCastInstruction(unsigned int Op, const Value* V,
479 const Type* Ty) {
480 std::string Tmp("");
481 printValueLoad(V);
482 switch (Op) {
483 // Signed
484 case Instruction::SExt:
485 case Instruction::SIToFP:
486 case Instruction::FPToSI:
487 Tmp = "conv."+getTypePostfix(Ty,false,true);
488 printSimpleInstruction(Tmp.c_str());
489 break;
490 // Unsigned
491 case Instruction::FPTrunc:
492 case Instruction::FPExt:
493 case Instruction::UIToFP:
494 case Instruction::Trunc:
495 case Instruction::ZExt:
496 case Instruction::FPToUI:
497 case Instruction::PtrToInt:
498 case Instruction::IntToPtr:
499 Tmp = "conv."+getTypePostfix(Ty,false);
500 printSimpleInstruction(Tmp.c_str());
501 break;
502 // Do nothing
503 case Instruction::BitCast:
504 // FIXME: meaning that ld*/st* instruction do not change data format.
505 break;
506 default:
507 cerr << "Opcode = " << Op << '\n';
508 assert(0 && "Invalid conversion instruction");
509 }
510}
511
512
513void MSILWriter::printGepInstruction(const Value* V, gep_type_iterator I,
514 gep_type_iterator E) {
515 // Load address
516 printValueLoad(V);
517 // Calculate element offset.
518 unsigned TySize;
519 for (++I; I!=E; ++I){
520 const Type* Ty = I.getIndexedType();
521 const Value* Idx = I.getOperand();
522 // Get size of type.
523 switch (Ty->getTypeID()) {
524 case Type::IntegerTyID:
525 case Type::FloatTyID:
526 case Type::DoubleTyID:
527 case Type::PointerTyID:
528 TySize = TD->getTypeSize(Ty);
529 break;
530 case Type::StructTyID:
531 TySize = 0;
532 break;
533 case Type::ArrayTyID:
534 TySize = TD->getTypeSize(cast<ArrayType>(Ty)->getElementType());
535 break;
536 case Type::VectorTyID:
537 TySize = TD->getTypeSize(cast<VectorType>(Ty)->getElementType());
538 break;
539 default:
540 cerr << "Type = " << *Ty << '\n';
541 assert(0 && "Invalid index type in printGepInstruction()");
542 }
543 // Calculate offset to structure field.
544 if (const StructType* STy = dyn_cast<StructType>(Ty)) {
545 TySize = 0;
546 uint64_t FieldIdx = cast<ConstantInt>(Idx)->getZExtValue();
547 // Offset is the summ of all previous structure fields.
548 for (uint64_t F = 0; F<FieldIdx; ++F)
549 TySize += TD->getTypeSize(STy->getContainedType(unsigned(F)));
550 // Add field offset to stack top.
551 printPtrLoad(TySize);
552 printSimpleInstruction("add");
553 continue;
554 }
555 // Add offset of current element to stack top.
556 if (!isZeroValue(Idx)) {
557 uint64_t TySize = TD->getTypeSize(I.getIndexedType());
558 // Constant optimization
559 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(Idx)) {
560 printPtrLoad(CInt->getZExtValue()*TySize);
561 } else {
562 printPtrLoad(TySize);
563 printValueLoad(Idx);
564 printSimpleInstruction("mul");
565 }
566 printSimpleInstruction("add");
567 }
568 }
569}
570
571
572std::string MSILWriter::getCallSignature(const FunctionType* Ty,
573 const Instruction* Inst,
574 std::string Name) {
575 std::string Tmp = "";
576 if (Ty->isVarArg()) Tmp += "vararg ";
577 // Name and return type.
578 Tmp += getTypeName(Ty->getReturnType())+Name+"(";
579 // Function argument type list.
580 unsigned NumParams = Ty->getNumParams();
581 for (unsigned I = 0; I!=NumParams; ++I) {
582 if (I!=0) Tmp += ",";
583 Tmp += getTypeName(Ty->getParamType(I));
584 }
585 // CLR needs to know the exact amount of parameters received by vararg
586 // function, because caller cleans the stack.
587 if (Ty->isVarArg() && Inst) {
588 // Origin to function arguments in "CallInst" or "InvokeInst"
589 unsigned Org = isa<InvokeInst>(Inst) ? 3 : 1;
590 // Print variable argument types.
591 unsigned NumOperands = Inst->getNumOperands()-Org;
592 if (NumParams<NumOperands) {
593 if (NumParams!=0) Tmp += ", ";
594 Tmp += "... , ";
595 for (unsigned J = NumParams; J!=NumOperands; ++J) {
596 if (J!=NumParams) Tmp += ", ";
597 Tmp += getTypeName(Inst->getOperand(J+Org)->getType());
598 }
599 }
600 }
601 return Tmp+")";
602}
603
604
605void MSILWriter::printFunctionCall(const Value* FnVal,
606 const Instruction* Inst) {
607 // Get function calling convention
608 std::string Name = "";
609 if (const CallInst* Call = dyn_cast<CallInst>(Inst))
610 Name = getConvModopt(Call->getCallingConv());
611 else if (const InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst))
612 Name = getConvModopt(Invoke->getCallingConv());
613 else {
614 cerr << "Instruction = " << Inst->getName() << '\n';
615 assert(0 && "Need \"Invoke\" or \"Call\" instruction only");
616 }
617
618 if (const Function* F = dyn_cast<Function>(FnVal)) {
619 // Direct call
620 Name += getValueName(F);
621 printSimpleInstruction("call",
622 getCallSignature(F->getFunctionType(),Inst,Name).c_str());
623 } else {
624 // Indirect function call
625 const PointerType* PTy = cast<PointerType>(FnVal->getType());
626 const FunctionType* FTy = cast<FunctionType>(PTy->getElementType());
627 // Load function address
628 printValueLoad(FnVal);
629 printSimpleInstruction("calli",getCallSignature(FTy,Inst,Name).c_str());
630 }
631}
632
633
634void MSILWriter::printCallInstruction(const Instruction* Inst) {
635 // Load arguments to stack
636 for (int I = 1, E = Inst->getNumOperands(); I!=E; ++I)
637 printValueLoad(Inst->getOperand(I));
638 printFunctionCall(Inst->getOperand(0),Inst);
639}
640
641
642void MSILWriter::printICmpInstruction(unsigned Predicate, const Value* Left,
643 const Value* Right) {
644 switch (Predicate) {
645 case ICmpInst::ICMP_EQ:
646 printBinaryInstruction("ceq",Left,Right);
647 break;
648 case ICmpInst::ICMP_NE:
649 // Emulate = not (Op1 eq Op2)
650 printBinaryInstruction("ceq",Left,Right);
651 printSimpleInstruction("not");
652 break;
653 case ICmpInst::ICMP_ULE:
654 case ICmpInst::ICMP_SLE:
655 // Emulate = (Op1 eq Op2) or (Op1 lt Op2)
656 printBinaryInstruction("ceq",Left,Right);
657 if (Predicate==ICmpInst::ICMP_ULE)
658 printBinaryInstruction("clt.un",Left,Right);
659 else
660 printBinaryInstruction("clt",Left,Right);
661 printSimpleInstruction("or");
662 break;
663 case ICmpInst::ICMP_UGE:
664 case ICmpInst::ICMP_SGE:
665 // Emulate = (Op1 eq Op2) or (Op1 gt Op2)
666 printBinaryInstruction("ceq",Left,Right);
667 if (Predicate==ICmpInst::ICMP_UGE)
668 printBinaryInstruction("cgt.un",Left,Right);
669 else
670 printBinaryInstruction("cgt",Left,Right);
671 printSimpleInstruction("or");
672 break;
673 case ICmpInst::ICMP_ULT:
674 printBinaryInstruction("clt.un",Left,Right);
675 break;
676 case ICmpInst::ICMP_SLT:
677 printBinaryInstruction("clt",Left,Right);
678 break;
679 case ICmpInst::ICMP_UGT:
680 printBinaryInstruction("cgt.un",Left,Right);
681 case ICmpInst::ICMP_SGT:
682 printBinaryInstruction("cgt",Left,Right);
683 break;
684 default:
685 cerr << "Predicate = " << Predicate << '\n';
686 assert(0 && "Invalid icmp predicate");
687 }
688}
689
690
691void MSILWriter::printFCmpInstruction(unsigned Predicate, const Value* Left,
692 const Value* Right) {
693 // FIXME: Correct comparison
694 std::string NanFunc = "bool [mscorlib]System.Double::IsNaN(float64)";
695 switch (Predicate) {
696 case FCmpInst::FCMP_UGT:
697 // X > Y || llvm_fcmp_uno(X, Y)
698 printBinaryInstruction("cgt",Left,Right);
699 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
700 printSimpleInstruction("or");
701 break;
702 case FCmpInst::FCMP_OGT:
703 // X > Y
704 printBinaryInstruction("cgt",Left,Right);
705 break;
706 case FCmpInst::FCMP_UGE:
707 // X >= Y || llvm_fcmp_uno(X, Y)
708 printBinaryInstruction("ceq",Left,Right);
709 printBinaryInstruction("cgt",Left,Right);
710 printSimpleInstruction("or");
711 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
712 printSimpleInstruction("or");
713 break;
714 case FCmpInst::FCMP_OGE:
715 // X >= Y
716 printBinaryInstruction("ceq",Left,Right);
717 printBinaryInstruction("cgt",Left,Right);
718 printSimpleInstruction("or");
719 break;
720 case FCmpInst::FCMP_ULT:
721 // X < Y || llvm_fcmp_uno(X, Y)
722 printBinaryInstruction("clt",Left,Right);
723 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
724 printSimpleInstruction("or");
725 break;
726 case FCmpInst::FCMP_OLT:
727 // X < Y
728 printBinaryInstruction("clt",Left,Right);
729 break;
730 case FCmpInst::FCMP_ULE:
731 // X <= Y || llvm_fcmp_uno(X, Y)
732 printBinaryInstruction("ceq",Left,Right);
733 printBinaryInstruction("clt",Left,Right);
734 printSimpleInstruction("or");
735 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
736 printSimpleInstruction("or");
737 break;
738 case FCmpInst::FCMP_OLE:
739 // X <= Y
740 printBinaryInstruction("ceq",Left,Right);
741 printBinaryInstruction("clt",Left,Right);
742 printSimpleInstruction("or");
743 break;
744 case FCmpInst::FCMP_UEQ:
745 // X == Y || llvm_fcmp_uno(X, Y)
746 printBinaryInstruction("ceq",Left,Right);
747 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
748 printSimpleInstruction("or");
749 break;
750 case FCmpInst::FCMP_OEQ:
751 // X == Y
752 printBinaryInstruction("ceq",Left,Right);
753 break;
754 case FCmpInst::FCMP_UNE:
755 // X != Y
756 printBinaryInstruction("ceq",Left,Right);
757 printSimpleInstruction("not");
758 break;
759 case FCmpInst::FCMP_ONE:
760 // X != Y && llvm_fcmp_ord(X, Y)
761 printBinaryInstruction("ceq",Left,Right);
762 printSimpleInstruction("not");
763 break;
764 case FCmpInst::FCMP_ORD:
765 // return X == X && Y == Y
766 printBinaryInstruction("ceq",Left,Left);
767 printBinaryInstruction("ceq",Right,Right);
768 printSimpleInstruction("or");
769 break;
770 case FCmpInst::FCMP_UNO:
771 // X != X || Y != Y
772 printBinaryInstruction("ceq",Left,Left);
773 printSimpleInstruction("not");
774 printBinaryInstruction("ceq",Right,Right);
775 printSimpleInstruction("not");
776 printSimpleInstruction("or");
777 break;
778 default:
779 assert(0 && "Illegal FCmp predicate");
780 }
781}
782
783
784void MSILWriter::printInvokeInstruction(const InvokeInst* Inst) {
785 std::string Label = "leave$normal_"+utostr(getUniqID());
786 Out << ".try {\n";
787 // Load arguments
788 for (int I = 3, E = Inst->getNumOperands(); I!=E; ++I)
789 printValueLoad(Inst->getOperand(I));
790 // Print call instruction
791 printFunctionCall(Inst->getOperand(0),Inst);
792 // Save function result and leave "try" block
793 printValueSave(Inst);
794 printSimpleInstruction("leave",Label.c_str());
795 Out << "}\n";
796 Out << "catch [mscorlib]System.Exception {\n";
797 // Redirect to unwind block
798 printSimpleInstruction("pop");
799 printBranchToBlock(Inst->getParent(),NULL,Inst->getUnwindDest());
800 Out << "}\n" << Label << ":\n";
801 // Redirect to continue block
802 printBranchToBlock(Inst->getParent(),NULL,Inst->getNormalDest());
803}
804
805
806void MSILWriter::printSwitchInstruction(const SwitchInst* Inst) {
807 // FIXME: Emulate with IL "switch" instruction
808 // Emulate = if () else if () else if () else ...
809 for (unsigned int I = 1, E = Inst->getNumCases(); I!=E; ++I) {
810 printValueLoad(Inst->getCondition());
811 printValueLoad(Inst->getCaseValue(I));
812 printSimpleInstruction("ceq");
813 // Condition jump to successor block
814 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(I),NULL);
815 }
816 // Jump to default block
817 printBranchToBlock(Inst->getParent(),NULL,Inst->getDefaultDest());
818}
819
820
821void MSILWriter::printInstruction(const Instruction* Inst) {
822 const Value *Left = 0, *Right = 0;
823 if (Inst->getNumOperands()>=1) Left = Inst->getOperand(0);
824 if (Inst->getNumOperands()>=2) Right = Inst->getOperand(1);
825 // Print instruction
826 // FIXME: "ShuffleVector","ExtractElement","InsertElement","VAArg" support.
827 switch (Inst->getOpcode()) {
828 // Terminator
829 case Instruction::Ret:
830 if (Inst->getNumOperands()) {
831 printValueLoad(Left);
832 printSimpleInstruction("ret");
833 } else
834 printSimpleInstruction("ret");
835 break;
836 case Instruction::Br:
837 printBranchInstruction(cast<BranchInst>(Inst));
838 break;
839 // Binary
840 case Instruction::Add:
841 printBinaryInstruction("add",Left,Right);
842 break;
843 case Instruction::Sub:
844 printBinaryInstruction("sub",Left,Right);
845 break;
846 case Instruction::Mul:
847 printBinaryInstruction("mul",Left,Right);
848 break;
849 case Instruction::UDiv:
850 printBinaryInstruction("div.un",Left,Right);
851 break;
852 case Instruction::SDiv:
853 case Instruction::FDiv:
854 printBinaryInstruction("div",Left,Right);
855 break;
856 case Instruction::URem:
857 printBinaryInstruction("rem.un",Left,Right);
858 break;
859 case Instruction::SRem:
860 case Instruction::FRem:
861 printBinaryInstruction("rem",Left,Right);
862 break;
863 // Binary Condition
864 case Instruction::ICmp:
865 printICmpInstruction(cast<ICmpInst>(Inst)->getPredicate(),Left,Right);
866 break;
867 case Instruction::FCmp:
868 printFCmpInstruction(cast<FCmpInst>(Inst)->getPredicate(),Left,Right);
869 break;
870 // Bitwise Binary
871 case Instruction::And:
872 printBinaryInstruction("and",Left,Right);
873 break;
874 case Instruction::Or:
875 printBinaryInstruction("or",Left,Right);
876 break;
877 case Instruction::Xor:
878 printBinaryInstruction("xor",Left,Right);
879 break;
880 case Instruction::Shl:
881 printBinaryInstruction("shl",Left,Right);
882 break;
883 case Instruction::LShr:
884 printBinaryInstruction("shr.un",Left,Right);
885 break;
886 case Instruction::AShr:
887 printBinaryInstruction("shr",Left,Right);
888 break;
889 case Instruction::Select:
890 printSelectInstruction(Inst->getOperand(0),Inst->getOperand(1),Inst->getOperand(2));
891 break;
892 case Instruction::Load:
893 printIndirectLoad(Inst->getOperand(0));
894 break;
895 case Instruction::Store:
896 printStoreInstruction(Inst);
897 break;
898 case Instruction::Trunc:
899 case Instruction::ZExt:
900 case Instruction::SExt:
901 case Instruction::FPTrunc:
902 case Instruction::FPExt:
903 case Instruction::UIToFP:
904 case Instruction::SIToFP:
905 case Instruction::FPToUI:
906 case Instruction::FPToSI:
907 case Instruction::PtrToInt:
908 case Instruction::IntToPtr:
909 case Instruction::BitCast:
910 printCastInstruction(Inst->getOpcode(),Left,
911 cast<CastInst>(Inst)->getDestTy());
912 break;
913 case Instruction::GetElementPtr:
914 printGepInstruction(Inst->getOperand(0),gep_type_begin(Inst),
915 gep_type_end(Inst));
916 break;
917 case Instruction::Call:
918 printCallInstruction(cast<CallInst>(Inst));
919 break;
920 case Instruction::Invoke:
921 printInvokeInstruction(cast<InvokeInst>(Inst));
922 break;
923 case Instruction::Unwind: {
924 std::string Class = "instance void [mscorlib]System.Exception::.ctor()";
925 printSimpleInstruction("newobj",Class.c_str());
926 printSimpleInstruction("throw");
927 break;
928 }
929 case Instruction::Switch:
930 printSwitchInstruction(cast<SwitchInst>(Inst));
931 break;
932 case Instruction::Alloca:
933 printValueLoad(Inst->getOperand(0));
934 printSimpleInstruction("localloc");
935 break;
936 case Instruction::Malloc:
937 assert(0 && "LowerAllocationsPass used");
938 break;
939 case Instruction::Free:
940 assert(0 && "LowerAllocationsPass used");
941 break;
942 case Instruction::Unreachable:
943 printSimpleInstruction("ldnull");
944 printSimpleInstruction("throw");
945 break;
946 default:
947 cerr << "Instruction = " << Inst->getName() << '\n';
948 assert(0 && "Unsupported instruction");
949 }
950}
951
952
953void MSILWriter::printLoop(const Loop* L) {
954 Out << getLabelName(L->getHeader()->getName()) << ":\n";
955 const std::vector<BasicBlock*>& blocks = L->getBlocks();
956 for (unsigned I = 0, E = blocks.size(); I!=E; I++) {
957 BasicBlock* BB = blocks[I];
958 Loop* BBLoop = LInfo->getLoopFor(BB);
959 if (BBLoop == L)
960 printBasicBlock(BB);
961 else if (BB==BBLoop->getHeader() && BBLoop->getParentLoop()==L)
962 printLoop(BBLoop);
963 }
964 printSimpleInstruction("br",getLabelName(L->getHeader()->getName()).c_str());
965}
966
967
968void MSILWriter::printBasicBlock(const BasicBlock* BB) {
969 Out << getLabelName(BB) << ":\n";
970 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) {
971 const Instruction* Inst = I;
972 // Comment llvm original instruction
973 Out << "\n//" << *Inst << "\n";
974 // Do not handle PHI instruction in current block
975 if (Inst->getOpcode()==Instruction::PHI) continue;
976 // Print instruction
977 printInstruction(Inst);
978 // Save result
979 if (Inst->getType()!=Type::VoidTy) {
980 // Do not save value after invoke, it done in "try" block
981 if (Inst->getOpcode()==Instruction::Invoke) continue;
982 printValueSave(Inst);
983 }
984 }
985}
986
987
988void MSILWriter::printLocalVariables(const Function& F) {
989 std::string Name;
990 const Type* Ty = NULL;
991 // Find variables
992 for (const_inst_iterator I = inst_begin(&F), E = inst_end(&F); I!=E; ++I) {
993 const AllocaInst* AI = dyn_cast<AllocaInst>(&*I);
994 if (AI && !isa<GlobalVariable>(AI)) {
995 Ty = PointerType::get(AI->getAllocatedType());
996 Name = getValueName(AI);
997 } else if (I->getType()!=Type::VoidTy) {
998 Ty = I->getType();
999 Name = getValueName(&*I);
1000 } else continue;
1001 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
1002 }
1003}
1004
1005
1006void MSILWriter::printFunctionBody(const Function& F) {
1007 // Print body
1008 for (Function::const_iterator I = F.begin(), E = F.end(); I!=E; ++I) {
1009 if (Loop *L = LInfo->getLoopFor(I)) {
1010 if (L->getHeader()==I && L->getParentLoop()==0)
1011 printLoop(L);
1012 } else {
1013 printBasicBlock(I);
1014 }
1015 }
1016}
1017
1018
1019void MSILWriter::printConstantExpr(const ConstantExpr* CE) {
1020 const Value *left = 0, *right = 0;
1021 if (CE->getNumOperands()>=1) left = CE->getOperand(0);
1022 if (CE->getNumOperands()>=2) right = CE->getOperand(1);
1023 // Print instruction
1024 switch (CE->getOpcode()) {
1025 case Instruction::Trunc:
1026 case Instruction::ZExt:
1027 case Instruction::SExt:
1028 case Instruction::FPTrunc:
1029 case Instruction::FPExt:
1030 case Instruction::UIToFP:
1031 case Instruction::SIToFP:
1032 case Instruction::FPToUI:
1033 case Instruction::FPToSI:
1034 case Instruction::PtrToInt:
1035 case Instruction::IntToPtr:
1036 case Instruction::BitCast:
1037 printCastInstruction(CE->getOpcode(),left,CE->getType());
1038 break;
1039 case Instruction::GetElementPtr:
1040 printGepInstruction(CE->getOperand(0),gep_type_begin(CE),gep_type_end(CE));
1041 break;
1042 case Instruction::ICmp:
1043 printICmpInstruction(CE->getPredicate(),left,right);
1044 break;
1045 case Instruction::FCmp:
1046 printFCmpInstruction(CE->getPredicate(),left,right);
1047 break;
1048 case Instruction::Select:
1049 printSelectInstruction(CE->getOperand(0),CE->getOperand(1),CE->getOperand(2));
1050 break;
1051 case Instruction::Add:
1052 printBinaryInstruction("add",left,right);
1053 break;
1054 case Instruction::Sub:
1055 printBinaryInstruction("sub",left,right);
1056 break;
1057 case Instruction::Mul:
1058 printBinaryInstruction("mul",left,right);
1059 break;
1060 case Instruction::UDiv:
1061 printBinaryInstruction("div.un",left,right);
1062 break;
1063 case Instruction::SDiv:
1064 case Instruction::FDiv:
1065 printBinaryInstruction("div",left,right);
1066 break;
1067 case Instruction::URem:
1068 printBinaryInstruction("rem.un",left,right);
1069 break;
1070 case Instruction::SRem:
1071 case Instruction::FRem:
1072 printBinaryInstruction("rem",left,right);
1073 break;
1074 case Instruction::And:
1075 printBinaryInstruction("and",left,right);
1076 break;
1077 case Instruction::Or:
1078 printBinaryInstruction("or",left,right);
1079 break;
1080 case Instruction::Xor:
1081 printBinaryInstruction("xor",left,right);
1082 break;
1083 case Instruction::Shl:
1084 printBinaryInstruction("shl",left,right);
1085 break;
1086 case Instruction::LShr:
1087 printBinaryInstruction("shr.un",left,right);
1088 break;
1089 case Instruction::AShr:
1090 printBinaryInstruction("shr",left,right);
1091 break;
1092 default:
1093 cerr << "Expression = " << *CE << "\n";
1094 assert(0 && "Invalid constant expression");
1095 }
1096}
1097
1098
1099void MSILWriter::printStaticInitializerList() {
1100 // List of global variables with uninitialized fields.
1101 for (std::map<const GlobalVariable*,std::vector<StaticInitializer> >::iterator
1102 VarI = StaticInitList.begin(), VarE = StaticInitList.end(); VarI!=VarE;
1103 ++VarI) {
1104 const std::vector<StaticInitializer>& InitList = VarI->second;
1105 if (InitList.empty()) continue;
1106 // For each uninitialized field.
1107 for (std::vector<StaticInitializer>::const_iterator I = InitList.begin(),
1108 E = InitList.end(); I!=E; ++I) {
1109 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(I->constant)) {
1110 Out << "\n// Init " << getValueName(VarI->first) << ", offset " <<
1111 utostr(I->offset) << ", type "<< *I->constant->getType() << "\n\n";
1112 // Load variable address
1113 printValueLoad(VarI->first);
1114 // Add offset
1115 if (I->offset!=0) {
1116 printPtrLoad(I->offset);
1117 printSimpleInstruction("add");
1118 }
1119 // Load value
1120 printConstantExpr(CE);
1121 // Save result at offset
1122 std::string postfix = getTypePostfix(CE->getType(),true);
1123 if (*postfix.begin()=='u') *postfix.begin() = 'i';
1124 postfix = "stind."+postfix;
1125 printSimpleInstruction(postfix.c_str());
1126 } else {
1127 cerr << "Constant = " << *I->constant << '\n';
1128 assert(0 && "Invalid static initializer");
1129 }
1130 }
1131 }
1132}
1133
1134
1135void MSILWriter::printFunction(const Function& F) {
1136 const FunctionType* FTy = F.getFunctionType();
Reid Spencer5694b6e2007-04-09 06:17:21 +00001137 const ParamAttrsList *Attrs = FTy->getParamAttrs();
Reid Spencer18da0722007-04-11 02:44:20 +00001138 bool isSigned = Attrs && Attrs->paramHasAttr(0, ParamAttr::SExt);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001139 Out << "\n.method static ";
1140 Out << (F.hasInternalLinkage() ? "private " : "public ");
1141 if (F.isVarArg()) Out << "vararg ";
1142 Out << getTypeName(F.getReturnType(),isSigned) <<
1143 getConvModopt(F.getCallingConv()) << getValueName(&F) << '\n';
1144 // Arguments
1145 Out << "\t(";
1146 unsigned ArgIdx = 1;
1147 for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I!=E;
1148 ++I, ++ArgIdx) {
Reid Spencer18da0722007-04-11 02:44:20 +00001149 isSigned = Attrs && Attrs->paramHasAttr(ArgIdx, ParamAttr::SExt);
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001150 if (I!=F.arg_begin()) Out << ", ";
1151 Out << getTypeName(I->getType(),isSigned) << getValueName(I);
1152 }
1153 Out << ") cil managed\n";
1154 // Body
1155 Out << "{\n";
1156 // FIXME: Convert "string[]" to "argc,argv"
1157 if (F.getName()=="main") {
1158 printSimpleInstruction(".entrypoint");
1159 printLocalVariables(F);
1160 printStaticInitializerList();
1161 } else {
1162 printLocalVariables(F);
1163 }
1164 printFunctionBody(F);
1165 Out << "}\n";
1166}
1167
1168
1169void MSILWriter::printDeclarations(const TypeSymbolTable& ST) {
1170 std::string Name;
1171 std::set<const Type*> Printed;
1172 //cerr << "UsedTypes = " << UsedTypes << '\n';
1173 for (std::set<const Type*>::const_iterator
1174 UI = UsedTypes->begin(), UE = UsedTypes->end(); UI!=UE; ++UI) {
1175 const Type* Ty = *UI;
1176 if (isa<ArrayType>(Ty))
1177 Name = getArrayTypeName(Ty->getTypeID(),Ty);
1178 else if (isa<VectorType>(Ty))
1179 Name = getArrayTypeName(Ty->getTypeID(),Ty);
1180 else if (isa<StructType>(Ty))
1181 Name = ModulePtr->getTypeName(Ty);
1182 // Type with no need to declare.
1183 else continue;
1184 // Print not duplicated type
1185 if (Printed.insert(Ty).second) {
1186 Out << ".class value explicit ansi sealed '" << Name << "'";
1187 Out << " { .pack " << 1 << " .size " << TD->getTypeSize(Ty) << " }\n\n";
1188 }
1189 }
1190}
1191
1192
1193unsigned int MSILWriter::getBitWidth(const Type* Ty) {
1194 unsigned int N = Ty->getPrimitiveSizeInBits();
1195 assert(N!=0 && "Invalid type in getBitWidth()");
1196 switch (N) {
1197 case 1:
1198 case 8:
1199 case 16:
1200 case 32:
1201 case 64:
1202 return N;
1203 default:
1204 cerr << "Bits = " << N << '\n';
1205 assert(0 && "Unsupported integer width");
1206 }
1207}
1208
1209
1210void MSILWriter::printStaticConstant(const Constant* C, uint64_t& Offset) {
1211 uint64_t TySize = 0;
1212 const Type* Ty = C->getType();
1213 // Print zero initialized constant.
1214 if (isa<ConstantAggregateZero>(C) || C->isNullValue()) {
1215 TySize = TD->getTypeSize(C->getType());
1216 Offset += TySize;
1217 Out << "int8 (0) [" << TySize << "]";
1218 return;
1219 }
1220 // Print constant initializer
1221 switch (Ty->getTypeID()) {
1222 case Type::IntegerTyID: {
1223 TySize = TD->getTypeSize(Ty);
1224 const ConstantInt* Int = cast<ConstantInt>(C);
1225 Out << getPrimitiveTypeName(Ty,true) << "(" << Int->getSExtValue() << ")";
1226 break;
1227 }
1228 case Type::FloatTyID:
1229 case Type::DoubleTyID: {
1230 TySize = TD->getTypeSize(Ty);
1231 const ConstantFP* CFp = cast<ConstantFP>(C);
1232 Out << getPrimitiveTypeName(Ty,true) << "(" << CFp->getValue() << ")";
1233 break;
1234 }
1235 case Type::ArrayTyID:
1236 case Type::VectorTyID:
1237 case Type::StructTyID:
1238 for (unsigned I = 0, E = C->getNumOperands(); I<E; I++) {
1239 if (I!=0) Out << ",\n";
1240 printStaticConstant(C->getOperand(I),Offset);
1241 }
1242 break;
1243 case Type::PointerTyID:
1244 TySize = TD->getTypeSize(C->getType());
1245 // Initialize with global variable address
1246 if (const GlobalVariable *G = dyn_cast<GlobalVariable>(C)) {
1247 std::string name = getValueName(G);
1248 Out << "&(" << name.insert(name.length()-1,"$data") << ")";
1249 } else {
1250 // Dynamic initialization
1251 if (!isa<ConstantPointerNull>(C) && !C->isNullValue())
1252 InitListPtr->push_back(StaticInitializer(C,Offset));
1253 // Null pointer initialization
1254 if (TySize==4) Out << "int32 (0)";
1255 else if (TySize==8) Out << "int64 (0)";
1256 else assert(0 && "Invalid pointer size");
1257 }
1258 break;
1259 default:
1260 cerr << "TypeID = " << Ty->getTypeID() << '\n';
1261 assert(0 && "Invalid type in printStaticConstant()");
1262 }
1263 // Increase offset.
1264 Offset += TySize;
1265}
1266
1267
1268void MSILWriter::printStaticInitializer(const Constant* C,
1269 const std::string& Name) {
1270 switch (C->getType()->getTypeID()) {
1271 case Type::IntegerTyID:
1272 case Type::FloatTyID:
1273 case Type::DoubleTyID:
1274 Out << getPrimitiveTypeName(C->getType(),true);
1275 break;
1276 case Type::ArrayTyID:
1277 case Type::VectorTyID:
1278 case Type::StructTyID:
1279 case Type::PointerTyID:
1280 Out << getTypeName(C->getType());
1281 break;
1282 default:
1283 cerr << "Type = " << *C << "\n";
1284 assert(0 && "Invalid constant type");
1285 }
1286 // Print initializer
1287 std::string label = Name;
1288 label.insert(label.length()-1,"$data");
1289 Out << Name << " at " << label << '\n';
1290 Out << ".data " << label << " = {\n";
1291 uint64_t offset = 0;
1292 printStaticConstant(C,offset);
1293 Out << "\n}\n\n";
1294}
1295
1296
1297void MSILWriter::printVariableDefinition(const GlobalVariable* G) {
1298 const Constant* C = G->getInitializer();
1299 if (C->isNullValue() || isa<ConstantAggregateZero>(C) || isa<UndefValue>(C))
1300 InitListPtr = 0;
1301 else
1302 InitListPtr = &StaticInitList[G];
1303 printStaticInitializer(C,getValueName(G));
1304}
1305
1306
1307void MSILWriter::printGlobalVariables() {
1308 if (ModulePtr->global_empty()) return;
1309 Module::global_iterator I,E;
1310 for (I = ModulePtr->global_begin(), E = ModulePtr->global_end(); I!=E; ++I) {
1311 // Variable definition
1312 if (I->isDeclaration()) continue;
1313 Out << ".field static " << (I->hasExternalLinkage() ? "public " :
1314 "private ");
1315 printVariableDefinition(&*I);
1316 }
1317}
1318
1319
1320void MSILWriter::printExternals() {
1321 Module::const_iterator I,E;
1322 for (I=ModulePtr->begin(),E=ModulePtr->end(); I!=E; ++I) {
1323 // Skip intrisics
1324 if (I->getIntrinsicID()) continue;
1325 // FIXME: Treat as standard library function
1326 if (I->isDeclaration()) {
1327 const Function* F = &*I;
1328 const FunctionType* FTy = F->getFunctionType();
1329 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
1330 std::string Sig = getCallSignature(FTy,NULL,Name);
1331 Out << ".method static hidebysig pinvokeimpl(\"msvcrt.dll\" cdecl)\n\t"
1332 << Sig << " preservesig {}\n\n";
1333 }
1334 }
1335}
1336
1337//===----------------------------------------------------------------------===//
Anton Korobeynikovbed29462007-04-16 18:10:23 +00001338// External Interface declaration
Anton Korobeynikov099883f2007-03-21 21:38:25 +00001339//===----------------------------------------------------------------------===//
1340
1341bool MSILTarget::addPassesToEmitWholeFile(PassManager &PM, std::ostream &o,
1342 CodeGenFileType FileType, bool Fast)
1343{
1344 if (FileType != TargetMachine::AssemblyFile) return true;
1345 MSILWriter* Writer = new MSILWriter(o);
1346 PM.add(createLowerGCPass());
1347 PM.add(createLowerAllocationsPass(true));
1348 // FIXME: Handle switch trougth native IL instruction "switch"
1349 PM.add(createLowerSwitchPass());
1350 PM.add(createCFGSimplificationPass());
1351 PM.add(new MSILModule(Writer->UsedTypes,Writer->TD));
1352 PM.add(Writer);
1353 return false;
1354}