1 //===-- MSILWriter.cpp - Library for converting LLVM code to MSIL ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This library converts LLVM code to MSIL code.
12 //===----------------------------------------------------------------------===//
14 #include "MSILWriter.h"
15 #include "llvm/CallingConv.h"
16 #include "llvm/DerivedTypes.h"
17 #include "llvm/Intrinsics.h"
18 #include "llvm/IntrinsicInst.h"
19 #include "llvm/TypeSymbolTable.h"
20 #include "llvm/Analysis/ConstantsScanner.h"
21 #include "llvm/Support/CallSite.h"
22 #include "llvm/Support/InstVisitor.h"
23 #include "llvm/Support/MathExtras.h"
24 #include "llvm/Transforms/Scalar.h"
25 #include "llvm/ADT/StringExtras.h"
26 #include "llvm/CodeGen/Passes.h"
29 // TargetMachine for the MSIL
30 struct VISIBILITY_HIDDEN MSILTarget : public TargetMachine {
31 const TargetData DataLayout; // Calculates type size & alignment
33 MSILTarget(const Module &M, const std::string &FS)
36 virtual bool WantsWholeFile() const { return true; }
37 virtual bool addPassesToEmitWholeFile(PassManager &PM, raw_ostream &Out,
38 CodeGenFileType FileType,
39 CodeGenOpt::Level OptLevel);
41 // This class always works, but shouldn't be the default in most cases.
42 static unsigned getModuleMatchQuality(const Module &M) { return 1; }
44 virtual const TargetData *getTargetData() const { return &DataLayout; }
48 /// MSILTargetMachineModule - Note that this is used on hosts that
49 /// cannot link in a library unless there are references into the
50 /// library. In particular, it seems that it is not possible to get
51 /// things to work on Win32 without this. Though it is unused, do not
53 extern "C" int MSILTargetMachineModule;
54 int MSILTargetMachineModule = 0;
56 static RegisterTarget<MSILTarget> X("msil", "MSIL backend");
58 // Force static initialization.
59 extern "C" void LLVMInitializeMSILTarget() { }
61 bool MSILModule::runOnModule(Module &M) {
63 TD = &getAnalysis<TargetData>();
66 TypeSymbolTable& Table = M.getTypeSymbolTable();
67 std::set<const Type *> Types = getAnalysis<FindUsedTypes>().getTypes();
68 for (TypeSymbolTable::iterator I = Table.begin(), E = Table.end(); I!=E; ) {
69 if (!isa<StructType>(I->second) && !isa<OpaqueType>(I->second))
72 std::set<const Type *>::iterator T = Types.find(I->second);
81 // Find unnamed types.
82 unsigned RenameCounter = 0;
83 for (std::set<const Type *>::const_iterator I = Types.begin(),
84 E = Types.end(); I!=E; ++I)
85 if (const StructType *STy = dyn_cast<StructType>(*I)) {
86 while (ModulePtr->addTypeName("unnamed$"+utostr(RenameCounter), STy))
90 // Pointer for FunctionPass.
91 UsedTypes = &getAnalysis<FindUsedTypes>().getTypes();
95 char MSILModule::ID = 0;
96 char MSILWriter::ID = 0;
98 bool MSILWriter::runOnFunction(Function &F) {
99 if (F.isDeclaration()) return false;
101 // Do not codegen any 'available_externally' functions at all, they have
102 // definitions outside the translation unit.
103 if (F.hasAvailableExternallyLinkage())
106 LInfo = &getAnalysis<LoopInfo>();
112 bool MSILWriter::doInitialization(Module &M) {
114 Mang = new Mangler(M);
115 Out << ".assembly extern mscorlib {}\n";
116 Out << ".assembly MSIL {}\n\n";
117 Out << "// External\n";
119 Out << "// Declarations\n";
120 printDeclarations(M.getTypeSymbolTable());
121 Out << "// Definitions\n";
122 printGlobalVariables();
123 Out << "// Startup code\n";
124 printModuleStartup();
129 bool MSILWriter::doFinalization(Module &M) {
135 void MSILWriter::printModuleStartup() {
137 ".method static public int32 $MSIL_Startup() {\n"
139 "\t.locals (native int i)\n"
140 "\t.locals (native int argc)\n"
141 "\t.locals (native int ptr)\n"
142 "\t.locals (void* argv)\n"
143 "\t.locals (string[] args)\n"
144 "\tcall\tstring[] [mscorlib]System.Environment::GetCommandLineArgs()\n"
151 printPtrLoad(TD->getPointerSize());
166 "\tcall\tnative int [mscorlib]System.Runtime.InteropServices.Marshal::"
167 "StringToHGlobalAnsi(string)\n"
171 printPtrLoad(TD->getPointerSize());
183 "\tcall void $MSIL_Init()\n";
185 // Call user 'main' function.
186 const Function* F = ModulePtr->getFunction("main");
187 if (!F || F->isDeclaration()) {
188 Out << "\tldc.i4.0\n\tret\n}\n";
192 std::string Args("");
193 Function::const_arg_iterator Arg1,Arg2;
195 switch (F->arg_size()) {
200 Arg1 = F->arg_begin();
201 if (Arg1->getType()->isInteger()) {
202 Out << "\tldloc\targc\n";
203 Args = getTypeName(Arg1->getType());
208 Arg1 = Arg2 = F->arg_begin(); ++Arg2;
209 if (Arg1->getType()->isInteger() &&
210 Arg2->getType()->getTypeID() == Type::PointerTyID) {
211 Out << "\tldloc\targc\n\tldloc\targv\n";
212 Args = getTypeName(Arg1->getType())+","+getTypeName(Arg2->getType());
220 bool RetVoid = (F->getReturnType()->getTypeID() == Type::VoidTyID);
221 if (BadSig || (!F->getReturnType()->isInteger() && !RetVoid)) {
222 Out << "\tldc.i4.0\n";
224 Out << "\tcall\t" << getTypeName(F->getReturnType()) <<
225 getConvModopt(F->getCallingConv()) << "main(" << Args << ")\n";
227 Out << "\tldc.i4.0\n";
229 Out << "\tconv.i4\n";
234 bool MSILWriter::isZeroValue(const Value* V) {
235 if (const Constant *C = dyn_cast<Constant>(V))
236 return C->isNullValue();
241 std::string MSILWriter::getValueName(const Value* V) {
242 // Name into the quotes allow control and space characters.
243 return "'"+Mang->getValueName(V)+"'";
247 std::string MSILWriter::getLabelName(const std::string& Name) {
248 if (Name.find('.')!=std::string::npos) {
249 std::string Tmp(Name);
250 // Replace unaccepable characters in the label name.
251 for (std::string::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I)
252 if (*I=='.') *I = '@';
259 std::string MSILWriter::getLabelName(const Value* V) {
260 return getLabelName(Mang->getValueName(V));
264 std::string MSILWriter::getConvModopt(unsigned CallingConvID) {
265 switch (CallingConvID) {
267 case CallingConv::Cold:
268 case CallingConv::Fast:
269 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) ";
270 case CallingConv::X86_FastCall:
271 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvFastcall) ";
272 case CallingConv::X86_StdCall:
273 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) ";
275 cerr << "CallingConvID = " << CallingConvID << '\n';
276 assert(0 && "Unsupported calling convention");
278 return ""; // Not reached
282 std::string MSILWriter::getArrayTypeName(Type::TypeID TyID, const Type* Ty) {
283 std::string Tmp = "";
284 const Type* ElemTy = Ty;
285 assert(Ty->getTypeID()==TyID && "Invalid type passed");
286 // Walk trought array element types.
288 // Multidimensional array.
289 if (ElemTy->getTypeID()==TyID) {
290 if (const ArrayType* ATy = dyn_cast<ArrayType>(ElemTy))
291 Tmp += utostr(ATy->getNumElements());
292 else if (const VectorType* VTy = dyn_cast<VectorType>(ElemTy))
293 Tmp += utostr(VTy->getNumElements());
294 ElemTy = cast<SequentialType>(ElemTy)->getElementType();
296 // Base element type found.
297 if (ElemTy->getTypeID()!=TyID) break;
300 return getTypeName(ElemTy, false, true)+"["+Tmp+"]";
304 std::string MSILWriter::getPrimitiveTypeName(const Type* Ty, bool isSigned) {
305 unsigned NumBits = 0;
306 switch (Ty->getTypeID()) {
309 case Type::IntegerTyID:
310 NumBits = getBitWidth(Ty);
314 return "unsigned int"+utostr(NumBits)+" ";
315 return "int"+utostr(NumBits)+" ";
316 case Type::FloatTyID:
318 case Type::DoubleTyID:
321 cerr << "Type = " << *Ty << '\n';
322 assert(0 && "Invalid primitive type");
324 return ""; // Not reached
328 std::string MSILWriter::getTypeName(const Type* Ty, bool isSigned,
330 if (Ty->isPrimitiveType() || Ty->isInteger())
331 return getPrimitiveTypeName(Ty,isSigned);
332 // FIXME: "OpaqueType" support
333 switch (Ty->getTypeID()) {
334 case Type::PointerTyID:
336 case Type::StructTyID:
338 return ModulePtr->getTypeName(Ty);
339 return "valuetype '"+ModulePtr->getTypeName(Ty)+"' ";
340 case Type::ArrayTyID:
342 return getArrayTypeName(Ty->getTypeID(),Ty);
343 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
344 case Type::VectorTyID:
346 return getArrayTypeName(Ty->getTypeID(),Ty);
347 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
349 cerr << "Type = " << *Ty << '\n';
350 assert(0 && "Invalid type in getTypeName()");
352 return ""; // Not reached
356 MSILWriter::ValueType MSILWriter::getValueLocation(const Value* V) {
358 if (isa<Argument>(V))
361 else if (const Function* F = dyn_cast<Function>(V))
362 return F->hasLocalLinkage() ? InternalVT : GlobalVT;
364 else if (const GlobalVariable* G = dyn_cast<GlobalVariable>(V))
365 return G->hasLocalLinkage() ? InternalVT : GlobalVT;
367 else if (isa<Constant>(V))
368 return isa<ConstantExpr>(V) ? ConstExprVT : ConstVT;
374 std::string MSILWriter::getTypePostfix(const Type* Ty, bool Expand,
376 unsigned NumBits = 0;
377 switch (Ty->getTypeID()) {
378 // Integer constant, expanding for stack operations.
379 case Type::IntegerTyID:
380 NumBits = getBitWidth(Ty);
381 // Expand integer value to "int32" or "int64".
382 if (Expand) return (NumBits<=32 ? "i4" : "i8");
383 if (NumBits==1) return "i1";
384 return (isSigned ? "i" : "u")+utostr(NumBits/8);
386 case Type::FloatTyID:
388 case Type::DoubleTyID:
390 case Type::PointerTyID:
391 return "i"+utostr(TD->getTypeAllocSize(Ty));
393 cerr << "TypeID = " << Ty->getTypeID() << '\n';
394 assert(0 && "Invalid type in TypeToPostfix()");
396 return ""; // Not reached
400 void MSILWriter::printConvToPtr() {
401 switch (ModulePtr->getPointerSize()) {
402 case Module::Pointer32:
403 printSimpleInstruction("conv.u4");
405 case Module::Pointer64:
406 printSimpleInstruction("conv.u8");
409 assert(0 && "Module use not supporting pointer size");
414 void MSILWriter::printPtrLoad(uint64_t N) {
415 switch (ModulePtr->getPointerSize()) {
416 case Module::Pointer32:
417 printSimpleInstruction("ldc.i4",utostr(N).c_str());
418 // FIXME: Need overflow test?
420 cerr << "Value = " << utostr(N) << '\n';
421 assert(0 && "32-bit pointer overflowed");
424 case Module::Pointer64:
425 printSimpleInstruction("ldc.i8",utostr(N).c_str());
428 assert(0 && "Module use not supporting pointer size");
433 void MSILWriter::printValuePtrLoad(const Value* V) {
439 void MSILWriter::printConstLoad(const Constant* C) {
440 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(C)) {
442 Out << "\tldc." << getTypePostfix(C->getType(),true) << '\t';
443 if (CInt->isMinValue(true))
444 Out << CInt->getSExtValue();
446 Out << CInt->getZExtValue();
447 } else if (const ConstantFP* FP = dyn_cast<ConstantFP>(C)) {
451 if (FP->getType()->getTypeID()==Type::FloatTyID) {
452 X = (uint32_t)FP->getValueAPF().bitcastToAPInt().getZExtValue();
455 X = FP->getValueAPF().bitcastToAPInt().getZExtValue();
458 Out << "\tldc.r" << Size << "\t( " << utohexstr(X) << ')';
459 } else if (isa<UndefValue>(C)) {
460 // Undefined constant value = NULL.
463 cerr << "Constant = " << *C << '\n';
464 assert(0 && "Invalid constant value");
470 void MSILWriter::printValueLoad(const Value* V) {
471 MSILWriter::ValueType Location = getValueLocation(V);
473 // Global variable or function address.
476 if (const Function* F = dyn_cast<Function>(V)) {
477 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
478 printSimpleInstruction("ldftn",
479 getCallSignature(F->getFunctionType(),NULL,Name).c_str());
482 const Type* ElemTy = cast<PointerType>(V->getType())->getElementType();
483 if (Location==GlobalVT && cast<GlobalVariable>(V)->hasDLLImportLinkage()) {
484 Tmp = "void* "+getValueName(V);
485 printSimpleInstruction("ldsfld",Tmp.c_str());
487 Tmp = getTypeName(ElemTy)+getValueName(V);
488 printSimpleInstruction("ldsflda",Tmp.c_str());
492 // Function argument.
494 printSimpleInstruction("ldarg",getValueName(V).c_str());
496 // Local function variable.
498 printSimpleInstruction("ldloc",getValueName(V).c_str());
502 if (isa<ConstantPointerNull>(V))
505 printConstLoad(cast<Constant>(V));
507 // Constant expression.
509 printConstantExpr(cast<ConstantExpr>(V));
512 cerr << "Value = " << *V << '\n';
513 assert(0 && "Invalid value location");
518 void MSILWriter::printValueSave(const Value* V) {
519 switch (getValueLocation(V)) {
521 printSimpleInstruction("starg",getValueName(V).c_str());
524 printSimpleInstruction("stloc",getValueName(V).c_str());
527 cerr << "Value = " << *V << '\n';
528 assert(0 && "Invalid value location");
533 void MSILWriter::printBinaryInstruction(const char* Name, const Value* Left,
534 const Value* Right) {
535 printValueLoad(Left);
536 printValueLoad(Right);
537 Out << '\t' << Name << '\n';
541 void MSILWriter::printSimpleInstruction(const char* Inst, const char* Operand) {
543 Out << '\t' << Inst << '\t' << Operand << '\n';
545 Out << '\t' << Inst << '\n';
549 void MSILWriter::printPHICopy(const BasicBlock* Src, const BasicBlock* Dst) {
550 for (BasicBlock::const_iterator I = Dst->begin(), E = Dst->end();
551 isa<PHINode>(I); ++I) {
552 const PHINode* Phi = cast<PHINode>(I);
553 const Value* Val = Phi->getIncomingValueForBlock(Src);
554 if (isa<UndefValue>(Val)) continue;
561 void MSILWriter::printBranchToBlock(const BasicBlock* CurrBB,
562 const BasicBlock* TrueBB,
563 const BasicBlock* FalseBB) {
564 if (TrueBB==FalseBB) {
565 // "TrueBB" and "FalseBB" destination equals
566 printPHICopy(CurrBB,TrueBB);
567 printSimpleInstruction("pop");
568 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
569 } else if (FalseBB==NULL) {
570 // If "FalseBB" not used the jump have condition
571 printPHICopy(CurrBB,TrueBB);
572 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
573 } else if (TrueBB==NULL) {
574 // If "TrueBB" not used the jump is unconditional
575 printPHICopy(CurrBB,FalseBB);
576 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
578 // Copy PHI instructions for each block
579 std::string TmpLabel;
580 // Print PHI instructions for "TrueBB"
581 if (isa<PHINode>(TrueBB->begin())) {
582 TmpLabel = getLabelName(TrueBB)+"$phi_"+utostr(getUniqID());
583 printSimpleInstruction("brtrue",TmpLabel.c_str());
585 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
587 // Print PHI instructions for "FalseBB"
588 if (isa<PHINode>(FalseBB->begin())) {
589 printPHICopy(CurrBB,FalseBB);
590 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
592 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
594 if (isa<PHINode>(TrueBB->begin())) {
595 // Handle "TrueBB" PHI Copy
596 Out << TmpLabel << ":\n";
597 printPHICopy(CurrBB,TrueBB);
598 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
604 void MSILWriter::printBranchInstruction(const BranchInst* Inst) {
605 if (Inst->isUnconditional()) {
606 printBranchToBlock(Inst->getParent(),NULL,Inst->getSuccessor(0));
608 printValueLoad(Inst->getCondition());
609 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(0),
610 Inst->getSuccessor(1));
615 void MSILWriter::printSelectInstruction(const Value* Cond, const Value* VTrue,
616 const Value* VFalse) {
617 std::string TmpLabel = std::string("select$true_")+utostr(getUniqID());
618 printValueLoad(VTrue);
619 printValueLoad(Cond);
620 printSimpleInstruction("brtrue",TmpLabel.c_str());
621 printSimpleInstruction("pop");
622 printValueLoad(VFalse);
623 Out << TmpLabel << ":\n";
627 void MSILWriter::printIndirectLoad(const Value* V) {
628 const Type* Ty = V->getType();
630 if (const PointerType* P = dyn_cast<PointerType>(Ty))
631 Ty = P->getElementType();
632 std::string Tmp = "ldind."+getTypePostfix(Ty, false);
633 printSimpleInstruction(Tmp.c_str());
637 void MSILWriter::printIndirectSave(const Value* Ptr, const Value* Val) {
640 printIndirectSave(Val->getType());
644 void MSILWriter::printIndirectSave(const Type* Ty) {
645 // Instruction need signed postfix for any type.
646 std::string postfix = getTypePostfix(Ty, false);
647 if (*postfix.begin()=='u') *postfix.begin() = 'i';
648 postfix = "stind."+postfix;
649 printSimpleInstruction(postfix.c_str());
653 void MSILWriter::printCastInstruction(unsigned int Op, const Value* V,
659 case Instruction::SExt:
660 case Instruction::SIToFP:
661 case Instruction::FPToSI:
662 Tmp = "conv."+getTypePostfix(Ty,false,true);
663 printSimpleInstruction(Tmp.c_str());
666 case Instruction::FPTrunc:
667 case Instruction::FPExt:
668 case Instruction::UIToFP:
669 case Instruction::Trunc:
670 case Instruction::ZExt:
671 case Instruction::FPToUI:
672 case Instruction::PtrToInt:
673 case Instruction::IntToPtr:
674 Tmp = "conv."+getTypePostfix(Ty,false);
675 printSimpleInstruction(Tmp.c_str());
678 case Instruction::BitCast:
679 // FIXME: meaning that ld*/st* instruction do not change data format.
682 cerr << "Opcode = " << Op << '\n';
683 assert(0 && "Invalid conversion instruction");
688 void MSILWriter::printGepInstruction(const Value* V, gep_type_iterator I,
689 gep_type_iterator E) {
692 printValuePtrLoad(V);
693 // Calculate element offset.
696 const Value* IndexValue = I.getOperand();
697 if (const StructType* StrucTy = dyn_cast<StructType>(*I)) {
698 uint64_t FieldIndex = cast<ConstantInt>(IndexValue)->getZExtValue();
699 // Offset is the sum of all previous structure fields.
700 for (uint64_t F = 0; F<FieldIndex; ++F)
701 Size += TD->getTypeAllocSize(StrucTy->getContainedType((unsigned)F));
703 printSimpleInstruction("add");
705 } else if (const SequentialType* SeqTy = dyn_cast<SequentialType>(*I)) {
706 Size = TD->getTypeAllocSize(SeqTy->getElementType());
708 Size = TD->getTypeAllocSize(*I);
710 // Add offset of current element to stack top.
711 if (!isZeroValue(IndexValue)) {
712 // Constant optimization.
713 if (const ConstantInt* C = dyn_cast<ConstantInt>(IndexValue)) {
714 if (C->getValue().isNegative()) {
715 printPtrLoad(C->getValue().abs().getZExtValue()*Size);
716 printSimpleInstruction("sub");
719 printPtrLoad(C->getZExtValue()*Size);
722 printValuePtrLoad(IndexValue);
723 printSimpleInstruction("mul");
725 printSimpleInstruction("add");
731 std::string MSILWriter::getCallSignature(const FunctionType* Ty,
732 const Instruction* Inst,
735 if (Ty->isVarArg()) Tmp += "vararg ";
736 // Name and return type.
737 Tmp += getTypeName(Ty->getReturnType())+Name+"(";
738 // Function argument type list.
739 unsigned NumParams = Ty->getNumParams();
740 for (unsigned I = 0; I!=NumParams; ++I) {
741 if (I!=0) Tmp += ",";
742 Tmp += getTypeName(Ty->getParamType(I));
744 // CLR needs to know the exact amount of parameters received by vararg
745 // function, because caller cleans the stack.
746 if (Ty->isVarArg() && Inst) {
747 // Origin to function arguments in "CallInst" or "InvokeInst".
748 unsigned Org = isa<InvokeInst>(Inst) ? 3 : 1;
749 // Print variable argument types.
750 unsigned NumOperands = Inst->getNumOperands()-Org;
751 if (NumParams<NumOperands) {
752 if (NumParams!=0) Tmp += ", ";
754 for (unsigned J = NumParams; J!=NumOperands; ++J) {
755 if (J!=NumParams) Tmp += ", ";
756 Tmp += getTypeName(Inst->getOperand(J+Org)->getType());
764 void MSILWriter::printFunctionCall(const Value* FnVal,
765 const Instruction* Inst) {
766 // Get function calling convention.
767 std::string Name = "";
768 if (const CallInst* Call = dyn_cast<CallInst>(Inst))
769 Name = getConvModopt(Call->getCallingConv());
770 else if (const InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst))
771 Name = getConvModopt(Invoke->getCallingConv());
773 cerr << "Instruction = " << Inst->getName() << '\n';
774 assert(0 && "Need \"Invoke\" or \"Call\" instruction only");
776 if (const Function* F = dyn_cast<Function>(FnVal)) {
778 Name += getValueName(F);
779 printSimpleInstruction("call",
780 getCallSignature(F->getFunctionType(),Inst,Name).c_str());
782 // Indirect function call.
783 const PointerType* PTy = cast<PointerType>(FnVal->getType());
784 const FunctionType* FTy = cast<FunctionType>(PTy->getElementType());
785 // Load function address.
786 printValueLoad(FnVal);
787 printSimpleInstruction("calli",getCallSignature(FTy,Inst,Name).c_str());
792 void MSILWriter::printIntrinsicCall(const IntrinsicInst* Inst) {
794 switch (Inst->getIntrinsicID()) {
795 case Intrinsic::vastart:
796 Name = getValueName(Inst->getOperand(1));
797 Name.insert(Name.length()-1,"$valist");
798 // Obtain the argument handle.
799 printSimpleInstruction("ldloca",Name.c_str());
800 printSimpleInstruction("arglist");
801 printSimpleInstruction("call",
802 "instance void [mscorlib]System.ArgIterator::.ctor"
803 "(valuetype [mscorlib]System.RuntimeArgumentHandle)");
804 // Save as pointer type "void*"
805 printValueLoad(Inst->getOperand(1));
806 printSimpleInstruction("ldloca",Name.c_str());
807 printIndirectSave(PointerType::getUnqual(IntegerType::get(8)));
809 case Intrinsic::vaend:
810 // Close argument list handle.
811 printIndirectLoad(Inst->getOperand(1));
812 printSimpleInstruction("call","instance void [mscorlib]System.ArgIterator::End()");
814 case Intrinsic::vacopy:
815 // Copy "ArgIterator" valuetype.
816 printIndirectLoad(Inst->getOperand(1));
817 printIndirectLoad(Inst->getOperand(2));
818 printSimpleInstruction("cpobj","[mscorlib]System.ArgIterator");
821 cerr << "Intrinsic ID = " << Inst->getIntrinsicID() << '\n';
822 assert(0 && "Invalid intrinsic function");
827 void MSILWriter::printCallInstruction(const Instruction* Inst) {
828 if (isa<IntrinsicInst>(Inst)) {
829 // Handle intrinsic function.
830 printIntrinsicCall(cast<IntrinsicInst>(Inst));
832 // Load arguments to stack and call function.
833 for (int I = 1, E = Inst->getNumOperands(); I!=E; ++I)
834 printValueLoad(Inst->getOperand(I));
835 printFunctionCall(Inst->getOperand(0),Inst);
840 void MSILWriter::printICmpInstruction(unsigned Predicate, const Value* Left,
841 const Value* Right) {
843 case ICmpInst::ICMP_EQ:
844 printBinaryInstruction("ceq",Left,Right);
846 case ICmpInst::ICMP_NE:
847 // Emulate = not neg (Op1 eq Op2)
848 printBinaryInstruction("ceq",Left,Right);
849 printSimpleInstruction("neg");
850 printSimpleInstruction("not");
852 case ICmpInst::ICMP_ULE:
853 case ICmpInst::ICMP_SLE:
854 // Emulate = (Op1 eq Op2) or (Op1 lt Op2)
855 printBinaryInstruction("ceq",Left,Right);
856 if (Predicate==ICmpInst::ICMP_ULE)
857 printBinaryInstruction("clt.un",Left,Right);
859 printBinaryInstruction("clt",Left,Right);
860 printSimpleInstruction("or");
862 case ICmpInst::ICMP_UGE:
863 case ICmpInst::ICMP_SGE:
864 // Emulate = (Op1 eq Op2) or (Op1 gt Op2)
865 printBinaryInstruction("ceq",Left,Right);
866 if (Predicate==ICmpInst::ICMP_UGE)
867 printBinaryInstruction("cgt.un",Left,Right);
869 printBinaryInstruction("cgt",Left,Right);
870 printSimpleInstruction("or");
872 case ICmpInst::ICMP_ULT:
873 printBinaryInstruction("clt.un",Left,Right);
875 case ICmpInst::ICMP_SLT:
876 printBinaryInstruction("clt",Left,Right);
878 case ICmpInst::ICMP_UGT:
879 printBinaryInstruction("cgt.un",Left,Right);
880 case ICmpInst::ICMP_SGT:
881 printBinaryInstruction("cgt",Left,Right);
884 cerr << "Predicate = " << Predicate << '\n';
885 assert(0 && "Invalid icmp predicate");
890 void MSILWriter::printFCmpInstruction(unsigned Predicate, const Value* Left,
891 const Value* Right) {
892 // FIXME: Correct comparison
893 std::string NanFunc = "bool [mscorlib]System.Double::IsNaN(float64)";
895 case FCmpInst::FCMP_UGT:
896 // X > Y || llvm_fcmp_uno(X, Y)
897 printBinaryInstruction("cgt",Left,Right);
898 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
899 printSimpleInstruction("or");
901 case FCmpInst::FCMP_OGT:
903 printBinaryInstruction("cgt",Left,Right);
905 case FCmpInst::FCMP_UGE:
906 // X >= Y || llvm_fcmp_uno(X, Y)
907 printBinaryInstruction("ceq",Left,Right);
908 printBinaryInstruction("cgt",Left,Right);
909 printSimpleInstruction("or");
910 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
911 printSimpleInstruction("or");
913 case FCmpInst::FCMP_OGE:
915 printBinaryInstruction("ceq",Left,Right);
916 printBinaryInstruction("cgt",Left,Right);
917 printSimpleInstruction("or");
919 case FCmpInst::FCMP_ULT:
920 // X < Y || llvm_fcmp_uno(X, Y)
921 printBinaryInstruction("clt",Left,Right);
922 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
923 printSimpleInstruction("or");
925 case FCmpInst::FCMP_OLT:
927 printBinaryInstruction("clt",Left,Right);
929 case FCmpInst::FCMP_ULE:
930 // X <= Y || llvm_fcmp_uno(X, Y)
931 printBinaryInstruction("ceq",Left,Right);
932 printBinaryInstruction("clt",Left,Right);
933 printSimpleInstruction("or");
934 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
935 printSimpleInstruction("or");
937 case FCmpInst::FCMP_OLE:
939 printBinaryInstruction("ceq",Left,Right);
940 printBinaryInstruction("clt",Left,Right);
941 printSimpleInstruction("or");
943 case FCmpInst::FCMP_UEQ:
944 // X == Y || llvm_fcmp_uno(X, Y)
945 printBinaryInstruction("ceq",Left,Right);
946 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
947 printSimpleInstruction("or");
949 case FCmpInst::FCMP_OEQ:
951 printBinaryInstruction("ceq",Left,Right);
953 case FCmpInst::FCMP_UNE:
955 printBinaryInstruction("ceq",Left,Right);
956 printSimpleInstruction("neg");
957 printSimpleInstruction("not");
959 case FCmpInst::FCMP_ONE:
960 // X != Y && llvm_fcmp_ord(X, Y)
961 printBinaryInstruction("ceq",Left,Right);
962 printSimpleInstruction("not");
964 case FCmpInst::FCMP_ORD:
965 // return X == X && Y == Y
966 printBinaryInstruction("ceq",Left,Left);
967 printBinaryInstruction("ceq",Right,Right);
968 printSimpleInstruction("or");
970 case FCmpInst::FCMP_UNO:
972 printBinaryInstruction("ceq",Left,Left);
973 printSimpleInstruction("not");
974 printBinaryInstruction("ceq",Right,Right);
975 printSimpleInstruction("not");
976 printSimpleInstruction("or");
979 assert(0 && "Illegal FCmp predicate");
984 void MSILWriter::printInvokeInstruction(const InvokeInst* Inst) {
985 std::string Label = "leave$normal_"+utostr(getUniqID());
988 for (int I = 3, E = Inst->getNumOperands(); I!=E; ++I)
989 printValueLoad(Inst->getOperand(I));
990 // Print call instruction
991 printFunctionCall(Inst->getOperand(0),Inst);
992 // Save function result and leave "try" block
993 printValueSave(Inst);
994 printSimpleInstruction("leave",Label.c_str());
996 Out << "catch [mscorlib]System.Exception {\n";
997 // Redirect to unwind block
998 printSimpleInstruction("pop");
999 printBranchToBlock(Inst->getParent(),NULL,Inst->getUnwindDest());
1000 Out << "}\n" << Label << ":\n";
1001 // Redirect to continue block
1002 printBranchToBlock(Inst->getParent(),NULL,Inst->getNormalDest());
1006 void MSILWriter::printSwitchInstruction(const SwitchInst* Inst) {
1007 // FIXME: Emulate with IL "switch" instruction
1008 // Emulate = if () else if () else if () else ...
1009 for (unsigned int I = 1, E = Inst->getNumCases(); I!=E; ++I) {
1010 printValueLoad(Inst->getCondition());
1011 printValueLoad(Inst->getCaseValue(I));
1012 printSimpleInstruction("ceq");
1013 // Condition jump to successor block
1014 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(I),NULL);
1016 // Jump to default block
1017 printBranchToBlock(Inst->getParent(),NULL,Inst->getDefaultDest());
1021 void MSILWriter::printVAArgInstruction(const VAArgInst* Inst) {
1022 printIndirectLoad(Inst->getOperand(0));
1023 printSimpleInstruction("call",
1024 "instance typedref [mscorlib]System.ArgIterator::GetNextArg()");
1025 printSimpleInstruction("refanyval","void*");
1027 "ldind."+getTypePostfix(PointerType::getUnqual(IntegerType::get(8)),false);
1028 printSimpleInstruction(Name.c_str());
1032 void MSILWriter::printAllocaInstruction(const AllocaInst* Inst) {
1033 uint64_t Size = TD->getTypeAllocSize(Inst->getAllocatedType());
1034 // Constant optimization.
1035 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(Inst->getOperand(0))) {
1036 printPtrLoad(CInt->getZExtValue()*Size);
1039 printValueLoad(Inst->getOperand(0));
1040 printSimpleInstruction("mul");
1042 printSimpleInstruction("localloc");
1046 void MSILWriter::printInstruction(const Instruction* Inst) {
1047 const Value *Left = 0, *Right = 0;
1048 if (Inst->getNumOperands()>=1) Left = Inst->getOperand(0);
1049 if (Inst->getNumOperands()>=2) Right = Inst->getOperand(1);
1050 // Print instruction
1051 // FIXME: "ShuffleVector","ExtractElement","InsertElement" support.
1052 switch (Inst->getOpcode()) {
1054 case Instruction::Ret:
1055 if (Inst->getNumOperands()) {
1056 printValueLoad(Left);
1057 printSimpleInstruction("ret");
1059 printSimpleInstruction("ret");
1061 case Instruction::Br:
1062 printBranchInstruction(cast<BranchInst>(Inst));
1065 case Instruction::Add:
1066 case Instruction::FAdd:
1067 printBinaryInstruction("add",Left,Right);
1069 case Instruction::Sub:
1070 case Instruction::FSub:
1071 printBinaryInstruction("sub",Left,Right);
1073 case Instruction::Mul:
1074 case Instruction::FMul:
1075 printBinaryInstruction("mul",Left,Right);
1077 case Instruction::UDiv:
1078 printBinaryInstruction("div.un",Left,Right);
1080 case Instruction::SDiv:
1081 case Instruction::FDiv:
1082 printBinaryInstruction("div",Left,Right);
1084 case Instruction::URem:
1085 printBinaryInstruction("rem.un",Left,Right);
1087 case Instruction::SRem:
1088 case Instruction::FRem:
1089 printBinaryInstruction("rem",Left,Right);
1092 case Instruction::ICmp:
1093 printICmpInstruction(cast<ICmpInst>(Inst)->getPredicate(),Left,Right);
1095 case Instruction::FCmp:
1096 printFCmpInstruction(cast<FCmpInst>(Inst)->getPredicate(),Left,Right);
1099 case Instruction::And:
1100 printBinaryInstruction("and",Left,Right);
1102 case Instruction::Or:
1103 printBinaryInstruction("or",Left,Right);
1105 case Instruction::Xor:
1106 printBinaryInstruction("xor",Left,Right);
1108 case Instruction::Shl:
1109 printValueLoad(Left);
1110 printValueLoad(Right);
1111 printSimpleInstruction("conv.i4");
1112 printSimpleInstruction("shl");
1114 case Instruction::LShr:
1115 printValueLoad(Left);
1116 printValueLoad(Right);
1117 printSimpleInstruction("conv.i4");
1118 printSimpleInstruction("shr.un");
1120 case Instruction::AShr:
1121 printValueLoad(Left);
1122 printValueLoad(Right);
1123 printSimpleInstruction("conv.i4");
1124 printSimpleInstruction("shr");
1126 case Instruction::Select:
1127 printSelectInstruction(Inst->getOperand(0),Inst->getOperand(1),Inst->getOperand(2));
1129 case Instruction::Load:
1130 printIndirectLoad(Inst->getOperand(0));
1132 case Instruction::Store:
1133 printIndirectSave(Inst->getOperand(1), Inst->getOperand(0));
1135 case Instruction::Trunc:
1136 case Instruction::ZExt:
1137 case Instruction::SExt:
1138 case Instruction::FPTrunc:
1139 case Instruction::FPExt:
1140 case Instruction::UIToFP:
1141 case Instruction::SIToFP:
1142 case Instruction::FPToUI:
1143 case Instruction::FPToSI:
1144 case Instruction::PtrToInt:
1145 case Instruction::IntToPtr:
1146 case Instruction::BitCast:
1147 printCastInstruction(Inst->getOpcode(),Left,
1148 cast<CastInst>(Inst)->getDestTy());
1150 case Instruction::GetElementPtr:
1151 printGepInstruction(Inst->getOperand(0),gep_type_begin(Inst),
1152 gep_type_end(Inst));
1154 case Instruction::Call:
1155 printCallInstruction(cast<CallInst>(Inst));
1157 case Instruction::Invoke:
1158 printInvokeInstruction(cast<InvokeInst>(Inst));
1160 case Instruction::Unwind:
1161 printSimpleInstruction("newobj",
1162 "instance void [mscorlib]System.Exception::.ctor()");
1163 printSimpleInstruction("throw");
1165 case Instruction::Switch:
1166 printSwitchInstruction(cast<SwitchInst>(Inst));
1168 case Instruction::Alloca:
1169 printAllocaInstruction(cast<AllocaInst>(Inst));
1171 case Instruction::Malloc:
1172 assert(0 && "LowerAllocationsPass used");
1174 case Instruction::Free:
1175 assert(0 && "LowerAllocationsPass used");
1177 case Instruction::Unreachable:
1178 printSimpleInstruction("ldstr", "\"Unreachable instruction\"");
1179 printSimpleInstruction("newobj",
1180 "instance void [mscorlib]System.Exception::.ctor(string)");
1181 printSimpleInstruction("throw");
1183 case Instruction::VAArg:
1184 printVAArgInstruction(cast<VAArgInst>(Inst));
1187 cerr << "Instruction = " << Inst->getName() << '\n';
1188 assert(0 && "Unsupported instruction");
1193 void MSILWriter::printLoop(const Loop* L) {
1194 Out << getLabelName(L->getHeader()->getName()) << ":\n";
1195 const std::vector<BasicBlock*>& blocks = L->getBlocks();
1196 for (unsigned I = 0, E = blocks.size(); I!=E; I++) {
1197 BasicBlock* BB = blocks[I];
1198 Loop* BBLoop = LInfo->getLoopFor(BB);
1200 printBasicBlock(BB);
1201 else if (BB==BBLoop->getHeader() && BBLoop->getParentLoop()==L)
1204 printSimpleInstruction("br",getLabelName(L->getHeader()->getName()).c_str());
1208 void MSILWriter::printBasicBlock(const BasicBlock* BB) {
1209 Out << getLabelName(BB) << ":\n";
1210 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) {
1211 const Instruction* Inst = I;
1212 // Comment llvm original instruction
1213 // Out << "\n//" << *Inst << "\n";
1214 // Do not handle PHI instruction in current block
1215 if (Inst->getOpcode()==Instruction::PHI) continue;
1216 // Print instruction
1217 printInstruction(Inst);
1219 if (Inst->getType()!=Type::VoidTy) {
1220 // Do not save value after invoke, it done in "try" block
1221 if (Inst->getOpcode()==Instruction::Invoke) continue;
1222 printValueSave(Inst);
1228 void MSILWriter::printLocalVariables(const Function& F) {
1230 const Type* Ty = NULL;
1231 std::set<const Value*> Printed;
1232 const Value* VaList = NULL;
1233 unsigned StackDepth = 8;
1234 // Find local variables
1235 for (const_inst_iterator I = inst_begin(&F), E = inst_end(&F); I!=E; ++I) {
1236 if (I->getOpcode()==Instruction::Call ||
1237 I->getOpcode()==Instruction::Invoke) {
1238 // Test stack depth.
1239 if (StackDepth<I->getNumOperands())
1240 StackDepth = I->getNumOperands();
1242 const AllocaInst* AI = dyn_cast<AllocaInst>(&*I);
1243 if (AI && !isa<GlobalVariable>(AI)) {
1244 // Local variable allocation.
1245 Ty = PointerType::getUnqual(AI->getAllocatedType());
1246 Name = getValueName(AI);
1247 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
1248 } else if (I->getType()!=Type::VoidTy) {
1249 // Operation result.
1251 Name = getValueName(&*I);
1252 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
1254 // Test on 'va_list' variable
1255 bool isVaList = false;
1256 if (const VAArgInst* VaInst = dyn_cast<VAArgInst>(&*I)) {
1257 // "va_list" as "va_arg" instruction operand.
1259 VaList = VaInst->getOperand(0);
1260 } else if (const IntrinsicInst* Inst = dyn_cast<IntrinsicInst>(&*I)) {
1261 // "va_list" as intrinsic function operand.
1262 switch (Inst->getIntrinsicID()) {
1263 case Intrinsic::vastart:
1264 case Intrinsic::vaend:
1265 case Intrinsic::vacopy:
1267 VaList = Inst->getOperand(1);
1273 // Print "va_list" variable.
1274 if (isVaList && Printed.insert(VaList).second) {
1275 Name = getValueName(VaList);
1276 Name.insert(Name.length()-1,"$valist");
1277 Out << "\t.locals (valuetype [mscorlib]System.ArgIterator "
1281 printSimpleInstruction(".maxstack",utostr(StackDepth*2).c_str());
1285 void MSILWriter::printFunctionBody(const Function& F) {
1287 for (Function::const_iterator I = F.begin(), E = F.end(); I!=E; ++I) {
1288 if (Loop *L = LInfo->getLoopFor(I)) {
1289 if (L->getHeader()==I && L->getParentLoop()==0)
1298 void MSILWriter::printConstantExpr(const ConstantExpr* CE) {
1299 const Value *left = 0, *right = 0;
1300 if (CE->getNumOperands()>=1) left = CE->getOperand(0);
1301 if (CE->getNumOperands()>=2) right = CE->getOperand(1);
1302 // Print instruction
1303 switch (CE->getOpcode()) {
1304 case Instruction::Trunc:
1305 case Instruction::ZExt:
1306 case Instruction::SExt:
1307 case Instruction::FPTrunc:
1308 case Instruction::FPExt:
1309 case Instruction::UIToFP:
1310 case Instruction::SIToFP:
1311 case Instruction::FPToUI:
1312 case Instruction::FPToSI:
1313 case Instruction::PtrToInt:
1314 case Instruction::IntToPtr:
1315 case Instruction::BitCast:
1316 printCastInstruction(CE->getOpcode(),left,CE->getType());
1318 case Instruction::GetElementPtr:
1319 printGepInstruction(CE->getOperand(0),gep_type_begin(CE),gep_type_end(CE));
1321 case Instruction::ICmp:
1322 printICmpInstruction(CE->getPredicate(),left,right);
1324 case Instruction::FCmp:
1325 printFCmpInstruction(CE->getPredicate(),left,right);
1327 case Instruction::Select:
1328 printSelectInstruction(CE->getOperand(0),CE->getOperand(1),CE->getOperand(2));
1330 case Instruction::Add:
1331 case Instruction::FAdd:
1332 printBinaryInstruction("add",left,right);
1334 case Instruction::Sub:
1335 case Instruction::FSub:
1336 printBinaryInstruction("sub",left,right);
1338 case Instruction::Mul:
1339 case Instruction::FMul:
1340 printBinaryInstruction("mul",left,right);
1342 case Instruction::UDiv:
1343 printBinaryInstruction("div.un",left,right);
1345 case Instruction::SDiv:
1346 case Instruction::FDiv:
1347 printBinaryInstruction("div",left,right);
1349 case Instruction::URem:
1350 printBinaryInstruction("rem.un",left,right);
1352 case Instruction::SRem:
1353 case Instruction::FRem:
1354 printBinaryInstruction("rem",left,right);
1356 case Instruction::And:
1357 printBinaryInstruction("and",left,right);
1359 case Instruction::Or:
1360 printBinaryInstruction("or",left,right);
1362 case Instruction::Xor:
1363 printBinaryInstruction("xor",left,right);
1365 case Instruction::Shl:
1366 printBinaryInstruction("shl",left,right);
1368 case Instruction::LShr:
1369 printBinaryInstruction("shr.un",left,right);
1371 case Instruction::AShr:
1372 printBinaryInstruction("shr",left,right);
1375 cerr << "Expression = " << *CE << "\n";
1376 assert(0 && "Invalid constant expression");
1381 void MSILWriter::printStaticInitializerList() {
1382 // List of global variables with uninitialized fields.
1383 for (std::map<const GlobalVariable*,std::vector<StaticInitializer> >::iterator
1384 VarI = StaticInitList.begin(), VarE = StaticInitList.end(); VarI!=VarE;
1386 const std::vector<StaticInitializer>& InitList = VarI->second;
1387 if (InitList.empty()) continue;
1388 // For each uninitialized field.
1389 for (std::vector<StaticInitializer>::const_iterator I = InitList.begin(),
1390 E = InitList.end(); I!=E; ++I) {
1391 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(I->constant)) {
1392 // Out << "\n// Init " << getValueName(VarI->first) << ", offset " <<
1393 // utostr(I->offset) << ", type "<< *I->constant->getType() << "\n\n";
1394 // Load variable address
1395 printValueLoad(VarI->first);
1398 printPtrLoad(I->offset);
1399 printSimpleInstruction("add");
1402 printConstantExpr(CE);
1403 // Save result at offset
1404 std::string postfix = getTypePostfix(CE->getType(),true);
1405 if (*postfix.begin()=='u') *postfix.begin() = 'i';
1406 postfix = "stind."+postfix;
1407 printSimpleInstruction(postfix.c_str());
1409 cerr << "Constant = " << *I->constant << '\n';
1410 assert(0 && "Invalid static initializer");
1417 void MSILWriter::printFunction(const Function& F) {
1418 bool isSigned = F.paramHasAttr(0, Attribute::SExt);
1419 Out << "\n.method static ";
1420 Out << (F.hasLocalLinkage() ? "private " : "public ");
1421 if (F.isVarArg()) Out << "vararg ";
1422 Out << getTypeName(F.getReturnType(),isSigned) <<
1423 getConvModopt(F.getCallingConv()) << getValueName(&F) << '\n';
1426 unsigned ArgIdx = 1;
1427 for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I!=E;
1429 isSigned = F.paramHasAttr(ArgIdx, Attribute::SExt);
1430 if (I!=F.arg_begin()) Out << ", ";
1431 Out << getTypeName(I->getType(),isSigned) << getValueName(I);
1433 Out << ") cil managed\n";
1436 printLocalVariables(F);
1437 printFunctionBody(F);
1442 void MSILWriter::printDeclarations(const TypeSymbolTable& ST) {
1444 std::set<const Type*> Printed;
1445 for (std::set<const Type*>::const_iterator
1446 UI = UsedTypes->begin(), UE = UsedTypes->end(); UI!=UE; ++UI) {
1447 const Type* Ty = *UI;
1448 if (isa<ArrayType>(Ty) || isa<VectorType>(Ty) || isa<StructType>(Ty))
1449 Name = getTypeName(Ty, false, true);
1450 // Type with no need to declare.
1452 // Print not duplicated type
1453 if (Printed.insert(Ty).second) {
1454 Out << ".class value explicit ansi sealed '" << Name << "'";
1455 Out << " { .pack " << 1 << " .size " << TD->getTypeAllocSize(Ty);
1462 unsigned int MSILWriter::getBitWidth(const Type* Ty) {
1463 unsigned int N = Ty->getPrimitiveSizeInBits();
1464 assert(N!=0 && "Invalid type in getBitWidth()");
1473 cerr << "Bits = " << N << '\n';
1474 assert(0 && "Unsupported integer width");
1476 return 0; // Not reached
1480 void MSILWriter::printStaticConstant(const Constant* C, uint64_t& Offset) {
1481 uint64_t TySize = 0;
1482 const Type* Ty = C->getType();
1483 // Print zero initialized constant.
1484 if (isa<ConstantAggregateZero>(C) || C->isNullValue()) {
1485 TySize = TD->getTypeAllocSize(C->getType());
1487 Out << "int8 (0) [" << TySize << "]";
1490 // Print constant initializer
1491 switch (Ty->getTypeID()) {
1492 case Type::IntegerTyID: {
1493 TySize = TD->getTypeAllocSize(Ty);
1494 const ConstantInt* Int = cast<ConstantInt>(C);
1495 Out << getPrimitiveTypeName(Ty,true) << "(" << Int->getSExtValue() << ")";
1498 case Type::FloatTyID:
1499 case Type::DoubleTyID: {
1500 TySize = TD->getTypeAllocSize(Ty);
1501 const ConstantFP* FP = cast<ConstantFP>(C);
1502 if (Ty->getTypeID() == Type::FloatTyID)
1504 (uint32_t)FP->getValueAPF().bitcastToAPInt().getZExtValue() << ')';
1507 FP->getValueAPF().bitcastToAPInt().getZExtValue() << ')';
1510 case Type::ArrayTyID:
1511 case Type::VectorTyID:
1512 case Type::StructTyID:
1513 for (unsigned I = 0, E = C->getNumOperands(); I<E; I++) {
1514 if (I!=0) Out << ",\n";
1515 printStaticConstant(C->getOperand(I),Offset);
1518 case Type::PointerTyID:
1519 TySize = TD->getTypeAllocSize(C->getType());
1520 // Initialize with global variable address
1521 if (const GlobalVariable *G = dyn_cast<GlobalVariable>(C)) {
1522 std::string name = getValueName(G);
1523 Out << "&(" << name.insert(name.length()-1,"$data") << ")";
1525 // Dynamic initialization
1526 if (!isa<ConstantPointerNull>(C) && !C->isNullValue())
1527 InitListPtr->push_back(StaticInitializer(C,Offset));
1528 // Null pointer initialization
1529 if (TySize==4) Out << "int32 (0)";
1530 else if (TySize==8) Out << "int64 (0)";
1531 else assert(0 && "Invalid pointer size");
1535 cerr << "TypeID = " << Ty->getTypeID() << '\n';
1536 assert(0 && "Invalid type in printStaticConstant()");
1543 void MSILWriter::printStaticInitializer(const Constant* C,
1544 const std::string& Name) {
1545 switch (C->getType()->getTypeID()) {
1546 case Type::IntegerTyID:
1547 case Type::FloatTyID:
1548 case Type::DoubleTyID:
1549 Out << getPrimitiveTypeName(C->getType(), false);
1551 case Type::ArrayTyID:
1552 case Type::VectorTyID:
1553 case Type::StructTyID:
1554 case Type::PointerTyID:
1555 Out << getTypeName(C->getType());
1558 cerr << "Type = " << *C << "\n";
1559 assert(0 && "Invalid constant type");
1561 // Print initializer
1562 std::string label = Name;
1563 label.insert(label.length()-1,"$data");
1564 Out << Name << " at " << label << '\n';
1565 Out << ".data " << label << " = {\n";
1566 uint64_t offset = 0;
1567 printStaticConstant(C,offset);
1572 void MSILWriter::printVariableDefinition(const GlobalVariable* G) {
1573 const Constant* C = G->getInitializer();
1574 if (C->isNullValue() || isa<ConstantAggregateZero>(C) || isa<UndefValue>(C))
1577 InitListPtr = &StaticInitList[G];
1578 printStaticInitializer(C,getValueName(G));
1582 void MSILWriter::printGlobalVariables() {
1583 if (ModulePtr->global_empty()) return;
1584 Module::global_iterator I,E;
1585 for (I = ModulePtr->global_begin(), E = ModulePtr->global_end(); I!=E; ++I) {
1586 // Variable definition
1587 Out << ".field static " << (I->isDeclaration() ? "public " :
1589 if (I->isDeclaration()) {
1590 Out << getTypeName(I->getType()) << getValueName(&*I) << "\n\n";
1592 printVariableDefinition(&*I);
1597 const char* MSILWriter::getLibraryName(const Function* F) {
1598 return getLibraryForSymbol(F->getName().c_str(), true, F->getCallingConv());
1602 const char* MSILWriter::getLibraryName(const GlobalVariable* GV) {
1603 return getLibraryForSymbol(Mang->getValueName(GV).c_str(), false, 0);
1607 const char* MSILWriter::getLibraryForSymbol(const char* Name, bool isFunction,
1608 unsigned CallingConv) {
1609 // TODO: Read *.def file with function and libraries definitions.
1610 return "MSVCRT.DLL";
1614 void MSILWriter::printExternals() {
1615 Module::const_iterator I,E;
1617 for (I=ModulePtr->begin(),E=ModulePtr->end(); I!=E; ++I) {
1619 if (I->isIntrinsic()) continue;
1620 if (I->isDeclaration()) {
1621 const Function* F = I;
1622 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
1624 getCallSignature(cast<FunctionType>(F->getFunctionType()), NULL, Name);
1625 Out << ".method static hidebysig pinvokeimpl(\""
1626 << getLibraryName(F) << "\")\n\t" << Sig << " preservesig {}\n\n";
1629 // External variables and static initialization.
1631 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1632 " native int LoadLibrary(string) preservesig {}\n"
1633 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1634 " native int GetProcAddress(native int, string) preservesig {}\n";
1636 ".method private static void* $MSIL_Import(string lib,string sym)\n"
1639 "\tcall\tnative int LoadLibrary(string)\n"
1641 "\tcall\tnative int GetProcAddress(native int,string)\n"
1644 "\tldstr\t\"Can no import variable\"\n"
1645 "\tnewobj\tinstance void [mscorlib]System.Exception::.ctor(string)\n"
1650 ".method static private void $MSIL_Init() managed cil\n{\n";
1651 printStaticInitializerList();
1652 // Foreach global variable.
1653 for (Module::global_iterator I = ModulePtr->global_begin(),
1654 E = ModulePtr->global_end(); I!=E; ++I) {
1655 if (!I->isDeclaration() || !I->hasDLLImportLinkage()) continue;
1656 // Use "LoadLibrary"/"GetProcAddress" to recive variable address.
1657 std::string Label = "not_null$_"+utostr(getUniqID());
1658 std::string Tmp = getTypeName(I->getType())+getValueName(&*I);
1659 printSimpleInstruction("ldsflda",Tmp.c_str());
1660 Out << "\tldstr\t\"" << getLibraryName(&*I) << "\"\n";
1661 Out << "\tldstr\t\"" << Mang->getValueName(&*I) << "\"\n";
1662 printSimpleInstruction("call","void* $MSIL_Import(string,string)");
1663 printIndirectSave(I->getType());
1665 printSimpleInstruction("ret");
1670 //===----------------------------------------------------------------------===//
1671 // External Interface declaration
1672 //===----------------------------------------------------------------------===//
1674 bool MSILTarget::addPassesToEmitWholeFile(PassManager &PM, raw_ostream &o,
1675 CodeGenFileType FileType,
1676 CodeGenOpt::Level OptLevel)
1678 if (FileType != TargetMachine::AssemblyFile) return true;
1679 MSILWriter* Writer = new MSILWriter(o);
1680 PM.add(createGCLoweringPass());
1681 PM.add(createLowerAllocationsPass(true));
1682 // FIXME: Handle switch trougth native IL instruction "switch"
1683 PM.add(createLowerSwitchPass());
1684 PM.add(createCFGSimplificationPass());
1685 PM.add(new MSILModule(Writer->UsedTypes,Writer->TD));
1687 PM.add(createGCInfoDeleter());