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/ParameterAttributes.h"
20 #include "llvm/TypeSymbolTable.h"
21 #include "llvm/Analysis/ConstantsScanner.h"
22 #include "llvm/Support/CallSite.h"
23 #include "llvm/Support/InstVisitor.h"
24 #include "llvm/Support/MathExtras.h"
25 #include "llvm/Transforms/Scalar.h"
26 #include "llvm/ADT/StringExtras.h"
27 #include "llvm/CodeGen/Passes.h"
30 // TargetMachine for the MSIL
31 struct VISIBILITY_HIDDEN MSILTarget : public TargetMachine {
32 const TargetData DataLayout; // Calculates type size & alignment
34 MSILTarget(const Module &M, const std::string &FS)
37 virtual bool WantsWholeFile() const { return true; }
38 virtual bool addPassesToEmitWholeFile(PassManager &PM, raw_ostream &Out,
39 CodeGenFileType FileType, bool Fast);
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; }
49 static RegisterTarget<MSILTarget> X("msil", " MSIL backend");
51 bool MSILModule::runOnModule(Module &M) {
53 TD = &getAnalysis<TargetData>();
56 TypeSymbolTable& Table = M.getTypeSymbolTable();
57 std::set<const Type *> Types = getAnalysis<FindUsedTypes>().getTypes();
58 for (TypeSymbolTable::iterator I = Table.begin(), E = Table.end(); I!=E; ) {
59 if (!isa<StructType>(I->second) && !isa<OpaqueType>(I->second))
62 std::set<const Type *>::iterator T = Types.find(I->second);
71 // Find unnamed types.
72 unsigned RenameCounter = 0;
73 for (std::set<const Type *>::const_iterator I = Types.begin(),
74 E = Types.end(); I!=E; ++I)
75 if (const StructType *STy = dyn_cast<StructType>(*I)) {
76 while (ModulePtr->addTypeName("unnamed$"+utostr(RenameCounter), STy))
80 // Pointer for FunctionPass.
81 UsedTypes = &getAnalysis<FindUsedTypes>().getTypes();
85 char MSILModule::ID = 0;
86 char MSILWriter::ID = 0;
88 bool MSILWriter::runOnFunction(Function &F) {
89 if (F.isDeclaration()) return false;
90 LInfo = &getAnalysis<LoopInfo>();
96 bool MSILWriter::doInitialization(Module &M) {
98 Mang = new Mangler(M);
99 Out << ".assembly extern mscorlib {}\n";
100 Out << ".assembly MSIL {}\n\n";
101 Out << "// External\n";
103 Out << "// Declarations\n";
104 printDeclarations(M.getTypeSymbolTable());
105 Out << "// Definitions\n";
106 printGlobalVariables();
107 Out << "// Startup code\n";
108 printModuleStartup();
113 bool MSILWriter::doFinalization(Module &M) {
119 void MSILWriter::printModuleStartup() {
121 ".method static public int32 $MSIL_Startup() {\n"
123 "\t.locals (native int i)\n"
124 "\t.locals (native int argc)\n"
125 "\t.locals (native int ptr)\n"
126 "\t.locals (void* argv)\n"
127 "\t.locals (string[] args)\n"
128 "\tcall\tstring[] [mscorlib]System.Environment::GetCommandLineArgs()\n"
135 printPtrLoad(TD->getPointerSize());
150 "\tcall\tnative int [mscorlib]System.Runtime.InteropServices.Marshal::"
151 "StringToHGlobalAnsi(string)\n"
155 printPtrLoad(TD->getPointerSize());
167 "\tcall void $MSIL_Init()\n";
169 // Call user 'main' function.
170 const Function* F = ModulePtr->getFunction("main");
171 if (!F || F->isDeclaration()) {
172 Out << "\tldc.i4.0\n\tret\n}\n";
176 std::string Args("");
177 Function::const_arg_iterator Arg1,Arg2;
179 switch (F->arg_size()) {
184 Arg1 = F->arg_begin();
185 if (Arg1->getType()->isInteger()) {
186 Out << "\tldloc\targc\n";
187 Args = getTypeName(Arg1->getType());
192 Arg1 = Arg2 = F->arg_begin(); ++Arg2;
193 if (Arg1->getType()->isInteger() &&
194 Arg2->getType()->getTypeID() == Type::PointerTyID) {
195 Out << "\tldloc\targc\n\tldloc\targv\n";
196 Args = getTypeName(Arg1->getType())+","+getTypeName(Arg2->getType());
204 bool RetVoid = (F->getReturnType()->getTypeID() == Type::VoidTyID);
205 if (BadSig || (!F->getReturnType()->isInteger() && !RetVoid)) {
206 Out << "\tldc.i4.0\n";
208 Out << "\tcall\t" << getTypeName(F->getReturnType()) <<
209 getConvModopt(F->getCallingConv()) << "main(" << Args << ")\n";
211 Out << "\tldc.i4.0\n";
213 Out << "\tconv.i4\n";
218 bool MSILWriter::isZeroValue(const Value* V) {
219 if (const Constant *C = dyn_cast<Constant>(V))
220 return C->isNullValue();
225 std::string MSILWriter::getValueName(const Value* V) {
226 // Name into the quotes allow control and space characters.
227 return "'"+Mang->getValueName(V)+"'";
231 std::string MSILWriter::getLabelName(const std::string& Name) {
232 if (Name.find('.')!=std::string::npos) {
233 std::string Tmp(Name);
234 // Replace unaccepable characters in the label name.
235 for (std::string::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I)
236 if (*I=='.') *I = '@';
243 std::string MSILWriter::getLabelName(const Value* V) {
244 return getLabelName(Mang->getValueName(V));
248 std::string MSILWriter::getConvModopt(unsigned CallingConvID) {
249 switch (CallingConvID) {
251 case CallingConv::Cold:
252 case CallingConv::Fast:
253 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) ";
254 case CallingConv::X86_FastCall:
255 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvFastcall) ";
256 case CallingConv::X86_StdCall:
257 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) ";
259 cerr << "CallingConvID = " << CallingConvID << '\n';
260 assert(0 && "Unsupported calling convention");
262 return ""; // Not reached
266 std::string MSILWriter::getArrayTypeName(Type::TypeID TyID, const Type* Ty) {
267 std::string Tmp = "";
268 const Type* ElemTy = Ty;
269 assert(Ty->getTypeID()==TyID && "Invalid type passed");
270 // Walk trought array element types.
272 // Multidimensional array.
273 if (ElemTy->getTypeID()==TyID) {
274 if (const ArrayType* ATy = dyn_cast<ArrayType>(ElemTy))
275 Tmp += utostr(ATy->getNumElements());
276 else if (const VectorType* VTy = dyn_cast<VectorType>(ElemTy))
277 Tmp += utostr(VTy->getNumElements());
278 ElemTy = cast<SequentialType>(ElemTy)->getElementType();
280 // Base element type found.
281 if (ElemTy->getTypeID()!=TyID) break;
284 return getTypeName(ElemTy, false, true)+"["+Tmp+"]";
288 std::string MSILWriter::getPrimitiveTypeName(const Type* Ty, bool isSigned) {
289 unsigned NumBits = 0;
290 switch (Ty->getTypeID()) {
293 case Type::IntegerTyID:
294 NumBits = getBitWidth(Ty);
298 return "unsigned int"+utostr(NumBits)+" ";
299 return "int"+utostr(NumBits)+" ";
300 case Type::FloatTyID:
302 case Type::DoubleTyID:
305 cerr << "Type = " << *Ty << '\n';
306 assert(0 && "Invalid primitive type");
308 return ""; // Not reached
312 std::string MSILWriter::getTypeName(const Type* Ty, bool isSigned,
314 if (Ty->isPrimitiveType() || Ty->isInteger())
315 return getPrimitiveTypeName(Ty,isSigned);
316 // FIXME: "OpaqueType" support
317 switch (Ty->getTypeID()) {
318 case Type::PointerTyID:
320 case Type::StructTyID:
322 return ModulePtr->getTypeName(Ty);
323 return "valuetype '"+ModulePtr->getTypeName(Ty)+"' ";
324 case Type::ArrayTyID:
326 return getArrayTypeName(Ty->getTypeID(),Ty);
327 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
328 case Type::VectorTyID:
330 return getArrayTypeName(Ty->getTypeID(),Ty);
331 return "valuetype '"+getArrayTypeName(Ty->getTypeID(),Ty)+"' ";
333 cerr << "Type = " << *Ty << '\n';
334 assert(0 && "Invalid type in getTypeName()");
336 return ""; // Not reached
340 MSILWriter::ValueType MSILWriter::getValueLocation(const Value* V) {
342 if (isa<Argument>(V))
345 else if (const Function* F = dyn_cast<Function>(V))
346 return F->hasInternalLinkage() ? InternalVT : GlobalVT;
348 else if (const GlobalVariable* G = dyn_cast<GlobalVariable>(V))
349 return G->hasInternalLinkage() ? InternalVT : GlobalVT;
351 else if (isa<Constant>(V))
352 return isa<ConstantExpr>(V) ? ConstExprVT : ConstVT;
358 std::string MSILWriter::getTypePostfix(const Type* Ty, bool Expand,
360 unsigned NumBits = 0;
361 switch (Ty->getTypeID()) {
362 // Integer constant, expanding for stack operations.
363 case Type::IntegerTyID:
364 NumBits = getBitWidth(Ty);
365 // Expand integer value to "int32" or "int64".
366 if (Expand) return (NumBits<=32 ? "i4" : "i8");
367 if (NumBits==1) return "i1";
368 return (isSigned ? "i" : "u")+utostr(NumBits/8);
370 case Type::FloatTyID:
372 case Type::DoubleTyID:
374 case Type::PointerTyID:
375 return "i"+utostr(TD->getABITypeSize(Ty));
377 cerr << "TypeID = " << Ty->getTypeID() << '\n';
378 assert(0 && "Invalid type in TypeToPostfix()");
380 return ""; // Not reached
384 void MSILWriter::printConvToPtr() {
385 switch (ModulePtr->getPointerSize()) {
386 case Module::Pointer32:
387 printSimpleInstruction("conv.u4");
389 case Module::Pointer64:
390 printSimpleInstruction("conv.u8");
393 assert(0 && "Module use not supporting pointer size");
398 void MSILWriter::printPtrLoad(uint64_t N) {
399 switch (ModulePtr->getPointerSize()) {
400 case Module::Pointer32:
401 printSimpleInstruction("ldc.i4",utostr(N).c_str());
402 // FIXME: Need overflow test?
404 cerr << "Value = " << utostr(N) << '\n';
405 assert(0 && "32-bit pointer overflowed");
408 case Module::Pointer64:
409 printSimpleInstruction("ldc.i8",utostr(N).c_str());
412 assert(0 && "Module use not supporting pointer size");
417 void MSILWriter::printValuePtrLoad(const Value* V) {
423 void MSILWriter::printConstLoad(const Constant* C) {
424 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(C)) {
426 Out << "\tldc." << getTypePostfix(C->getType(),true) << '\t';
427 if (CInt->isMinValue(true))
428 Out << CInt->getSExtValue();
430 Out << CInt->getZExtValue();
431 } else if (const ConstantFP* FP = dyn_cast<ConstantFP>(C)) {
435 if (FP->getType()->getTypeID()==Type::FloatTyID) {
436 X = (uint32_t)FP->getValueAPF().convertToAPInt().getZExtValue();
439 X = FP->getValueAPF().convertToAPInt().getZExtValue();
442 Out << "\tldc.r" << Size << "\t( " << utohexstr(X) << ')';
443 } else if (isa<UndefValue>(C)) {
444 // Undefined constant value = NULL.
447 cerr << "Constant = " << *C << '\n';
448 assert(0 && "Invalid constant value");
454 void MSILWriter::printValueLoad(const Value* V) {
455 MSILWriter::ValueType Location = getValueLocation(V);
457 // Global variable or function address.
460 if (const Function* F = dyn_cast<Function>(V)) {
461 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
462 printSimpleInstruction("ldftn",
463 getCallSignature(F->getFunctionType(),NULL,Name).c_str());
466 const Type* ElemTy = cast<PointerType>(V->getType())->getElementType();
467 if (Location==GlobalVT && cast<GlobalVariable>(V)->hasDLLImportLinkage()) {
468 Tmp = "void* "+getValueName(V);
469 printSimpleInstruction("ldsfld",Tmp.c_str());
471 Tmp = getTypeName(ElemTy)+getValueName(V);
472 printSimpleInstruction("ldsflda",Tmp.c_str());
476 // Function argument.
478 printSimpleInstruction("ldarg",getValueName(V).c_str());
480 // Local function variable.
482 printSimpleInstruction("ldloc",getValueName(V).c_str());
486 if (isa<ConstantPointerNull>(V))
489 printConstLoad(cast<Constant>(V));
491 // Constant expression.
493 printConstantExpr(cast<ConstantExpr>(V));
496 cerr << "Value = " << *V << '\n';
497 assert(0 && "Invalid value location");
502 void MSILWriter::printValueSave(const Value* V) {
503 switch (getValueLocation(V)) {
505 printSimpleInstruction("starg",getValueName(V).c_str());
508 printSimpleInstruction("stloc",getValueName(V).c_str());
511 cerr << "Value = " << *V << '\n';
512 assert(0 && "Invalid value location");
517 void MSILWriter::printBinaryInstruction(const char* Name, const Value* Left,
518 const Value* Right) {
519 printValueLoad(Left);
520 printValueLoad(Right);
521 Out << '\t' << Name << '\n';
525 void MSILWriter::printSimpleInstruction(const char* Inst, const char* Operand) {
527 Out << '\t' << Inst << '\t' << Operand << '\n';
529 Out << '\t' << Inst << '\n';
533 void MSILWriter::printPHICopy(const BasicBlock* Src, const BasicBlock* Dst) {
534 for (BasicBlock::const_iterator I = Dst->begin(), E = Dst->end();
535 isa<PHINode>(I); ++I) {
536 const PHINode* Phi = cast<PHINode>(I);
537 const Value* Val = Phi->getIncomingValueForBlock(Src);
538 if (isa<UndefValue>(Val)) continue;
545 void MSILWriter::printBranchToBlock(const BasicBlock* CurrBB,
546 const BasicBlock* TrueBB,
547 const BasicBlock* FalseBB) {
548 if (TrueBB==FalseBB) {
549 // "TrueBB" and "FalseBB" destination equals
550 printPHICopy(CurrBB,TrueBB);
551 printSimpleInstruction("pop");
552 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
553 } else if (FalseBB==NULL) {
554 // If "FalseBB" not used the jump have condition
555 printPHICopy(CurrBB,TrueBB);
556 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
557 } else if (TrueBB==NULL) {
558 // If "TrueBB" not used the jump is unconditional
559 printPHICopy(CurrBB,FalseBB);
560 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
562 // Copy PHI instructions for each block
563 std::string TmpLabel;
564 // Print PHI instructions for "TrueBB"
565 if (isa<PHINode>(TrueBB->begin())) {
566 TmpLabel = getLabelName(TrueBB)+"$phi_"+utostr(getUniqID());
567 printSimpleInstruction("brtrue",TmpLabel.c_str());
569 printSimpleInstruction("brtrue",getLabelName(TrueBB).c_str());
571 // Print PHI instructions for "FalseBB"
572 if (isa<PHINode>(FalseBB->begin())) {
573 printPHICopy(CurrBB,FalseBB);
574 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
576 printSimpleInstruction("br",getLabelName(FalseBB).c_str());
578 if (isa<PHINode>(TrueBB->begin())) {
579 // Handle "TrueBB" PHI Copy
580 Out << TmpLabel << ":\n";
581 printPHICopy(CurrBB,TrueBB);
582 printSimpleInstruction("br",getLabelName(TrueBB).c_str());
588 void MSILWriter::printBranchInstruction(const BranchInst* Inst) {
589 if (Inst->isUnconditional()) {
590 printBranchToBlock(Inst->getParent(),NULL,Inst->getSuccessor(0));
592 printValueLoad(Inst->getCondition());
593 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(0),
594 Inst->getSuccessor(1));
599 void MSILWriter::printSelectInstruction(const Value* Cond, const Value* VTrue,
600 const Value* VFalse) {
601 std::string TmpLabel = std::string("select$true_")+utostr(getUniqID());
602 printValueLoad(VTrue);
603 printValueLoad(Cond);
604 printSimpleInstruction("brtrue",TmpLabel.c_str());
605 printSimpleInstruction("pop");
606 printValueLoad(VFalse);
607 Out << TmpLabel << ":\n";
611 void MSILWriter::printIndirectLoad(const Value* V) {
612 const Type* Ty = V->getType();
614 if (const PointerType* P = dyn_cast<PointerType>(Ty))
615 Ty = P->getElementType();
616 std::string Tmp = "ldind."+getTypePostfix(Ty, false);
617 printSimpleInstruction(Tmp.c_str());
621 void MSILWriter::printIndirectSave(const Value* Ptr, const Value* Val) {
624 printIndirectSave(Val->getType());
628 void MSILWriter::printIndirectSave(const Type* Ty) {
629 // Instruction need signed postfix for any type.
630 std::string postfix = getTypePostfix(Ty, false);
631 if (*postfix.begin()=='u') *postfix.begin() = 'i';
632 postfix = "stind."+postfix;
633 printSimpleInstruction(postfix.c_str());
637 void MSILWriter::printCastInstruction(unsigned int Op, const Value* V,
643 case Instruction::SExt:
644 case Instruction::SIToFP:
645 case Instruction::FPToSI:
646 Tmp = "conv."+getTypePostfix(Ty,false,true);
647 printSimpleInstruction(Tmp.c_str());
650 case Instruction::FPTrunc:
651 case Instruction::FPExt:
652 case Instruction::UIToFP:
653 case Instruction::Trunc:
654 case Instruction::ZExt:
655 case Instruction::FPToUI:
656 case Instruction::PtrToInt:
657 case Instruction::IntToPtr:
658 Tmp = "conv."+getTypePostfix(Ty,false);
659 printSimpleInstruction(Tmp.c_str());
662 case Instruction::BitCast:
663 // FIXME: meaning that ld*/st* instruction do not change data format.
666 cerr << "Opcode = " << Op << '\n';
667 assert(0 && "Invalid conversion instruction");
672 void MSILWriter::printGepInstruction(const Value* V, gep_type_iterator I,
673 gep_type_iterator E) {
676 printValuePtrLoad(V);
677 // Calculate element offset.
680 const Value* IndexValue = I.getOperand();
681 if (const StructType* StrucTy = dyn_cast<StructType>(*I)) {
682 uint64_t FieldIndex = cast<ConstantInt>(IndexValue)->getZExtValue();
683 // Offset is the sum of all previous structure fields.
684 for (uint64_t F = 0; F<FieldIndex; ++F)
685 Size += TD->getABITypeSize(StrucTy->getContainedType((unsigned)F));
687 printSimpleInstruction("add");
689 } else if (const SequentialType* SeqTy = dyn_cast<SequentialType>(*I)) {
690 Size = TD->getABITypeSize(SeqTy->getElementType());
692 Size = TD->getABITypeSize(*I);
694 // Add offset of current element to stack top.
695 if (!isZeroValue(IndexValue)) {
696 // Constant optimization.
697 if (const ConstantInt* C = dyn_cast<ConstantInt>(IndexValue)) {
698 if (C->getValue().isNegative()) {
699 printPtrLoad(C->getValue().abs().getZExtValue()*Size);
700 printSimpleInstruction("sub");
703 printPtrLoad(C->getZExtValue()*Size);
706 printValuePtrLoad(IndexValue);
707 printSimpleInstruction("mul");
709 printSimpleInstruction("add");
715 std::string MSILWriter::getCallSignature(const FunctionType* Ty,
716 const Instruction* Inst,
719 if (Ty->isVarArg()) Tmp += "vararg ";
720 // Name and return type.
721 Tmp += getTypeName(Ty->getReturnType())+Name+"(";
722 // Function argument type list.
723 unsigned NumParams = Ty->getNumParams();
724 for (unsigned I = 0; I!=NumParams; ++I) {
725 if (I!=0) Tmp += ",";
726 Tmp += getTypeName(Ty->getParamType(I));
728 // CLR needs to know the exact amount of parameters received by vararg
729 // function, because caller cleans the stack.
730 if (Ty->isVarArg() && Inst) {
731 // Origin to function arguments in "CallInst" or "InvokeInst".
732 unsigned Org = isa<InvokeInst>(Inst) ? 3 : 1;
733 // Print variable argument types.
734 unsigned NumOperands = Inst->getNumOperands()-Org;
735 if (NumParams<NumOperands) {
736 if (NumParams!=0) Tmp += ", ";
738 for (unsigned J = NumParams; J!=NumOperands; ++J) {
739 if (J!=NumParams) Tmp += ", ";
740 Tmp += getTypeName(Inst->getOperand(J+Org)->getType());
748 void MSILWriter::printFunctionCall(const Value* FnVal,
749 const Instruction* Inst) {
750 // Get function calling convention.
751 std::string Name = "";
752 if (const CallInst* Call = dyn_cast<CallInst>(Inst))
753 Name = getConvModopt(Call->getCallingConv());
754 else if (const InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst))
755 Name = getConvModopt(Invoke->getCallingConv());
757 cerr << "Instruction = " << Inst->getName() << '\n';
758 assert(0 && "Need \"Invoke\" or \"Call\" instruction only");
760 if (const Function* F = dyn_cast<Function>(FnVal)) {
762 Name += getValueName(F);
763 printSimpleInstruction("call",
764 getCallSignature(F->getFunctionType(),Inst,Name).c_str());
766 // Indirect function call.
767 const PointerType* PTy = cast<PointerType>(FnVal->getType());
768 const FunctionType* FTy = cast<FunctionType>(PTy->getElementType());
769 // Load function address.
770 printValueLoad(FnVal);
771 printSimpleInstruction("calli",getCallSignature(FTy,Inst,Name).c_str());
776 void MSILWriter::printIntrinsicCall(const IntrinsicInst* Inst) {
778 switch (Inst->getIntrinsicID()) {
779 case Intrinsic::vastart:
780 Name = getValueName(Inst->getOperand(1));
781 Name.insert(Name.length()-1,"$valist");
782 // Obtain the argument handle.
783 printSimpleInstruction("ldloca",Name.c_str());
784 printSimpleInstruction("arglist");
785 printSimpleInstruction("call",
786 "instance void [mscorlib]System.ArgIterator::.ctor"
787 "(valuetype [mscorlib]System.RuntimeArgumentHandle)");
788 // Save as pointer type "void*"
789 printValueLoad(Inst->getOperand(1));
790 printSimpleInstruction("ldloca",Name.c_str());
791 printIndirectSave(PointerType::getUnqual(IntegerType::get(8)));
793 case Intrinsic::vaend:
794 // Close argument list handle.
795 printIndirectLoad(Inst->getOperand(1));
796 printSimpleInstruction("call","instance void [mscorlib]System.ArgIterator::End()");
798 case Intrinsic::vacopy:
799 // Copy "ArgIterator" valuetype.
800 printIndirectLoad(Inst->getOperand(1));
801 printIndirectLoad(Inst->getOperand(2));
802 printSimpleInstruction("cpobj","[mscorlib]System.ArgIterator");
805 cerr << "Intrinsic ID = " << Inst->getIntrinsicID() << '\n';
806 assert(0 && "Invalid intrinsic function");
811 void MSILWriter::printCallInstruction(const Instruction* Inst) {
812 if (isa<IntrinsicInst>(Inst)) {
813 // Handle intrinsic function.
814 printIntrinsicCall(cast<IntrinsicInst>(Inst));
816 // Load arguments to stack and call function.
817 for (int I = 1, E = Inst->getNumOperands(); I!=E; ++I)
818 printValueLoad(Inst->getOperand(I));
819 printFunctionCall(Inst->getOperand(0),Inst);
824 void MSILWriter::printICmpInstruction(unsigned Predicate, const Value* Left,
825 const Value* Right) {
827 case ICmpInst::ICMP_EQ:
828 printBinaryInstruction("ceq",Left,Right);
830 case ICmpInst::ICMP_NE:
831 // Emulate = not neg (Op1 eq Op2)
832 printBinaryInstruction("ceq",Left,Right);
833 printSimpleInstruction("neg");
834 printSimpleInstruction("not");
836 case ICmpInst::ICMP_ULE:
837 case ICmpInst::ICMP_SLE:
838 // Emulate = (Op1 eq Op2) or (Op1 lt Op2)
839 printBinaryInstruction("ceq",Left,Right);
840 if (Predicate==ICmpInst::ICMP_ULE)
841 printBinaryInstruction("clt.un",Left,Right);
843 printBinaryInstruction("clt",Left,Right);
844 printSimpleInstruction("or");
846 case ICmpInst::ICMP_UGE:
847 case ICmpInst::ICMP_SGE:
848 // Emulate = (Op1 eq Op2) or (Op1 gt Op2)
849 printBinaryInstruction("ceq",Left,Right);
850 if (Predicate==ICmpInst::ICMP_UGE)
851 printBinaryInstruction("cgt.un",Left,Right);
853 printBinaryInstruction("cgt",Left,Right);
854 printSimpleInstruction("or");
856 case ICmpInst::ICMP_ULT:
857 printBinaryInstruction("clt.un",Left,Right);
859 case ICmpInst::ICMP_SLT:
860 printBinaryInstruction("clt",Left,Right);
862 case ICmpInst::ICMP_UGT:
863 printBinaryInstruction("cgt.un",Left,Right);
864 case ICmpInst::ICMP_SGT:
865 printBinaryInstruction("cgt",Left,Right);
868 cerr << "Predicate = " << Predicate << '\n';
869 assert(0 && "Invalid icmp predicate");
874 void MSILWriter::printFCmpInstruction(unsigned Predicate, const Value* Left,
875 const Value* Right) {
876 // FIXME: Correct comparison
877 std::string NanFunc = "bool [mscorlib]System.Double::IsNaN(float64)";
879 case FCmpInst::FCMP_UGT:
880 // X > Y || llvm_fcmp_uno(X, Y)
881 printBinaryInstruction("cgt",Left,Right);
882 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
883 printSimpleInstruction("or");
885 case FCmpInst::FCMP_OGT:
887 printBinaryInstruction("cgt",Left,Right);
889 case FCmpInst::FCMP_UGE:
890 // X >= Y || llvm_fcmp_uno(X, Y)
891 printBinaryInstruction("ceq",Left,Right);
892 printBinaryInstruction("cgt",Left,Right);
893 printSimpleInstruction("or");
894 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
895 printSimpleInstruction("or");
897 case FCmpInst::FCMP_OGE:
899 printBinaryInstruction("ceq",Left,Right);
900 printBinaryInstruction("cgt",Left,Right);
901 printSimpleInstruction("or");
903 case FCmpInst::FCMP_ULT:
904 // X < Y || llvm_fcmp_uno(X, Y)
905 printBinaryInstruction("clt",Left,Right);
906 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
907 printSimpleInstruction("or");
909 case FCmpInst::FCMP_OLT:
911 printBinaryInstruction("clt",Left,Right);
913 case FCmpInst::FCMP_ULE:
914 // X <= Y || llvm_fcmp_uno(X, Y)
915 printBinaryInstruction("ceq",Left,Right);
916 printBinaryInstruction("clt",Left,Right);
917 printSimpleInstruction("or");
918 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
919 printSimpleInstruction("or");
921 case FCmpInst::FCMP_OLE:
923 printBinaryInstruction("ceq",Left,Right);
924 printBinaryInstruction("clt",Left,Right);
925 printSimpleInstruction("or");
927 case FCmpInst::FCMP_UEQ:
928 // X == Y || llvm_fcmp_uno(X, Y)
929 printBinaryInstruction("ceq",Left,Right);
930 printFCmpInstruction(FCmpInst::FCMP_UNO,Left,Right);
931 printSimpleInstruction("or");
933 case FCmpInst::FCMP_OEQ:
935 printBinaryInstruction("ceq",Left,Right);
937 case FCmpInst::FCMP_UNE:
939 printBinaryInstruction("ceq",Left,Right);
940 printSimpleInstruction("neg");
941 printSimpleInstruction("not");
943 case FCmpInst::FCMP_ONE:
944 // X != Y && llvm_fcmp_ord(X, Y)
945 printBinaryInstruction("ceq",Left,Right);
946 printSimpleInstruction("not");
948 case FCmpInst::FCMP_ORD:
949 // return X == X && Y == Y
950 printBinaryInstruction("ceq",Left,Left);
951 printBinaryInstruction("ceq",Right,Right);
952 printSimpleInstruction("or");
954 case FCmpInst::FCMP_UNO:
956 printBinaryInstruction("ceq",Left,Left);
957 printSimpleInstruction("not");
958 printBinaryInstruction("ceq",Right,Right);
959 printSimpleInstruction("not");
960 printSimpleInstruction("or");
963 assert(0 && "Illegal FCmp predicate");
968 void MSILWriter::printInvokeInstruction(const InvokeInst* Inst) {
969 std::string Label = "leave$normal_"+utostr(getUniqID());
972 for (int I = 3, E = Inst->getNumOperands(); I!=E; ++I)
973 printValueLoad(Inst->getOperand(I));
974 // Print call instruction
975 printFunctionCall(Inst->getOperand(0),Inst);
976 // Save function result and leave "try" block
977 printValueSave(Inst);
978 printSimpleInstruction("leave",Label.c_str());
980 Out << "catch [mscorlib]System.Exception {\n";
981 // Redirect to unwind block
982 printSimpleInstruction("pop");
983 printBranchToBlock(Inst->getParent(),NULL,Inst->getUnwindDest());
984 Out << "}\n" << Label << ":\n";
985 // Redirect to continue block
986 printBranchToBlock(Inst->getParent(),NULL,Inst->getNormalDest());
990 void MSILWriter::printSwitchInstruction(const SwitchInst* Inst) {
991 // FIXME: Emulate with IL "switch" instruction
992 // Emulate = if () else if () else if () else ...
993 for (unsigned int I = 1, E = Inst->getNumCases(); I!=E; ++I) {
994 printValueLoad(Inst->getCondition());
995 printValueLoad(Inst->getCaseValue(I));
996 printSimpleInstruction("ceq");
997 // Condition jump to successor block
998 printBranchToBlock(Inst->getParent(),Inst->getSuccessor(I),NULL);
1000 // Jump to default block
1001 printBranchToBlock(Inst->getParent(),NULL,Inst->getDefaultDest());
1005 void MSILWriter::printVAArgInstruction(const VAArgInst* Inst) {
1006 printIndirectLoad(Inst->getOperand(0));
1007 printSimpleInstruction("call",
1008 "instance typedref [mscorlib]System.ArgIterator::GetNextArg()");
1009 printSimpleInstruction("refanyval","void*");
1011 "ldind."+getTypePostfix(PointerType::getUnqual(IntegerType::get(8)),false);
1012 printSimpleInstruction(Name.c_str());
1016 void MSILWriter::printAllocaInstruction(const AllocaInst* Inst) {
1017 uint64_t Size = TD->getABITypeSize(Inst->getAllocatedType());
1018 // Constant optimization.
1019 if (const ConstantInt* CInt = dyn_cast<ConstantInt>(Inst->getOperand(0))) {
1020 printPtrLoad(CInt->getZExtValue()*Size);
1023 printValueLoad(Inst->getOperand(0));
1024 printSimpleInstruction("mul");
1026 printSimpleInstruction("localloc");
1030 void MSILWriter::printInstruction(const Instruction* Inst) {
1031 const Value *Left = 0, *Right = 0;
1032 if (Inst->getNumOperands()>=1) Left = Inst->getOperand(0);
1033 if (Inst->getNumOperands()>=2) Right = Inst->getOperand(1);
1034 // Print instruction
1035 // FIXME: "ShuffleVector","ExtractElement","InsertElement" support.
1036 switch (Inst->getOpcode()) {
1038 case Instruction::Ret:
1039 if (Inst->getNumOperands()) {
1040 printValueLoad(Left);
1041 printSimpleInstruction("ret");
1043 printSimpleInstruction("ret");
1045 case Instruction::Br:
1046 printBranchInstruction(cast<BranchInst>(Inst));
1049 case Instruction::Add:
1050 printBinaryInstruction("add",Left,Right);
1052 case Instruction::Sub:
1053 printBinaryInstruction("sub",Left,Right);
1055 case Instruction::Mul:
1056 printBinaryInstruction("mul",Left,Right);
1058 case Instruction::UDiv:
1059 printBinaryInstruction("div.un",Left,Right);
1061 case Instruction::SDiv:
1062 case Instruction::FDiv:
1063 printBinaryInstruction("div",Left,Right);
1065 case Instruction::URem:
1066 printBinaryInstruction("rem.un",Left,Right);
1068 case Instruction::SRem:
1069 case Instruction::FRem:
1070 printBinaryInstruction("rem",Left,Right);
1073 case Instruction::ICmp:
1074 printICmpInstruction(cast<ICmpInst>(Inst)->getPredicate(),Left,Right);
1076 case Instruction::FCmp:
1077 printFCmpInstruction(cast<FCmpInst>(Inst)->getPredicate(),Left,Right);
1080 case Instruction::And:
1081 printBinaryInstruction("and",Left,Right);
1083 case Instruction::Or:
1084 printBinaryInstruction("or",Left,Right);
1086 case Instruction::Xor:
1087 printBinaryInstruction("xor",Left,Right);
1089 case Instruction::Shl:
1090 printValueLoad(Left);
1091 printValueLoad(Right);
1092 printSimpleInstruction("conv.i4");
1093 printSimpleInstruction("shl");
1095 case Instruction::LShr:
1096 printValueLoad(Left);
1097 printValueLoad(Right);
1098 printSimpleInstruction("conv.i4");
1099 printSimpleInstruction("shr.un");
1101 case Instruction::AShr:
1102 printValueLoad(Left);
1103 printValueLoad(Right);
1104 printSimpleInstruction("conv.i4");
1105 printSimpleInstruction("shr");
1107 case Instruction::Select:
1108 printSelectInstruction(Inst->getOperand(0),Inst->getOperand(1),Inst->getOperand(2));
1110 case Instruction::Load:
1111 printIndirectLoad(Inst->getOperand(0));
1113 case Instruction::Store:
1114 printIndirectSave(Inst->getOperand(1), Inst->getOperand(0));
1116 case Instruction::Trunc:
1117 case Instruction::ZExt:
1118 case Instruction::SExt:
1119 case Instruction::FPTrunc:
1120 case Instruction::FPExt:
1121 case Instruction::UIToFP:
1122 case Instruction::SIToFP:
1123 case Instruction::FPToUI:
1124 case Instruction::FPToSI:
1125 case Instruction::PtrToInt:
1126 case Instruction::IntToPtr:
1127 case Instruction::BitCast:
1128 printCastInstruction(Inst->getOpcode(),Left,
1129 cast<CastInst>(Inst)->getDestTy());
1131 case Instruction::GetElementPtr:
1132 printGepInstruction(Inst->getOperand(0),gep_type_begin(Inst),
1133 gep_type_end(Inst));
1135 case Instruction::Call:
1136 printCallInstruction(cast<CallInst>(Inst));
1138 case Instruction::Invoke:
1139 printInvokeInstruction(cast<InvokeInst>(Inst));
1141 case Instruction::Unwind:
1142 printSimpleInstruction("newobj",
1143 "instance void [mscorlib]System.Exception::.ctor()");
1144 printSimpleInstruction("throw");
1146 case Instruction::Switch:
1147 printSwitchInstruction(cast<SwitchInst>(Inst));
1149 case Instruction::Alloca:
1150 printAllocaInstruction(cast<AllocaInst>(Inst));
1152 case Instruction::Malloc:
1153 assert(0 && "LowerAllocationsPass used");
1155 case Instruction::Free:
1156 assert(0 && "LowerAllocationsPass used");
1158 case Instruction::Unreachable:
1159 printSimpleInstruction("ldstr", "\"Unreachable instruction\"");
1160 printSimpleInstruction("newobj",
1161 "instance void [mscorlib]System.Exception::.ctor(string)");
1162 printSimpleInstruction("throw");
1164 case Instruction::VAArg:
1165 printVAArgInstruction(cast<VAArgInst>(Inst));
1168 cerr << "Instruction = " << Inst->getName() << '\n';
1169 assert(0 && "Unsupported instruction");
1174 void MSILWriter::printLoop(const Loop* L) {
1175 Out << getLabelName(L->getHeader()->getName()) << ":\n";
1176 const std::vector<BasicBlock*>& blocks = L->getBlocks();
1177 for (unsigned I = 0, E = blocks.size(); I!=E; I++) {
1178 BasicBlock* BB = blocks[I];
1179 Loop* BBLoop = LInfo->getLoopFor(BB);
1181 printBasicBlock(BB);
1182 else if (BB==BBLoop->getHeader() && BBLoop->getParentLoop()==L)
1185 printSimpleInstruction("br",getLabelName(L->getHeader()->getName()).c_str());
1189 void MSILWriter::printBasicBlock(const BasicBlock* BB) {
1190 Out << getLabelName(BB) << ":\n";
1191 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) {
1192 const Instruction* Inst = I;
1193 // Comment llvm original instruction
1194 // Out << "\n//" << *Inst << "\n";
1195 // Do not handle PHI instruction in current block
1196 if (Inst->getOpcode()==Instruction::PHI) continue;
1197 // Print instruction
1198 printInstruction(Inst);
1200 if (Inst->getType()!=Type::VoidTy) {
1201 // Do not save value after invoke, it done in "try" block
1202 if (Inst->getOpcode()==Instruction::Invoke) continue;
1203 printValueSave(Inst);
1209 void MSILWriter::printLocalVariables(const Function& F) {
1211 const Type* Ty = NULL;
1212 std::set<const Value*> Printed;
1213 const Value* VaList = NULL;
1214 unsigned StackDepth = 8;
1215 // Find local variables
1216 for (const_inst_iterator I = inst_begin(&F), E = inst_end(&F); I!=E; ++I) {
1217 if (I->getOpcode()==Instruction::Call ||
1218 I->getOpcode()==Instruction::Invoke) {
1219 // Test stack depth.
1220 if (StackDepth<I->getNumOperands())
1221 StackDepth = I->getNumOperands();
1223 const AllocaInst* AI = dyn_cast<AllocaInst>(&*I);
1224 if (AI && !isa<GlobalVariable>(AI)) {
1225 // Local variable allocation.
1226 Ty = PointerType::getUnqual(AI->getAllocatedType());
1227 Name = getValueName(AI);
1228 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
1229 } else if (I->getType()!=Type::VoidTy) {
1230 // Operation result.
1232 Name = getValueName(&*I);
1233 Out << "\t.locals (" << getTypeName(Ty) << Name << ")\n";
1235 // Test on 'va_list' variable
1236 bool isVaList = false;
1237 if (const VAArgInst* VaInst = dyn_cast<VAArgInst>(&*I)) {
1238 // "va_list" as "va_arg" instruction operand.
1240 VaList = VaInst->getOperand(0);
1241 } else if (const IntrinsicInst* Inst = dyn_cast<IntrinsicInst>(&*I)) {
1242 // "va_list" as intrinsic function operand.
1243 switch (Inst->getIntrinsicID()) {
1244 case Intrinsic::vastart:
1245 case Intrinsic::vaend:
1246 case Intrinsic::vacopy:
1248 VaList = Inst->getOperand(1);
1254 // Print "va_list" variable.
1255 if (isVaList && Printed.insert(VaList).second) {
1256 Name = getValueName(VaList);
1257 Name.insert(Name.length()-1,"$valist");
1258 Out << "\t.locals (valuetype [mscorlib]System.ArgIterator "
1262 printSimpleInstruction(".maxstack",utostr(StackDepth*2).c_str());
1266 void MSILWriter::printFunctionBody(const Function& F) {
1268 for (Function::const_iterator I = F.begin(), E = F.end(); I!=E; ++I) {
1269 if (Loop *L = LInfo->getLoopFor(I)) {
1270 if (L->getHeader()==I && L->getParentLoop()==0)
1279 void MSILWriter::printConstantExpr(const ConstantExpr* CE) {
1280 const Value *left = 0, *right = 0;
1281 if (CE->getNumOperands()>=1) left = CE->getOperand(0);
1282 if (CE->getNumOperands()>=2) right = CE->getOperand(1);
1283 // Print instruction
1284 switch (CE->getOpcode()) {
1285 case Instruction::Trunc:
1286 case Instruction::ZExt:
1287 case Instruction::SExt:
1288 case Instruction::FPTrunc:
1289 case Instruction::FPExt:
1290 case Instruction::UIToFP:
1291 case Instruction::SIToFP:
1292 case Instruction::FPToUI:
1293 case Instruction::FPToSI:
1294 case Instruction::PtrToInt:
1295 case Instruction::IntToPtr:
1296 case Instruction::BitCast:
1297 printCastInstruction(CE->getOpcode(),left,CE->getType());
1299 case Instruction::GetElementPtr:
1300 printGepInstruction(CE->getOperand(0),gep_type_begin(CE),gep_type_end(CE));
1302 case Instruction::ICmp:
1303 printICmpInstruction(CE->getPredicate(),left,right);
1305 case Instruction::FCmp:
1306 printFCmpInstruction(CE->getPredicate(),left,right);
1308 case Instruction::Select:
1309 printSelectInstruction(CE->getOperand(0),CE->getOperand(1),CE->getOperand(2));
1311 case Instruction::Add:
1312 printBinaryInstruction("add",left,right);
1314 case Instruction::Sub:
1315 printBinaryInstruction("sub",left,right);
1317 case Instruction::Mul:
1318 printBinaryInstruction("mul",left,right);
1320 case Instruction::UDiv:
1321 printBinaryInstruction("div.un",left,right);
1323 case Instruction::SDiv:
1324 case Instruction::FDiv:
1325 printBinaryInstruction("div",left,right);
1327 case Instruction::URem:
1328 printBinaryInstruction("rem.un",left,right);
1330 case Instruction::SRem:
1331 case Instruction::FRem:
1332 printBinaryInstruction("rem",left,right);
1334 case Instruction::And:
1335 printBinaryInstruction("and",left,right);
1337 case Instruction::Or:
1338 printBinaryInstruction("or",left,right);
1340 case Instruction::Xor:
1341 printBinaryInstruction("xor",left,right);
1343 case Instruction::Shl:
1344 printBinaryInstruction("shl",left,right);
1346 case Instruction::LShr:
1347 printBinaryInstruction("shr.un",left,right);
1349 case Instruction::AShr:
1350 printBinaryInstruction("shr",left,right);
1353 cerr << "Expression = " << *CE << "\n";
1354 assert(0 && "Invalid constant expression");
1359 void MSILWriter::printStaticInitializerList() {
1360 // List of global variables with uninitialized fields.
1361 for (std::map<const GlobalVariable*,std::vector<StaticInitializer> >::iterator
1362 VarI = StaticInitList.begin(), VarE = StaticInitList.end(); VarI!=VarE;
1364 const std::vector<StaticInitializer>& InitList = VarI->second;
1365 if (InitList.empty()) continue;
1366 // For each uninitialized field.
1367 for (std::vector<StaticInitializer>::const_iterator I = InitList.begin(),
1368 E = InitList.end(); I!=E; ++I) {
1369 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(I->constant)) {
1370 // Out << "\n// Init " << getValueName(VarI->first) << ", offset " <<
1371 // utostr(I->offset) << ", type "<< *I->constant->getType() << "\n\n";
1372 // Load variable address
1373 printValueLoad(VarI->first);
1376 printPtrLoad(I->offset);
1377 printSimpleInstruction("add");
1380 printConstantExpr(CE);
1381 // Save result at offset
1382 std::string postfix = getTypePostfix(CE->getType(),true);
1383 if (*postfix.begin()=='u') *postfix.begin() = 'i';
1384 postfix = "stind."+postfix;
1385 printSimpleInstruction(postfix.c_str());
1387 cerr << "Constant = " << *I->constant << '\n';
1388 assert(0 && "Invalid static initializer");
1395 void MSILWriter::printFunction(const Function& F) {
1396 bool isSigned = F.paramHasAttr(0, ParamAttr::SExt);
1397 Out << "\n.method static ";
1398 Out << (F.hasInternalLinkage() ? "private " : "public ");
1399 if (F.isVarArg()) Out << "vararg ";
1400 Out << getTypeName(F.getReturnType(),isSigned) <<
1401 getConvModopt(F.getCallingConv()) << getValueName(&F) << '\n';
1404 unsigned ArgIdx = 1;
1405 for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I!=E;
1407 isSigned = F.paramHasAttr(ArgIdx, ParamAttr::SExt);
1408 if (I!=F.arg_begin()) Out << ", ";
1409 Out << getTypeName(I->getType(),isSigned) << getValueName(I);
1411 Out << ") cil managed\n";
1414 printLocalVariables(F);
1415 printFunctionBody(F);
1420 void MSILWriter::printDeclarations(const TypeSymbolTable& ST) {
1422 std::set<const Type*> Printed;
1423 for (std::set<const Type*>::const_iterator
1424 UI = UsedTypes->begin(), UE = UsedTypes->end(); UI!=UE; ++UI) {
1425 const Type* Ty = *UI;
1426 if (isa<ArrayType>(Ty) || isa<VectorType>(Ty) || isa<StructType>(Ty))
1427 Name = getTypeName(Ty, false, true);
1428 // Type with no need to declare.
1430 // Print not duplicated type
1431 if (Printed.insert(Ty).second) {
1432 Out << ".class value explicit ansi sealed '" << Name << "'";
1433 Out << " { .pack " << 1 << " .size " << TD->getABITypeSize(Ty)<< " }\n\n";
1439 unsigned int MSILWriter::getBitWidth(const Type* Ty) {
1440 unsigned int N = Ty->getPrimitiveSizeInBits();
1441 assert(N!=0 && "Invalid type in getBitWidth()");
1450 cerr << "Bits = " << N << '\n';
1451 assert(0 && "Unsupported integer width");
1453 return 0; // Not reached
1457 void MSILWriter::printStaticConstant(const Constant* C, uint64_t& Offset) {
1458 uint64_t TySize = 0;
1459 const Type* Ty = C->getType();
1460 // Print zero initialized constant.
1461 if (isa<ConstantAggregateZero>(C) || C->isNullValue()) {
1462 TySize = TD->getABITypeSize(C->getType());
1464 Out << "int8 (0) [" << TySize << "]";
1467 // Print constant initializer
1468 switch (Ty->getTypeID()) {
1469 case Type::IntegerTyID: {
1470 TySize = TD->getABITypeSize(Ty);
1471 const ConstantInt* Int = cast<ConstantInt>(C);
1472 Out << getPrimitiveTypeName(Ty,true) << "(" << Int->getSExtValue() << ")";
1475 case Type::FloatTyID:
1476 case Type::DoubleTyID: {
1477 TySize = TD->getABITypeSize(Ty);
1478 const ConstantFP* FP = cast<ConstantFP>(C);
1479 if (Ty->getTypeID() == Type::FloatTyID)
1481 (uint32_t)FP->getValueAPF().convertToAPInt().getZExtValue() << ')';
1484 FP->getValueAPF().convertToAPInt().getZExtValue() << ')';
1487 case Type::ArrayTyID:
1488 case Type::VectorTyID:
1489 case Type::StructTyID:
1490 for (unsigned I = 0, E = C->getNumOperands(); I<E; I++) {
1491 if (I!=0) Out << ",\n";
1492 printStaticConstant(C->getOperand(I),Offset);
1495 case Type::PointerTyID:
1496 TySize = TD->getABITypeSize(C->getType());
1497 // Initialize with global variable address
1498 if (const GlobalVariable *G = dyn_cast<GlobalVariable>(C)) {
1499 std::string name = getValueName(G);
1500 Out << "&(" << name.insert(name.length()-1,"$data") << ")";
1502 // Dynamic initialization
1503 if (!isa<ConstantPointerNull>(C) && !C->isNullValue())
1504 InitListPtr->push_back(StaticInitializer(C,Offset));
1505 // Null pointer initialization
1506 if (TySize==4) Out << "int32 (0)";
1507 else if (TySize==8) Out << "int64 (0)";
1508 else assert(0 && "Invalid pointer size");
1512 cerr << "TypeID = " << Ty->getTypeID() << '\n';
1513 assert(0 && "Invalid type in printStaticConstant()");
1520 void MSILWriter::printStaticInitializer(const Constant* C,
1521 const std::string& Name) {
1522 switch (C->getType()->getTypeID()) {
1523 case Type::IntegerTyID:
1524 case Type::FloatTyID:
1525 case Type::DoubleTyID:
1526 Out << getPrimitiveTypeName(C->getType(), false);
1528 case Type::ArrayTyID:
1529 case Type::VectorTyID:
1530 case Type::StructTyID:
1531 case Type::PointerTyID:
1532 Out << getTypeName(C->getType());
1535 cerr << "Type = " << *C << "\n";
1536 assert(0 && "Invalid constant type");
1538 // Print initializer
1539 std::string label = Name;
1540 label.insert(label.length()-1,"$data");
1541 Out << Name << " at " << label << '\n';
1542 Out << ".data " << label << " = {\n";
1543 uint64_t offset = 0;
1544 printStaticConstant(C,offset);
1549 void MSILWriter::printVariableDefinition(const GlobalVariable* G) {
1550 const Constant* C = G->getInitializer();
1551 if (C->isNullValue() || isa<ConstantAggregateZero>(C) || isa<UndefValue>(C))
1554 InitListPtr = &StaticInitList[G];
1555 printStaticInitializer(C,getValueName(G));
1559 void MSILWriter::printGlobalVariables() {
1560 if (ModulePtr->global_empty()) return;
1561 Module::global_iterator I,E;
1562 for (I = ModulePtr->global_begin(), E = ModulePtr->global_end(); I!=E; ++I) {
1563 // Variable definition
1564 Out << ".field static " << (I->isDeclaration() ? "public " :
1566 if (I->isDeclaration()) {
1567 Out << getTypeName(I->getType()) << getValueName(&*I) << "\n\n";
1569 printVariableDefinition(&*I);
1574 const char* MSILWriter::getLibraryName(const Function* F) {
1575 return getLibraryForSymbol(F->getName().c_str(), true, F->getCallingConv());
1579 const char* MSILWriter::getLibraryName(const GlobalVariable* GV) {
1580 return getLibraryForSymbol(Mang->getValueName(GV).c_str(), false, 0);
1584 const char* MSILWriter::getLibraryForSymbol(const char* Name, bool isFunction,
1585 unsigned CallingConv) {
1586 // TODO: Read *.def file with function and libraries definitions.
1587 return "MSVCRT.DLL";
1591 void MSILWriter::printExternals() {
1592 Module::const_iterator I,E;
1594 for (I=ModulePtr->begin(),E=ModulePtr->end(); I!=E; ++I) {
1596 if (I->isIntrinsic()) continue;
1597 if (I->isDeclaration()) {
1598 const Function* F = I;
1599 std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);
1601 getCallSignature(cast<FunctionType>(F->getFunctionType()), NULL, Name);
1602 Out << ".method static hidebysig pinvokeimpl(\""
1603 << getLibraryName(F) << "\")\n\t" << Sig << " preservesig {}\n\n";
1606 // External variables and static initialization.
1608 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1609 " native int LoadLibrary(string) preservesig {}\n"
1610 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1611 " native int GetProcAddress(native int, string) preservesig {}\n";
1613 ".method private static void* $MSIL_Import(string lib,string sym)\n"
1616 "\tcall\tnative int LoadLibrary(string)\n"
1618 "\tcall\tnative int GetProcAddress(native int,string)\n"
1621 "\tldstr\t\"Can no import variable\"\n"
1622 "\tnewobj\tinstance void [mscorlib]System.Exception::.ctor(string)\n"
1627 ".method static private void $MSIL_Init() managed cil\n{\n";
1628 printStaticInitializerList();
1629 // Foreach global variable.
1630 for (Module::global_iterator I = ModulePtr->global_begin(),
1631 E = ModulePtr->global_end(); I!=E; ++I) {
1632 if (!I->isDeclaration() || !I->hasDLLImportLinkage()) continue;
1633 // Use "LoadLibrary"/"GetProcAddress" to recive variable address.
1634 std::string Label = "not_null$_"+utostr(getUniqID());
1635 std::string Tmp = getTypeName(I->getType())+getValueName(&*I);
1636 printSimpleInstruction("ldsflda",Tmp.c_str());
1637 Out << "\tldstr\t\"" << getLibraryName(&*I) << "\"\n";
1638 Out << "\tldstr\t\"" << Mang->getValueName(&*I) << "\"\n";
1639 printSimpleInstruction("call","void* $MSIL_Import(string,string)");
1640 printIndirectSave(I->getType());
1642 printSimpleInstruction("ret");
1647 //===----------------------------------------------------------------------===//
1648 // External Interface declaration
1649 //===----------------------------------------------------------------------===//
1651 bool MSILTarget::addPassesToEmitWholeFile(PassManager &PM, raw_ostream &o,
1652 CodeGenFileType FileType, bool Fast)
1654 if (FileType != TargetMachine::AssemblyFile) return true;
1655 MSILWriter* Writer = new MSILWriter(o);
1656 PM.add(createGCLoweringPass());
1657 PM.add(createLowerAllocationsPass(true));
1658 // FIXME: Handle switch trougth native IL instruction "switch"
1659 PM.add(createLowerSwitchPass());
1660 PM.add(createCFGSimplificationPass());
1661 PM.add(new MSILModule(Writer->UsedTypes,Writer->TD));
1663 PM.add(createGCInfoDeleter());