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/ErrorHandling.h"
23 #include "llvm/Support/InstVisitor.h"
24 #include "llvm/Support/MathExtras.h"
25 #include "llvm/Target/TargetRegistry.h"
26 #include "llvm/Transforms/Scalar.h"
27 #include "llvm/ADT/StringExtras.h"
28 #include "llvm/CodeGen/Passes.h"
32 // TargetMachine for the MSIL
33 struct MSILTarget : public TargetMachine {
34 MSILTarget(const Target &T, const std::string &TT, const std::string &FS)
37 virtual bool WantsWholeFile() const { return true; }
38 virtual bool addPassesToEmitWholeFile(PassManager &PM,
39 formatted_raw_ostream &Out,
40 CodeGenFileType FileType,
41 CodeGenOpt::Level OptLevel,
44 virtual const TargetData *getTargetData() const { return 0; }
48 extern "C" void LLVMInitializeMSILTarget() {
49 // Register the target.
50 RegisterTargetMachine<MSILTarget> X(TheMSILTarget);
53 bool MSILModule::runOnModule(Module &M) {
55 TD = &getAnalysis<TargetData>();
58 TypeSymbolTable& Table = M.getTypeSymbolTable();
59 std::set<const Type *> Types = getAnalysis<FindUsedTypes>().getTypes();
60 for (TypeSymbolTable::iterator I = Table.begin(), E = Table.end(); I!=E; ) {
61 if (!I->second->isStructTy() && !I->second->isOpaqueTy())
64 std::set<const Type *>::iterator T = Types.find(I->second);
73 // Find unnamed types.
74 unsigned RenameCounter = 0;
75 for (std::set<const Type *>::const_iterator I = Types.begin(),
76 E = Types.end(); I!=E; ++I)
77 if (const StructType *STy = dyn_cast<StructType>(*I)) {
78 while (ModulePtr->addTypeName("unnamed$"+utostr(RenameCounter), STy))
82 // Pointer for FunctionPass.
83 UsedTypes = &getAnalysis<FindUsedTypes>().getTypes();
87 char MSILModule::ID = 0;
88 char MSILWriter::ID = 0;
90 bool MSILWriter::runOnFunction(Function &F) {
91 if (F.isDeclaration()) return false;
93 // Do not codegen any 'available_externally' functions at all, they have
94 // definitions outside the translation unit.
95 if (F.hasAvailableExternallyLinkage())
98 LInfo = &getAnalysis<LoopInfo>();
104 bool MSILWriter::doInitialization(Module &M) {
106 Out << ".assembly extern mscorlib {}\n";
107 Out << ".assembly MSIL {}\n\n";
108 Out << "// External\n";
110 Out << "// Declarations\n";
111 printDeclarations(M.getTypeSymbolTable());
112 Out << "// Definitions\n";
113 printGlobalVariables();
114 Out << "// Startup code\n";
115 printModuleStartup();
120 bool MSILWriter::doFinalization(Module &M) {
125 void MSILWriter::printModuleStartup() {
127 ".method static public int32 $MSIL_Startup() {\n"
129 "\t.locals (native int i)\n"
130 "\t.locals (native int argc)\n"
131 "\t.locals (native int ptr)\n"
132 "\t.locals (void* argv)\n"
133 "\t.locals (string[] args)\n"
134 "\tcall\tstring[] [mscorlib]System.Environment::GetCommandLineArgs()\n"
141 printPtrLoad(TD->getPointerSize());
156 "\tcall\tnative int [mscorlib]System.Runtime.InteropServices.Marshal::"
157 "StringToHGlobalAnsi(string)\n"
161 printPtrLoad(TD->getPointerSize());
173 "\tcall void $MSIL_Init()\n";
175 // Call user 'main' function.
176 const Function* F = ModulePtr->getFunction("main");
177 if (!F || F->isDeclaration()) {
178 Out << "\tldc.i4.0\n\tret\n}\n";
182 std::string Args("");
183 Function::const_arg_iterator Arg1,Arg2;
185 switch (F->arg_size()) {
190 Arg1 = F->arg_begin();
191 if (Arg1->getType()->isIntegerTy()) {
192 Out << "\tldloc\targc\n";
193 Args = getTypeName(Arg1->getType());
198 Arg1 = Arg2 = F->arg_begin(); ++Arg2;
199 if (Arg1->getType()->isIntegerTy() &&
200 Arg2->getType()->getTypeID() == Type::PointerTyID) {
201 Out << "\tldloc\targc\n\tldloc\targv\n";
202 Args = getTypeName(Arg1->getType())+","+getTypeName(Arg2->getType());
210 bool RetVoid = (F->getReturnType()->getTypeID() == Type::VoidTyID);
211 if (BadSig || (!F->getReturnType()->isIntegerTy() && !RetVoid)) {
212 Out << "\tldc.i4.0\n";
214 Out << "\tcall\t" << getTypeName(F->getReturnType()) <<
215 getConvModopt(F->getCallingConv()) << "main(" << Args << ")\n";
217 Out << "\tldc.i4.0\n";
219 Out << "\tconv.i4\n";
224 bool MSILWriter::isZeroValue(const Value* V) {
225 if (const Constant *C = dyn_cast<Constant>(V))
226 return C->isNullValue();
231 std::string MSILWriter::getValueName(const Value* V) {
233 if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
234 Name = GV->getName();
236 unsigned &No = AnonValueNumbers[V];
237 if (No == 0) No = ++NextAnonValueNumber;
238 Name = "tmp" + utostr(No);
241 // Name into the quotes allow control and space characters.
246 std::string MSILWriter::getLabelName(const std::string& Name) {
247 if (Name.find('.')!=std::string::npos) {
248 std::string Tmp(Name);
249 // Replace unaccepable characters in the label name.
250 for (std::string::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I)
251 if (*I=='.') *I = '@';
258 std::string MSILWriter::getLabelName(const Value* V) {
260 if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
261 Name = GV->getName();
263 unsigned &No = AnonValueNumbers[V];
264 if (No == 0) No = ++NextAnonValueNumber;
265 Name = "tmp" + utostr(No);
268 return getLabelName(Name);
272 std::string MSILWriter::getConvModopt(CallingConv::ID CallingConvID) {
273 switch (CallingConvID) {
275 case CallingConv::Cold:
276 case CallingConv::Fast:
277 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) ";
278 case CallingConv::X86_FastCall:
279 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvFastcall) ";
280 case CallingConv::X86_StdCall:
281 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) ";
283 errs() << "CallingConvID = " << CallingConvID << '\n';
284 llvm_unreachable("Unsupported calling convention");
286 return ""; // Not reached
290 std::string MSILWriter::getArrayTypeName(Type::TypeID TyID, const Type* Ty) {
291 std::string Tmp = "";
292 const Type* ElemTy = Ty;
293 assert(Ty->getTypeID()==TyID && "Invalid type passed");
294 // Walk trought array element types.
296 // Multidimensional array.
297 if (ElemTy->getTypeID()==TyID) {
298 if (const ArrayType* ATy = dyn_cast<ArrayType>(ElemTy))
299 Tmp += utostr(ATy->getNumElements());
300 else if (const VectorType* VTy = dyn_cast<VectorType>(ElemTy))
301 Tmp += utostr(VTy->getNumElements());
302 ElemTy = cast<SequentialType>(ElemTy)->getElementType();
304 // Base element type found.
305 if (ElemTy->getTypeID()!=TyID) break;
308 return getTypeName(ElemTy, false, true)+"["+Tmp+"]";
312 std::string MSILWriter::getPrimitiveTypeName(const Type* Ty, bool isSigned) {
313 unsigned NumBits = 0;
314 switch (Ty->getTypeID()) {
317 case Type::IntegerTyID:
318 NumBits = getBitWidth(Ty);
322 return "unsigned int"+utostr(NumBits)+" ";
323 return "int"+utostr(NumBits)+" ";
324 case Type::FloatTyID:
326 case Type::DoubleTyID:
329 errs() << "Type = " << *Ty << '\n';
330 llvm_unreachable("Invalid primitive type");
332 return ""; // Not reached
336 std::string MSILWriter::getTypeName(const Type* Ty, bool isSigned,
338 if (Ty->isPrimitiveType() || Ty->isIntegerTy())
339 return getPrimitiveTypeName(Ty,isSigned);
340 // FIXME: "OpaqueType" support
341 switch (Ty->getTypeID()) {
342 case Type::PointerTyID:
344 case Type::StructTyID:
346 return ModulePtr->getTypeName(Ty);
347 return "valuetype '"+ModulePtr->getTypeName(Ty)+"' ";
348 case Type::ArrayTyID:
350 return getArrayTypeName(Ty->getTypeID(),Ty);
351 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
352 case Type::VectorTyID:
354 return getArrayTypeName(Ty->getTypeID(),Ty);
355 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
357 errs() << "Type = " << *Ty << '\n';
358 llvm_unreachable("Invalid type in getTypeName()");
360 return ""; // Not reached
364 MSILWriter::ValueType MSILWriter::getValueLocation(const Value* V) {
366 if (isa<Argument>(V))
369 else if (const Function* F = dyn_cast<Function>(V))
370 return F->hasLocalLinkage() ? InternalVT : GlobalVT;
372 else if (const GlobalVariable* G = dyn_cast<GlobalVariable>(V))
373 return G->hasLocalLinkage() ? InternalVT : GlobalVT;
375 else if (isa<Constant>(V))
376 return isa<ConstantExpr>(V) ? ConstExprVT : ConstVT;
382 std::string MSILWriter::getTypePostfix(const Type* Ty, bool Expand,
384 unsigned NumBits = 0;
385 switch (Ty->getTypeID()) {
386 // Integer constant, expanding for stack operations.
387 case Type::IntegerTyID:
388 NumBits = getBitWidth(Ty);
389 // Expand integer value to "int32" or "int64".
390 if (Expand) return (NumBits<=32 ? "i4" : "i8");
391 if (NumBits==1) return "i1";
392 return (isSigned ? "i" : "u")+utostr(NumBits/8);
394 case Type::FloatTyID:
396 case Type::DoubleTyID:
398 case Type::PointerTyID:
399 return "i"+utostr(TD->getTypeAllocSize(Ty));
401 errs() << "TypeID = " << Ty->getTypeID() << '\n';
402 llvm_unreachable("Invalid type in TypeToPostfix()");
404 return ""; // Not reached
408 void MSILWriter::printConvToPtr() {
409 switch (ModulePtr->getPointerSize()) {
410 case Module::Pointer32:
411 printSimpleInstruction("conv.u4");
413 case Module::Pointer64:
414 printSimpleInstruction("conv.u8");
417 llvm_unreachable("Module use not supporting pointer size");
422 void MSILWriter::printPtrLoad(uint64_t N) {
423 switch (ModulePtr->getPointerSize()) {
424 case Module::Pointer32:
425 printSimpleInstruction("ldc.i4",utostr(N).c_str());
426 // FIXME: Need overflow test?
428 errs() << "Value = " << utostr(N) << '\n';
429 llvm_unreachable("32-bit pointer overflowed");
432 case Module::Pointer64:
433 printSimpleInstruction("ldc.i8",utostr(N).c_str());
436 llvm_unreachable("Module use not supporting pointer size");
441 void MSILWriter::printValuePtrLoad(const Value* V) {
447 void MSILWriter::printConstLoad(const Constant* C) {
448 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(C)) {
450 Out << "\tldc." << getTypePostfix(C->getType(),true) << '\t';
451 if (CInt->isMinValue(true))
452 Out << CInt->getSExtValue();
454 Out << CInt->getZExtValue();
455 } else if (const ConstantFP* FP = dyn_cast<ConstantFP>(C)) {
459 if (FP->getType()->getTypeID()==Type::FloatTyID) {
460 X = (uint32_t)FP->getValueAPF().bitcastToAPInt().getZExtValue();
463 X = FP->getValueAPF().bitcastToAPInt().getZExtValue();
466 Out << "\tldc.r" << Size << "\t( " << utohexstr(X) << ')';
467 } else if (isa<UndefValue>(C)) {
468 // Undefined constant value = NULL.
471 errs() << "Constant = " << *C << '\n';
472 llvm_unreachable("Invalid constant value");
478 void MSILWriter::printValueLoad(const Value* V) {
479 MSILWriter::ValueType Location = getValueLocation(V);
481 // Global variable or function address.
484 if (const Function* F = dyn_cast<Function>(V)) {
485 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
486 printSimpleInstruction("ldftn",
487 getCallSignature(F->getFunctionType(),NULL,Name).c_str());
490 const Type* ElemTy = cast<PointerType>(V->getType())->getElementType();
491 if (Location==GlobalVT && cast<GlobalVariable>(V)->hasDLLImportLinkage()) {
492 Tmp = "void* "+getValueName(V);
493 printSimpleInstruction("ldsfld",Tmp.c_str());
495 Tmp = getTypeName(ElemTy)+getValueName(V);
496 printSimpleInstruction("ldsflda",Tmp.c_str());
500 // Function argument.
502 printSimpleInstruction("ldarg",getValueName(V).c_str());
504 // Local function variable.
506 printSimpleInstruction("ldloc",getValueName(V).c_str());
510 if (isa<ConstantPointerNull>(V))
513 printConstLoad(cast<Constant>(V));
515 // Constant expression.
517 printConstantExpr(cast<ConstantExpr>(V));
520 errs() << "Value = " << *V << '\n';
521 llvm_unreachable("Invalid value location");
526 void MSILWriter::printValueSave(const Value* V) {
527 switch (getValueLocation(V)) {
529 printSimpleInstruction("starg",getValueName(V).c_str());
532 printSimpleInstruction("stloc",getValueName(V).c_str());
535 errs() << "Value = " << *V << '\n';
536 llvm_unreachable("Invalid value location");
541 void MSILWriter::printBinaryInstruction(const char* Name, const Value* Left,
542 const Value* Right) {
543 printValueLoad(Left);
544 printValueLoad(Right);
545 Out << '\t' << Name << '\n';
549 void MSILWriter::printSimpleInstruction(const char* Inst, const char* Operand) {
551 Out << '\t' << Inst << '\t' << Operand << '\n';
553 Out << '\t' << Inst << '\n';
557 void MSILWriter::printPHICopy(const BasicBlock* Src, const BasicBlock* Dst) {
558 for (BasicBlock::const_iterator I = Dst->begin(); isa<PHINode>(I); ++I) {
559 const PHINode* Phi = cast<PHINode>(I);
560 const Value* Val = Phi->getIncomingValueForBlock(Src);
561 if (isa<UndefValue>(Val)) continue;
568 void MSILWriter::printBranchToBlock(const BasicBlock* CurrBB,
569 const BasicBlock* TrueBB,
570 const BasicBlock* FalseBB) {
571 if (TrueBB==FalseBB) {
572 // "TrueBB" and "FalseBB" destination equals
573 printPHICopy(CurrBB,TrueBB);
574 printSimpleInstruction("pop");
575 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
576 } else if (FalseBB==NULL) {
577 // If "FalseBB" not used the jump have condition
578 printPHICopy(CurrBB,TrueBB);
579 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
580 } else if (TrueBB==NULL) {
581 // If "TrueBB" not used the jump is unconditional
582 printPHICopy(CurrBB,FalseBB);
583 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
585 // Copy PHI instructions for each block
586 std::string TmpLabel;
587 // Print PHI instructions for "TrueBB"
588 if (isa<PHINode>(TrueBB->begin())) {
589 TmpLabel = getLabelName(TrueBB)+"$phi_"+utostr(getUniqID());
590 printSimpleInstruction("brtrue",TmpLabel.c_str());
592 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
594 // Print PHI instructions for "FalseBB"
595 if (isa<PHINode>(FalseBB->begin())) {
596 printPHICopy(CurrBB,FalseBB);
597 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
599 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
601 if (isa<PHINode>(TrueBB->begin())) {
602 // Handle "TrueBB" PHI Copy
603 Out << TmpLabel << ":\n";
604 printPHICopy(CurrBB,TrueBB);
605 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
611 void MSILWriter::printBranchInstruction(const BranchInst* Inst) {
612 if (Inst->isUnconditional()) {
613 printBranchToBlock(Inst->getParent(),NULL,Inst->getSuccessor(0));
615 printValueLoad(Inst->getCondition());
616 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(0),
617 Inst->getSuccessor(1));
622 void MSILWriter::printSelectInstruction(const Value* Cond, const Value* VTrue,
623 const Value* VFalse) {
624 std::string TmpLabel = std::string("select$true_")+utostr(getUniqID());
625 printValueLoad(VTrue);
626 printValueLoad(Cond);
627 printSimpleInstruction("brtrue",TmpLabel.c_str());
628 printSimpleInstruction("pop");
629 printValueLoad(VFalse);
630 Out << TmpLabel << ":\n";
634 void MSILWriter::printIndirectLoad(const Value* V) {
635 const Type* Ty = V->getType();
637 if (const PointerType* P = dyn_cast<PointerType>(Ty))
638 Ty = P->getElementType();
639 std::string Tmp = "ldind."+getTypePostfix(Ty, false);
640 printSimpleInstruction(Tmp.c_str());
644 void MSILWriter::printIndirectSave(const Value* Ptr, const Value* Val) {
647 printIndirectSave(Val->getType());
651 void MSILWriter::printIndirectSave(const Type* Ty) {
652 // Instruction need signed postfix for any type.
653 std::string postfix = getTypePostfix(Ty, false);
654 if (*postfix.begin()=='u') *postfix.begin() = 'i';
655 postfix = "stind."+postfix;
656 printSimpleInstruction(postfix.c_str());
660 void MSILWriter::printCastInstruction(unsigned int Op, const Value* V,
661 const Type* Ty, const Type* SrcTy) {
666 case Instruction::SExt:
667 // If sign extending int, convert first from unsigned to signed
668 // with the same bit size - because otherwise we will loose the sign.
670 Tmp = "conv."+getTypePostfix(SrcTy,false,true);
671 printSimpleInstruction(Tmp.c_str());
674 case Instruction::SIToFP:
675 case Instruction::FPToSI:
676 Tmp = "conv."+getTypePostfix(Ty,false,true);
677 printSimpleInstruction(Tmp.c_str());
680 case Instruction::FPTrunc:
681 case Instruction::FPExt:
682 case Instruction::UIToFP:
683 case Instruction::Trunc:
684 case Instruction::ZExt:
685 case Instruction::FPToUI:
686 case Instruction::PtrToInt:
687 case Instruction::IntToPtr:
688 Tmp = "conv."+getTypePostfix(Ty,false);
689 printSimpleInstruction(Tmp.c_str());
692 case Instruction::BitCast:
693 // FIXME: meaning that ld*/st* instruction do not change data format.
696 errs() << "Opcode = " << Op << '\n';
697 llvm_unreachable("Invalid conversion instruction");
702 void MSILWriter::printGepInstruction(const Value* V, gep_type_iterator I,
703 gep_type_iterator E) {
706 printValuePtrLoad(V);
707 // Calculate element offset.
710 const Value* IndexValue = I.getOperand();
711 if (const StructType* StrucTy = dyn_cast<StructType>(*I)) {
712 uint64_t FieldIndex = cast<ConstantInt>(IndexValue)->getZExtValue();
713 // Offset is the sum of all previous structure fields.
714 for (uint64_t F = 0; F<FieldIndex; ++F)
715 Size += TD->getTypeAllocSize(StrucTy->getContainedType((unsigned)F));
717 printSimpleInstruction("add");
719 } else if (const SequentialType* SeqTy = dyn_cast<SequentialType>(*I)) {
720 Size = TD->getTypeAllocSize(SeqTy->getElementType());
722 Size = TD->getTypeAllocSize(*I);
724 // Add offset of current element to stack top.
725 if (!isZeroValue(IndexValue)) {
726 // Constant optimization.
727 if (const ConstantInt* C = dyn_cast<ConstantInt>(IndexValue)) {
728 if (C->getValue().isNegative()) {
729 printPtrLoad(C->getValue().abs().getZExtValue()*Size);
730 printSimpleInstruction("sub");
733 printPtrLoad(C->getZExtValue()*Size);
736 printValuePtrLoad(IndexValue);
737 printSimpleInstruction("mul");
739 printSimpleInstruction("add");
745 std::string MSILWriter::getCallSignature(const FunctionType* Ty,
746 const Instruction* Inst,
749 if (Ty->isVarArg()) Tmp += "vararg ";
750 // Name and return type.
751 Tmp += getTypeName(Ty->getReturnType())+Name+"(";
752 // Function argument type list.
753 unsigned NumParams = Ty->getNumParams();
754 for (unsigned I = 0; I!=NumParams; ++I) {
755 if (I!=0) Tmp += ",";
756 Tmp += getTypeName(Ty->getParamType(I));
758 // CLR needs to know the exact amount of parameters received by vararg
759 // function, because caller cleans the stack.
760 if (Ty->isVarArg() && Inst) {
761 // Origin to function arguments in "CallInst" or "InvokeInst".
762 unsigned Org = isa<InvokeInst>(Inst) ? 3 : 1;
763 // Print variable argument types.
764 unsigned NumOperands = Inst->getNumOperands()-Org;
765 if (NumParams<NumOperands) {
766 if (NumParams!=0) Tmp += ", ";
768 for (unsigned J = NumParams; J!=NumOperands; ++J) {
769 if (J!=NumParams) Tmp += ", ";
770 Tmp += getTypeName(Inst->getOperand(J+Org)->getType());
778 void MSILWriter::printFunctionCall(const Value* FnVal,
779 const Instruction* Inst) {
780 // Get function calling convention.
781 std::string Name = "";
782 if (const CallInst* Call = dyn_cast<CallInst>(Inst))
783 Name = getConvModopt(Call->getCallingConv());
784 else if (const InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst))
785 Name = getConvModopt(Invoke->getCallingConv());
787 errs() << "Instruction = " << Inst->getName() << '\n';
788 llvm_unreachable("Need \"Invoke\" or \"Call\" instruction only");
790 if (const Function* F = dyn_cast<Function>(FnVal)) {
792 Name += getValueName(F);
793 printSimpleInstruction("call",
794 getCallSignature(F->getFunctionType(),Inst,Name).c_str());
796 // Indirect function call.
797 const PointerType* PTy = cast<PointerType>(FnVal->getType());
798 const FunctionType* FTy = cast<FunctionType>(PTy->getElementType());
799 // Load function address.
800 printValueLoad(FnVal);
801 printSimpleInstruction("calli",getCallSignature(FTy,Inst,Name).c_str());
806 void MSILWriter::printIntrinsicCall(const IntrinsicInst* Inst) {
808 switch (Inst->getIntrinsicID()) {
809 case Intrinsic::vastart:
810 Name = getValueName(Inst->getOperand(1));
811 Name.insert(Name.length()-1,"$valist");
812 // Obtain the argument handle.
813 printSimpleInstruction("ldloca",Name.c_str());
814 printSimpleInstruction("arglist");
815 printSimpleInstruction("call",
816 "instance void [mscorlib]System.ArgIterator::.ctor"
817 "(valuetype [mscorlib]System.RuntimeArgumentHandle)");
818 // Save as pointer type "void*"
819 printValueLoad(Inst->getOperand(1));
820 printSimpleInstruction("ldloca",Name.c_str());
821 printIndirectSave(PointerType::getUnqual(
822 IntegerType::get(Inst->getContext(), 8)));
824 case Intrinsic::vaend:
825 // Close argument list handle.
826 printIndirectLoad(Inst->getOperand(1));
827 printSimpleInstruction("call","instance void [mscorlib]System.ArgIterator::End()");
829 case Intrinsic::vacopy:
830 // Copy "ArgIterator" valuetype.
831 printIndirectLoad(Inst->getOperand(1));
832 printIndirectLoad(Inst->getOperand(2));
833 printSimpleInstruction("cpobj","[mscorlib]System.ArgIterator");
836 errs() << "Intrinsic ID = " << Inst->getIntrinsicID() << '\n';
837 llvm_unreachable("Invalid intrinsic function");
842 void MSILWriter::printCallInstruction(const Instruction* Inst) {
843 if (isa<IntrinsicInst>(Inst)) {
844 // Handle intrinsic function.
845 printIntrinsicCall(cast<IntrinsicInst>(Inst));
847 // Load arguments to stack and call function.
848 for (int I = 1, E = Inst->getNumOperands(); I!=E; ++I)
849 printValueLoad(Inst->getOperand(I));
850 printFunctionCall(Inst->getOperand(0),Inst);
855 void MSILWriter::printICmpInstruction(unsigned Predicate, const Value* Left,
856 const Value* Right) {
858 case ICmpInst::ICMP_EQ:
859 printBinaryInstruction("ceq",Left,Right);
861 case ICmpInst::ICMP_NE:
862 // Emulate = not neg (Op1 eq Op2)
863 printBinaryInstruction("ceq",Left,Right);
864 printSimpleInstruction("neg");
865 printSimpleInstruction("not");
867 case ICmpInst::ICMP_ULE:
868 case ICmpInst::ICMP_SLE:
869 // Emulate = (Op1 eq Op2) or (Op1 lt Op2)
870 printBinaryInstruction("ceq",Left,Right);
871 if (Predicate==ICmpInst::ICMP_ULE)
872 printBinaryInstruction("clt.un",Left,Right);
874 printBinaryInstruction("clt",Left,Right);
875 printSimpleInstruction("or");
877 case ICmpInst::ICMP_UGE:
878 case ICmpInst::ICMP_SGE:
879 // Emulate = (Op1 eq Op2) or (Op1 gt Op2)
880 printBinaryInstruction("ceq",Left,Right);
881 if (Predicate==ICmpInst::ICMP_UGE)
882 printBinaryInstruction("cgt.un",Left,Right);
884 printBinaryInstruction("cgt",Left,Right);
885 printSimpleInstruction("or");
887 case ICmpInst::ICMP_ULT:
888 printBinaryInstruction("clt.un",Left,Right);
890 case ICmpInst::ICMP_SLT:
891 printBinaryInstruction("clt",Left,Right);
893 case ICmpInst::ICMP_UGT:
894 printBinaryInstruction("cgt.un",Left,Right);
896 case ICmpInst::ICMP_SGT:
897 printBinaryInstruction("cgt",Left,Right);
900 errs() << "Predicate = " << Predicate << '\n';
901 llvm_unreachable("Invalid icmp predicate");
906 void MSILWriter::printFCmpInstruction(unsigned Predicate, const Value* Left,
907 const Value* Right) {
908 // FIXME: Correct comparison
909 std::string NanFunc = "bool [mscorlib]System.Double::IsNaN(float64)";
911 case FCmpInst::FCMP_UGT:
912 // X > Y || llvm_fcmp_uno(X, Y)
913 printBinaryInstruction("cgt",Left,Right);
914 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
915 printSimpleInstruction("or");
917 case FCmpInst::FCMP_OGT:
919 printBinaryInstruction("cgt",Left,Right);
921 case FCmpInst::FCMP_UGE:
922 // X >= Y || llvm_fcmp_uno(X, Y)
923 printBinaryInstruction("ceq",Left,Right);
924 printBinaryInstruction("cgt",Left,Right);
925 printSimpleInstruction("or");
926 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
927 printSimpleInstruction("or");
929 case FCmpInst::FCMP_OGE:
931 printBinaryInstruction("ceq",Left,Right);
932 printBinaryInstruction("cgt",Left,Right);
933 printSimpleInstruction("or");
935 case FCmpInst::FCMP_ULT:
936 // X < Y || llvm_fcmp_uno(X, Y)
937 printBinaryInstruction("clt",Left,Right);
938 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
939 printSimpleInstruction("or");
941 case FCmpInst::FCMP_OLT:
943 printBinaryInstruction("clt",Left,Right);
945 case FCmpInst::FCMP_ULE:
946 // X <= Y || llvm_fcmp_uno(X, Y)
947 printBinaryInstruction("ceq",Left,Right);
948 printBinaryInstruction("clt",Left,Right);
949 printSimpleInstruction("or");
950 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
951 printSimpleInstruction("or");
953 case FCmpInst::FCMP_OLE:
955 printBinaryInstruction("ceq",Left,Right);
956 printBinaryInstruction("clt",Left,Right);
957 printSimpleInstruction("or");
959 case FCmpInst::FCMP_UEQ:
960 // X == Y || llvm_fcmp_uno(X, Y)
961 printBinaryInstruction("ceq",Left,Right);
962 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
963 printSimpleInstruction("or");
965 case FCmpInst::FCMP_OEQ:
967 printBinaryInstruction("ceq",Left,Right);
969 case FCmpInst::FCMP_UNE:
971 printBinaryInstruction("ceq",Left,Right);
972 printSimpleInstruction("neg");
973 printSimpleInstruction("not");
975 case FCmpInst::FCMP_ONE:
976 // X != Y && llvm_fcmp_ord(X, Y)
977 printBinaryInstruction("ceq",Left,Right);
978 printSimpleInstruction("not");
980 case FCmpInst::FCMP_ORD:
981 // return X == X && Y == Y
982 printBinaryInstruction("ceq",Left,Left);
983 printBinaryInstruction("ceq",Right,Right);
984 printSimpleInstruction("or");
986 case FCmpInst::FCMP_UNO:
988 printBinaryInstruction("ceq",Left,Left);
989 printSimpleInstruction("not");
990 printBinaryInstruction("ceq",Right,Right);
991 printSimpleInstruction("not");
992 printSimpleInstruction("or");
995 llvm_unreachable("Illegal FCmp predicate");
1000 void MSILWriter::printInvokeInstruction(const InvokeInst* Inst) {
1001 std::string Label = "leave$normal_"+utostr(getUniqID());
1004 for (int I = 3, E = Inst->getNumOperands(); I!=E; ++I)
1005 printValueLoad(Inst->getOperand(I));
1006 // Print call instruction
1007 printFunctionCall(Inst->getOperand(0),Inst);
1008 // Save function result and leave "try" block
1009 printValueSave(Inst);
1010 printSimpleInstruction("leave",Label.c_str());
1012 Out << "catch [mscorlib]System.Exception {\n";
1013 // Redirect to unwind block
1014 printSimpleInstruction("pop");
1015 printBranchToBlock(Inst->getParent(),NULL,Inst->getUnwindDest());
1016 Out << "}\n" << Label << ":\n";
1017 // Redirect to continue block
1018 printBranchToBlock(Inst->getParent(),NULL,Inst->getNormalDest());
1022 void MSILWriter::printSwitchInstruction(const SwitchInst* Inst) {
1023 // FIXME: Emulate with IL "switch" instruction
1024 // Emulate = if () else if () else if () else ...
1025 for (unsigned int I = 1, E = Inst->getNumCases(); I!=E; ++I) {
1026 printValueLoad(Inst->getCondition());
1027 printValueLoad(Inst->getCaseValue(I));
1028 printSimpleInstruction("ceq");
1029 // Condition jump to successor block
1030 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(I),NULL);
1032 // Jump to default block
1033 printBranchToBlock(Inst->getParent(),NULL,Inst->getDefaultDest());
1037 void MSILWriter::printVAArgInstruction(const VAArgInst* Inst) {
1038 printIndirectLoad(Inst->getOperand(0));
1039 printSimpleInstruction("call",
1040 "instance typedref [mscorlib]System.ArgIterator::GetNextArg()");
1041 printSimpleInstruction("refanyval","void*");
1043 "ldind."+getTypePostfix(PointerType::getUnqual(
1044 IntegerType::get(Inst->getContext(), 8)),false);
1045 printSimpleInstruction(Name.c_str());
1049 void MSILWriter::printAllocaInstruction(const AllocaInst* Inst) {
1050 uint64_t Size = TD->getTypeAllocSize(Inst->getAllocatedType());
1051 // Constant optimization.
1052 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(Inst->getOperand(0))) {
1053 printPtrLoad(CInt->getZExtValue()*Size);
1056 printValueLoad(Inst->getOperand(0));
1057 printSimpleInstruction("mul");
1059 printSimpleInstruction("localloc");
1063 void MSILWriter::printInstruction(const Instruction* Inst) {
1064 const Value *Left = 0, *Right = 0;
1065 if (Inst->getNumOperands()>=1) Left = Inst->getOperand(0);
1066 if (Inst->getNumOperands()>=2) Right = Inst->getOperand(1);
1067 // Print instruction
1068 // FIXME: "ShuffleVector","ExtractElement","InsertElement" support.
1069 switch (Inst->getOpcode()) {
1071 case Instruction::Ret:
1072 if (Inst->getNumOperands()) {
1073 printValueLoad(Left);
1074 printSimpleInstruction("ret");
1076 printSimpleInstruction("ret");
1078 case Instruction::Br:
1079 printBranchInstruction(cast<BranchInst>(Inst));
1082 case Instruction::Add:
1083 case Instruction::FAdd:
1084 printBinaryInstruction("add",Left,Right);
1086 case Instruction::Sub:
1087 case Instruction::FSub:
1088 printBinaryInstruction("sub",Left,Right);
1090 case Instruction::Mul:
1091 case Instruction::FMul:
1092 printBinaryInstruction("mul",Left,Right);
1094 case Instruction::UDiv:
1095 printBinaryInstruction("div.un",Left,Right);
1097 case Instruction::SDiv:
1098 case Instruction::FDiv:
1099 printBinaryInstruction("div",Left,Right);
1101 case Instruction::URem:
1102 printBinaryInstruction("rem.un",Left,Right);
1104 case Instruction::SRem:
1105 case Instruction::FRem:
1106 printBinaryInstruction("rem",Left,Right);
1109 case Instruction::ICmp:
1110 printICmpInstruction(cast<ICmpInst>(Inst)->getPredicate(),Left,Right);
1112 case Instruction::FCmp:
1113 printFCmpInstruction(cast<FCmpInst>(Inst)->getPredicate(),Left,Right);
1116 case Instruction::And:
1117 printBinaryInstruction("and",Left,Right);
1119 case Instruction::Or:
1120 printBinaryInstruction("or",Left,Right);
1122 case Instruction::Xor:
1123 printBinaryInstruction("xor",Left,Right);
1125 case Instruction::Shl:
1126 printValueLoad(Left);
1127 printValueLoad(Right);
1128 printSimpleInstruction("conv.i4");
1129 printSimpleInstruction("shl");
1131 case Instruction::LShr:
1132 printValueLoad(Left);
1133 printValueLoad(Right);
1134 printSimpleInstruction("conv.i4");
1135 printSimpleInstruction("shr.un");
1137 case Instruction::AShr:
1138 printValueLoad(Left);
1139 printValueLoad(Right);
1140 printSimpleInstruction("conv.i4");
1141 printSimpleInstruction("shr");
1143 case Instruction::Select:
1144 printSelectInstruction(Inst->getOperand(0),Inst->getOperand(1),Inst->getOperand(2));
1146 case Instruction::Load:
1147 printIndirectLoad(Inst->getOperand(0));
1149 case Instruction::Store:
1150 printIndirectSave(Inst->getOperand(1), Inst->getOperand(0));
1152 case Instruction::SExt:
1153 printCastInstruction(Inst->getOpcode(),Left,
1154 cast<CastInst>(Inst)->getDestTy(),
1155 cast<CastInst>(Inst)->getSrcTy());
1157 case Instruction::Trunc:
1158 case Instruction::ZExt:
1159 case Instruction::FPTrunc:
1160 case Instruction::FPExt:
1161 case Instruction::UIToFP:
1162 case Instruction::SIToFP:
1163 case Instruction::FPToUI:
1164 case Instruction::FPToSI:
1165 case Instruction::PtrToInt:
1166 case Instruction::IntToPtr:
1167 case Instruction::BitCast:
1168 printCastInstruction(Inst->getOpcode(),Left,
1169 cast<CastInst>(Inst)->getDestTy());
1171 case Instruction::GetElementPtr:
1172 printGepInstruction(Inst->getOperand(0),gep_type_begin(Inst),
1173 gep_type_end(Inst));
1175 case Instruction::Call:
1176 printCallInstruction(cast<CallInst>(Inst));
1178 case Instruction::Invoke:
1179 printInvokeInstruction(cast<InvokeInst>(Inst));
1181 case Instruction::Unwind:
1182 printSimpleInstruction("newobj",
1183 "instance void [mscorlib]System.Exception::.ctor()");
1184 printSimpleInstruction("throw");
1186 case Instruction::Switch:
1187 printSwitchInstruction(cast<SwitchInst>(Inst));
1189 case Instruction::Alloca:
1190 printAllocaInstruction(cast<AllocaInst>(Inst));
1192 case Instruction::Unreachable:
1193 printSimpleInstruction("ldstr", "\"Unreachable instruction\"");
1194 printSimpleInstruction("newobj",
1195 "instance void [mscorlib]System.Exception::.ctor(string)");
1196 printSimpleInstruction("throw");
1198 case Instruction::VAArg:
1199 printVAArgInstruction(cast<VAArgInst>(Inst));
1202 errs() << "Instruction = " << Inst->getName() << '\n';
1203 llvm_unreachable("Unsupported instruction");
1208 void MSILWriter::printLoop(const Loop* L) {
1209 Out << getLabelName(L->getHeader()->getName()) << ":\n";
1210 const std::vector<BasicBlock*>& blocks = L->getBlocks();
1211 for (unsigned I = 0, E = blocks.size(); I!=E; I++) {
1212 BasicBlock* BB = blocks[I];
1213 Loop* BBLoop = LInfo->getLoopFor(BB);
1215 printBasicBlock(BB);
1216 else if (BB==BBLoop->getHeader() && BBLoop->getParentLoop()==L)
1219 printSimpleInstruction("br",getLabelName(L->getHeader()->getName()).c_str());
1223 void MSILWriter::printBasicBlock(const BasicBlock* BB) {
1224 Out << getLabelName(BB) << ":\n";
1225 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) {
1226 const Instruction* Inst = I;
1227 // Comment llvm original instruction
1228 // Out << "\n//" << *Inst << "\n";
1229 // Do not handle PHI instruction in current block
1230 if (Inst->getOpcode()==Instruction::PHI) continue;
1231 // Print instruction
1232 printInstruction(Inst);
1234 if (Inst->getType()!=Type::getVoidTy(BB->getContext())) {
1235 // Do not save value after invoke, it done in "try" block
1236 if (Inst->getOpcode()==Instruction::Invoke) continue;
1237 printValueSave(Inst);
1243 void MSILWriter::printLocalVariables(const Function& F) {
1245 const Type* Ty = NULL;
1246 std::set<const Value*> Printed;
1247 const Value* VaList = NULL;
1248 unsigned StackDepth = 8;
1249 // Find local variables
1250 for (const_inst_iterator I = inst_begin(&F), E = inst_end(&F); I!=E; ++I) {
1251 if (I->getOpcode()==Instruction::Call ||
1252 I->getOpcode()==Instruction::Invoke) {
1253 // Test stack depth.
1254 if (StackDepth<I->getNumOperands())
1255 StackDepth = I->getNumOperands();
1257 const AllocaInst* AI = dyn_cast<AllocaInst>(&*I);
1258 if (AI && !isa<GlobalVariable>(AI)) {
1259 // Local variable allocation.
1260 Ty = PointerType::getUnqual(AI->getAllocatedType());
1261 Name = getValueName(AI);
1262 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
1263 } else if (I->getType()!=Type::getVoidTy(F.getContext())) {
1264 // Operation result.
1266 Name = getValueName(&*I);
1267 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
1269 // Test on 'va_list' variable
1270 bool isVaList = false;
1271 if (const VAArgInst* VaInst = dyn_cast<VAArgInst>(&*I)) {
1272 // "va_list" as "va_arg" instruction operand.
1274 VaList = VaInst->getOperand(0);
1275 } else if (const IntrinsicInst* Inst = dyn_cast<IntrinsicInst>(&*I)) {
1276 // "va_list" as intrinsic function operand.
1277 switch (Inst->getIntrinsicID()) {
1278 case Intrinsic::vastart:
1279 case Intrinsic::vaend:
1280 case Intrinsic::vacopy:
1282 VaList = Inst->getOperand(1);
1288 // Print "va_list" variable.
1289 if (isVaList && Printed.insert(VaList).second) {
1290 Name = getValueName(VaList);
1291 Name.insert(Name.length()-1,"$valist");
1292 Out << "\t.locals (valuetype [mscorlib]System.ArgIterator "
1296 printSimpleInstruction(".maxstack",utostr(StackDepth*2).c_str());
1300 void MSILWriter::printFunctionBody(const Function& F) {
1302 for (Function::const_iterator I = F.begin(), E = F.end(); I!=E; ++I) {
1303 if (Loop *L = LInfo->getLoopFor(I)) {
1304 if (L->getHeader()==I && L->getParentLoop()==0)
1313 void MSILWriter::printConstantExpr(const ConstantExpr* CE) {
1314 const Value *left = 0, *right = 0;
1315 if (CE->getNumOperands()>=1) left = CE->getOperand(0);
1316 if (CE->getNumOperands()>=2) right = CE->getOperand(1);
1317 // Print instruction
1318 switch (CE->getOpcode()) {
1319 case Instruction::Trunc:
1320 case Instruction::ZExt:
1321 case Instruction::SExt:
1322 case Instruction::FPTrunc:
1323 case Instruction::FPExt:
1324 case Instruction::UIToFP:
1325 case Instruction::SIToFP:
1326 case Instruction::FPToUI:
1327 case Instruction::FPToSI:
1328 case Instruction::PtrToInt:
1329 case Instruction::IntToPtr:
1330 case Instruction::BitCast:
1331 printCastInstruction(CE->getOpcode(),left,CE->getType());
1333 case Instruction::GetElementPtr:
1334 printGepInstruction(CE->getOperand(0),gep_type_begin(CE),gep_type_end(CE));
1336 case Instruction::ICmp:
1337 printICmpInstruction(CE->getPredicate(),left,right);
1339 case Instruction::FCmp:
1340 printFCmpInstruction(CE->getPredicate(),left,right);
1342 case Instruction::Select:
1343 printSelectInstruction(CE->getOperand(0),CE->getOperand(1),CE->getOperand(2));
1345 case Instruction::Add:
1346 case Instruction::FAdd:
1347 printBinaryInstruction("add",left,right);
1349 case Instruction::Sub:
1350 case Instruction::FSub:
1351 printBinaryInstruction("sub",left,right);
1353 case Instruction::Mul:
1354 case Instruction::FMul:
1355 printBinaryInstruction("mul",left,right);
1357 case Instruction::UDiv:
1358 printBinaryInstruction("div.un",left,right);
1360 case Instruction::SDiv:
1361 case Instruction::FDiv:
1362 printBinaryInstruction("div",left,right);
1364 case Instruction::URem:
1365 printBinaryInstruction("rem.un",left,right);
1367 case Instruction::SRem:
1368 case Instruction::FRem:
1369 printBinaryInstruction("rem",left,right);
1371 case Instruction::And:
1372 printBinaryInstruction("and",left,right);
1374 case Instruction::Or:
1375 printBinaryInstruction("or",left,right);
1377 case Instruction::Xor:
1378 printBinaryInstruction("xor",left,right);
1380 case Instruction::Shl:
1381 printBinaryInstruction("shl",left,right);
1383 case Instruction::LShr:
1384 printBinaryInstruction("shr.un",left,right);
1386 case Instruction::AShr:
1387 printBinaryInstruction("shr",left,right);
1390 errs() << "Expression = " << *CE << "\n";
1391 llvm_unreachable("Invalid constant expression");
1396 void MSILWriter::printStaticInitializerList() {
1397 // List of global variables with uninitialized fields.
1398 for (std::map<const GlobalVariable*,std::vector<StaticInitializer> >::iterator
1399 VarI = StaticInitList.begin(), VarE = StaticInitList.end(); VarI!=VarE;
1401 const std::vector<StaticInitializer>& InitList = VarI->second;
1402 if (InitList.empty()) continue;
1403 // For each uninitialized field.
1404 for (std::vector<StaticInitializer>::const_iterator I = InitList.begin(),
1405 E = InitList.end(); I!=E; ++I) {
1406 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(I->constant)) {
1407 // Out << "\n// Init " << getValueName(VarI->first) << ", offset " <<
1408 // utostr(I->offset) << ", type "<< *I->constant->getType() << "\n\n";
1409 // Load variable address
1410 printValueLoad(VarI->first);
1413 printPtrLoad(I->offset);
1414 printSimpleInstruction("add");
1417 printConstantExpr(CE);
1418 // Save result at offset
1419 std::string postfix = getTypePostfix(CE->getType(),true);
1420 if (*postfix.begin()=='u') *postfix.begin() = 'i';
1421 postfix = "stind."+postfix;
1422 printSimpleInstruction(postfix.c_str());
1424 errs() << "Constant = " << *I->constant << '\n';
1425 llvm_unreachable("Invalid static initializer");
1432 void MSILWriter::printFunction(const Function& F) {
1433 bool isSigned = F.paramHasAttr(0, Attribute::SExt);
1434 Out << "\n.method static ";
1435 Out << (F.hasLocalLinkage() ? "private " : "public ");
1436 if (F.isVarArg()) Out << "vararg ";
1437 Out << getTypeName(F.getReturnType(),isSigned) <<
1438 getConvModopt(F.getCallingConv()) << getValueName(&F) << '\n';
1441 unsigned ArgIdx = 1;
1442 for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I!=E;
1444 isSigned = F.paramHasAttr(ArgIdx, Attribute::SExt);
1445 if (I!=F.arg_begin()) Out << ", ";
1446 Out << getTypeName(I->getType(),isSigned) << getValueName(I);
1448 Out << ") cil managed\n";
1451 printLocalVariables(F);
1452 printFunctionBody(F);
1457 void MSILWriter::printDeclarations(const TypeSymbolTable& ST) {
1459 std::set<const Type*> Printed;
1460 for (std::set<const Type*>::const_iterator
1461 UI = UsedTypes->begin(), UE = UsedTypes->end(); UI!=UE; ++UI) {
1462 const Type* Ty = *UI;
1463 if (Ty->isArrayTy() || Ty->isVectorTy() || Ty->isStructTy())
1464 Name = getTypeName(Ty, false, true);
1465 // Type with no need to declare.
1467 // Print not duplicated type
1468 if (Printed.insert(Ty).second) {
1469 Out << ".class value explicit ansi sealed '" << Name << "'";
1470 Out << " { .pack " << 1 << " .size " << TD->getTypeAllocSize(Ty);
1477 unsigned int MSILWriter::getBitWidth(const Type* Ty) {
1478 unsigned int N = Ty->getPrimitiveSizeInBits();
1479 assert(N!=0 && "Invalid type in getBitWidth()");
1488 errs() << "Bits = " << N << '\n';
1489 llvm_unreachable("Unsupported integer width");
1491 return 0; // Not reached
1495 void MSILWriter::printStaticConstant(const Constant* C, uint64_t& Offset) {
1496 uint64_t TySize = 0;
1497 const Type* Ty = C->getType();
1498 // Print zero initialized constant.
1499 if (isa<ConstantAggregateZero>(C) || C->isNullValue()) {
1500 TySize = TD->getTypeAllocSize(C->getType());
1502 Out << "int8 (0) [" << TySize << "]";
1505 // Print constant initializer
1506 switch (Ty->getTypeID()) {
1507 case Type::IntegerTyID: {
1508 TySize = TD->getTypeAllocSize(Ty);
1509 const ConstantInt* Int = cast<ConstantInt>(C);
1510 Out << getPrimitiveTypeName(Ty,true) << "(" << Int->getSExtValue() << ")";
1513 case Type::FloatTyID:
1514 case Type::DoubleTyID: {
1515 TySize = TD->getTypeAllocSize(Ty);
1516 const ConstantFP* FP = cast<ConstantFP>(C);
1517 if (Ty->getTypeID() == Type::FloatTyID)
1519 (uint32_t)FP->getValueAPF().bitcastToAPInt().getZExtValue() << ')';
1522 FP->getValueAPF().bitcastToAPInt().getZExtValue() << ')';
1525 case Type::ArrayTyID:
1526 case Type::VectorTyID:
1527 case Type::StructTyID:
1528 for (unsigned I = 0, E = C->getNumOperands(); I<E; I++) {
1529 if (I!=0) Out << ",\n";
1530 printStaticConstant(cast<Constant>(C->getOperand(I)), Offset);
1533 case Type::PointerTyID:
1534 TySize = TD->getTypeAllocSize(C->getType());
1535 // Initialize with global variable address
1536 if (const GlobalVariable *G = dyn_cast<GlobalVariable>(C)) {
1537 std::string name = getValueName(G);
1538 Out << "&(" << name.insert(name.length()-1,"$data") << ")";
1540 // Dynamic initialization
1541 if (!isa<ConstantPointerNull>(C) && !C->isNullValue())
1542 InitListPtr->push_back(StaticInitializer(C,Offset));
1543 // Null pointer initialization
1544 if (TySize==4) Out << "int32 (0)";
1545 else if (TySize==8) Out << "int64 (0)";
1546 else llvm_unreachable("Invalid pointer size");
1550 errs() << "TypeID = " << Ty->getTypeID() << '\n';
1551 llvm_unreachable("Invalid type in printStaticConstant()");
1558 void MSILWriter::printStaticInitializer(const Constant* C,
1559 const std::string& Name) {
1560 switch (C->getType()->getTypeID()) {
1561 case Type::IntegerTyID:
1562 case Type::FloatTyID:
1563 case Type::DoubleTyID:
1564 Out << getPrimitiveTypeName(C->getType(), false);
1566 case Type::ArrayTyID:
1567 case Type::VectorTyID:
1568 case Type::StructTyID:
1569 case Type::PointerTyID:
1570 Out << getTypeName(C->getType());
1573 errs() << "Type = " << *C << "\n";
1574 llvm_unreachable("Invalid constant type");
1576 // Print initializer
1577 std::string label = Name;
1578 label.insert(label.length()-1,"$data");
1579 Out << Name << " at " << label << '\n';
1580 Out << ".data " << label << " = {\n";
1581 uint64_t offset = 0;
1582 printStaticConstant(C,offset);
1587 void MSILWriter::printVariableDefinition(const GlobalVariable* G) {
1588 const Constant* C = G->getInitializer();
1589 if (C->isNullValue() || isa<ConstantAggregateZero>(C) || isa<UndefValue>(C))
1592 InitListPtr = &StaticInitList[G];
1593 printStaticInitializer(C,getValueName(G));
1597 void MSILWriter::printGlobalVariables() {
1598 if (ModulePtr->global_empty()) return;
1599 Module::global_iterator I,E;
1600 for (I = ModulePtr->global_begin(), E = ModulePtr->global_end(); I!=E; ++I) {
1601 // Variable definition
1602 Out << ".field static " << (I->isDeclaration() ? "public " :
1604 if (I->isDeclaration()) {
1605 Out << getTypeName(I->getType()) << getValueName(&*I) << "\n\n";
1607 printVariableDefinition(&*I);
1612 const char* MSILWriter::getLibraryName(const Function* F) {
1613 return getLibraryForSymbol(F->getName(), true, F->getCallingConv());
1617 const char* MSILWriter::getLibraryName(const GlobalVariable* GV) {
1618 return getLibraryForSymbol(GV->getName(), false, CallingConv::C);
1622 const char* MSILWriter::getLibraryForSymbol(const StringRef &Name,
1624 CallingConv::ID CallingConv) {
1625 // TODO: Read *.def file with function and libraries definitions.
1626 return "MSVCRT.DLL";
1630 void MSILWriter::printExternals() {
1631 Module::const_iterator I,E;
1633 for (I=ModulePtr->begin(),E=ModulePtr->end(); I!=E; ++I) {
1635 if (I->isIntrinsic()) continue;
1636 if (I->isDeclaration()) {
1637 const Function* F = I;
1638 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
1640 getCallSignature(cast<FunctionType>(F->getFunctionType()), NULL, Name);
1641 Out << ".method static hidebysig pinvokeimpl(\""
1642 << getLibraryName(F) << "\")\n\t" << Sig << " preservesig {}\n\n";
1645 // External variables and static initialization.
1647 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1648 " native int LoadLibrary(string) preservesig {}\n"
1649 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1650 " native int GetProcAddress(native int, string) preservesig {}\n";
1652 ".method private static void* $MSIL_Import(string lib,string sym)\n"
1655 "\tcall\tnative int LoadLibrary(string)\n"
1657 "\tcall\tnative int GetProcAddress(native int,string)\n"
1660 "\tldstr\t\"Can no import variable\"\n"
1661 "\tnewobj\tinstance void [mscorlib]System.Exception::.ctor(string)\n"
1666 ".method static private void $MSIL_Init() managed cil\n{\n";
1667 printStaticInitializerList();
1668 // Foreach global variable.
1669 for (Module::global_iterator I = ModulePtr->global_begin(),
1670 E = ModulePtr->global_end(); I!=E; ++I) {
1671 if (!I->isDeclaration() || !I->hasDLLImportLinkage()) continue;
1672 // Use "LoadLibrary"/"GetProcAddress" to recive variable address.
1673 std::string Tmp = getTypeName(I->getType())+getValueName(&*I);
1674 printSimpleInstruction("ldsflda",Tmp.c_str());
1675 Out << "\tldstr\t\"" << getLibraryName(&*I) << "\"\n";
1676 Out << "\tldstr\t\"" << I->getName() << "\"\n";
1677 printSimpleInstruction("call","void* $MSIL_Import(string,string)");
1678 printIndirectSave(I->getType());
1680 printSimpleInstruction("ret");
1685 //===----------------------------------------------------------------------===//
1686 // External Interface declaration
1687 //===----------------------------------------------------------------------===//
1689 bool MSILTarget::addPassesToEmitWholeFile(PassManager &PM,
1690 formatted_raw_ostream &o,
1691 CodeGenFileType FileType,
1692 CodeGenOpt::Level OptLevel,
1695 if (FileType != TargetMachine::CGFT_AssemblyFile) return true;
1696 MSILWriter* Writer = new MSILWriter(o);
1697 PM.add(createGCLoweringPass());
1698 // FIXME: Handle switch through native IL instruction "switch"
1699 PM.add(createLowerSwitchPass());
1700 PM.add(createCFGSimplificationPass());
1701 PM.add(new MSILModule(Writer->UsedTypes,Writer->TD));
1703 PM.add(createGCInfoDeleter());