1 //===-- MSILWriter.cpp - Library for converting LLVM code to MSIL ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by Roman Samoilov and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
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"
29 // TargetMachine for the MSIL
30 struct VISIBILITY_HIDDEN MSILTarget
: public TargetMachine
{
31 const TargetData DataLayout
; // Calculates type size & alignment
33 MSILTarget(const Module
&M
, const std::string
&FS
)
36 virtual bool WantsWholeFile() const { return true; }
37 virtual bool addPassesToEmitWholeFile(PassManager
&PM
, std::ostream
&Out
,
38 CodeGenFileType FileType
, bool Fast
);
40 // This class always works, but shouldn't be the default in most cases.
41 static unsigned getModuleMatchQuality(const Module
&M
) { return 1; }
43 virtual const TargetData
*getTargetData() const { return &DataLayout
; }
48 RegisterTarget
<MSILTarget
> X("msil", " MSIL backend");
50 bool MSILModule::runOnModule(Module
&M
) {
52 TD
= &getAnalysis
<TargetData
>();
55 TypeSymbolTable
& Table
= M
.getTypeSymbolTable();
56 std::set
<const Type
*> Types
= getAnalysis
<FindUsedTypes
>().getTypes();
57 for (TypeSymbolTable::iterator I
= Table
.begin(), E
= Table
.end(); I
!=E
; ) {
58 if (!isa
<StructType
>(I
->second
) && !isa
<OpaqueType
>(I
->second
))
61 std::set
<const Type
*>::iterator T
= Types
.find(I
->second
);
70 // Find unnamed types.
71 unsigned RenameCounter
= 0;
72 for (std::set
<const Type
*>::const_iterator I
= Types
.begin(),
73 E
= Types
.end(); I
!=E
; ++I
)
74 if (const StructType
*STy
= dyn_cast
<StructType
>(*I
)) {
75 while (ModulePtr
->addTypeName("unnamed$"+utostr(RenameCounter
), STy
))
79 // Pointer for FunctionPass.
80 UsedTypes
= &getAnalysis
<FindUsedTypes
>().getTypes();
84 char MSILModule::ID
= 0;
85 char MSILWriter::ID
= 0;
87 bool MSILWriter::runOnFunction(Function
&F
) {
88 if (F
.isDeclaration()) return false;
89 LInfo
= &getAnalysis
<LoopInfo
>();
95 bool MSILWriter::doInitialization(Module
&M
) {
97 Mang
= new Mangler(M
);
98 Out
<< ".assembly extern mscorlib {}\n";
99 Out
<< ".assembly MSIL {}\n\n";
100 Out
<< "// External\n";
102 Out
<< "// Declarations\n";
103 printDeclarations(M
.getTypeSymbolTable());
104 Out
<< "// Definitions\n";
105 printGlobalVariables();
106 Out
<< "// Startup code\n";
107 printModuleStartup();
112 bool MSILWriter::doFinalization(Module
&M
) {
118 void MSILWriter::printModuleStartup() {
120 ".method static public int32 $MSIL_Startup() {\n"
122 "\t.locals (native int i)\n"
123 "\t.locals (native int argc)\n"
124 "\t.locals (native int ptr)\n"
125 "\t.locals (void* argv)\n"
126 "\t.locals (string[] args)\n"
127 "\tcall\tstring[] [mscorlib]System.Environment::GetCommandLineArgs()\n"
134 printPtrLoad(TD
->getPointerSize());
149 "\tcall\tnative int [mscorlib]System.Runtime.InteropServices.Marshal::"
150 "StringToHGlobalAnsi(string)\n"
154 printPtrLoad(TD
->getPointerSize());
166 "\tcall void $MSIL_Init()\n";
168 // Call user 'main' function.
169 const Function
* F
= ModulePtr
->getFunction("main");
170 if (!F
|| F
->isDeclaration()) {
171 Out
<< "\tldc.i4.0\n\tret\n}\n";
175 std::string
Args("");
176 Function::const_arg_iterator Arg1
,Arg2
;
178 switch (F
->arg_size()) {
183 Arg1
= F
->arg_begin();
184 if (Arg1
->getType()->isInteger()) {
185 Out
<< "\tldloc\targc\n";
186 Args
= getTypeName(Arg1
->getType());
191 Arg1
= Arg2
= F
->arg_begin(); ++Arg2
;
192 if (Arg1
->getType()->isInteger() &&
193 Arg2
->getType()->getTypeID() == Type::PointerTyID
) {
194 Out
<< "\tldloc\targc\n\tldloc\targv\n";
195 Args
= getTypeName(Arg1
->getType())+","+getTypeName(Arg2
->getType());
203 bool RetVoid
= (F
->getReturnType()->getTypeID() == Type::VoidTyID
);
204 if (BadSig
|| !F
->getReturnType()->isInteger() && !RetVoid
) {
205 Out
<< "\tldc.i4.0\n";
207 Out
<< "\tcall\t" << getTypeName(F
->getReturnType()) <<
208 getConvModopt(F
->getCallingConv()) << "main(" << Args
<< ")\n";
210 Out
<< "\tldc.i4.0\n";
212 Out
<< "\tconv.i4\n";
217 bool MSILWriter::isZeroValue(const Value
* V
) {
218 if (const Constant
*C
= dyn_cast
<Constant
>(V
))
219 return C
->isNullValue();
224 std::string
MSILWriter::getValueName(const Value
* V
) {
225 // Name into the quotes allow control and space characters.
226 return "'"+Mang
->getValueName(V
)+"'";
230 std::string
MSILWriter::getLabelName(const std::string
& Name
) {
231 if (Name
.find('.')!=std::string::npos
) {
232 std::string
Tmp(Name
);
233 // Replace unaccepable characters in the label name.
234 for (std::string::iterator I
= Tmp
.begin(), E
= Tmp
.end(); I
!=E
; ++I
)
235 if (*I
=='.') *I
= '@';
242 std::string
MSILWriter::getLabelName(const Value
* V
) {
243 return getLabelName(Mang
->getValueName(V
));
247 std::string
MSILWriter::getConvModopt(unsigned CallingConvID
) {
248 switch (CallingConvID
) {
250 case CallingConv::Cold
:
251 case CallingConv::Fast
:
252 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) ";
253 case CallingConv::X86_FastCall
:
254 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvFastcall) ";
255 case CallingConv::X86_StdCall
:
256 return "modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall) ";
258 cerr
<< "CallingConvID = " << CallingConvID
<< '\n';
259 assert(0 && "Unsupported calling convention");
264 std::string
MSILWriter::getArrayTypeName(Type::TypeID TyID
, const Type
* Ty
) {
265 std::string Tmp
= "";
266 const Type
* ElemTy
= Ty
;
267 assert(Ty
->getTypeID()==TyID
&& "Invalid type passed");
268 // Walk trought array element types.
270 // Multidimensional array.
271 if (ElemTy
->getTypeID()==TyID
) {
272 if (const ArrayType
* ATy
= dyn_cast
<ArrayType
>(ElemTy
))
273 Tmp
+= utostr(ATy
->getNumElements());
274 else if (const VectorType
* VTy
= dyn_cast
<VectorType
>(ElemTy
))
275 Tmp
+= utostr(VTy
->getNumElements());
276 ElemTy
= cast
<SequentialType
>(ElemTy
)->getElementType();
278 // Base element type found.
279 if (ElemTy
->getTypeID()!=TyID
) break;
282 return getTypeName(ElemTy
, false, true)+"["+Tmp
+"]";
286 std::string
MSILWriter::getPrimitiveTypeName(const Type
* Ty
, bool isSigned
) {
287 unsigned NumBits
= 0;
288 switch (Ty
->getTypeID()) {
291 case Type::IntegerTyID
:
292 NumBits
= getBitWidth(Ty
);
296 return "unsigned int"+utostr(NumBits
)+" ";
297 return "int"+utostr(NumBits
)+" ";
298 case Type::FloatTyID
:
300 case Type::DoubleTyID
:
303 cerr
<< "Type = " << *Ty
<< '\n';
304 assert(0 && "Invalid primitive type");
309 std::string
MSILWriter::getTypeName(const Type
* Ty
, bool isSigned
,
311 if (Ty
->isPrimitiveType() || Ty
->isInteger())
312 return getPrimitiveTypeName(Ty
,isSigned
);
313 // FIXME: "OpaqueType" support
314 switch (Ty
->getTypeID()) {
315 case Type::PointerTyID
:
317 case Type::StructTyID
:
319 return ModulePtr
->getTypeName(Ty
);
320 return "valuetype '"+ModulePtr
->getTypeName(Ty
)+"' ";
321 case Type::ArrayTyID
:
323 return getArrayTypeName(Ty
->getTypeID(),Ty
);
324 return "valuetype '"+getArrayTypeName(Ty
->getTypeID(),Ty
)+"' ";
325 case Type::VectorTyID
:
327 return getArrayTypeName(Ty
->getTypeID(),Ty
);
328 return "valuetype '"+getArrayTypeName(Ty
->getTypeID(),Ty
)+"' ";
330 cerr
<< "Type = " << *Ty
<< '\n';
331 assert(0 && "Invalid type in getTypeName()");
336 MSILWriter::ValueType
MSILWriter::getValueLocation(const Value
* V
) {
338 if (isa
<Argument
>(V
))
341 else if (const Function
* F
= dyn_cast
<Function
>(V
))
342 return F
->hasInternalLinkage() ? InternalVT
: GlobalVT
;
344 else if (const GlobalVariable
* G
= dyn_cast
<GlobalVariable
>(V
))
345 return G
->hasInternalLinkage() ? InternalVT
: GlobalVT
;
347 else if (isa
<Constant
>(V
))
348 return isa
<ConstantExpr
>(V
) ? ConstExprVT
: ConstVT
;
354 std::string
MSILWriter::getTypePostfix(const Type
* Ty
, bool Expand
,
356 unsigned NumBits
= 0;
357 switch (Ty
->getTypeID()) {
358 // Integer constant, expanding for stack operations.
359 case Type::IntegerTyID
:
360 NumBits
= getBitWidth(Ty
);
361 // Expand integer value to "int32" or "int64".
362 if (Expand
) return (NumBits
<=32 ? "i4" : "i8");
363 if (NumBits
==1) return "i1";
364 return (isSigned
? "i" : "u")+utostr(NumBits
/8);
366 case Type::FloatTyID
:
368 case Type::DoubleTyID
:
370 case Type::PointerTyID
:
371 return "i"+utostr(TD
->getTypeSize(Ty
));
373 cerr
<< "TypeID = " << Ty
->getTypeID() << '\n';
374 assert(0 && "Invalid type in TypeToPostfix()");
379 void MSILWriter::printConvToPtr() {
380 switch (ModulePtr
->getPointerSize()) {
381 case Module::Pointer32
:
382 printSimpleInstruction("conv.u4");
384 case Module::Pointer64
:
385 printSimpleInstruction("conv.u8");
388 assert(0 && "Module use not supporting pointer size");
393 void MSILWriter::printPtrLoad(uint64_t N
) {
394 switch (ModulePtr
->getPointerSize()) {
395 case Module::Pointer32
:
396 printSimpleInstruction("ldc.i4",utostr(N
).c_str());
397 // FIXME: Need overflow test?
399 cerr
<< "Value = " << utostr(N
) << '\n';
400 assert(0 && "32-bit pointer overflowed");
403 case Module::Pointer64
:
404 printSimpleInstruction("ldc.i8",utostr(N
).c_str());
407 assert(0 && "Module use not supporting pointer size");
412 void MSILWriter::printValuePtrLoad(const Value
* V
) {
418 void MSILWriter::printConstLoad(const Constant
* C
) {
419 if (const ConstantInt
* CInt
= dyn_cast
<ConstantInt
>(C
)) {
421 Out
<< "\tldc." << getTypePostfix(C
->getType(),true) << '\t';
422 if (CInt
->isMinValue(true))
423 Out
<< CInt
->getSExtValue();
425 Out
<< CInt
->getZExtValue();
426 } else if (const ConstantFP
* FP
= dyn_cast
<ConstantFP
>(C
)) {
430 if (FP
->getType()->getTypeID()==Type::FloatTyID
) {
431 X
= (uint32_t)FP
->getValueAPF().convertToAPInt().getZExtValue();
434 X
= FP
->getValueAPF().convertToAPInt().getZExtValue();
437 Out
<< "\tldc.r" << Size
<< "\t( " << utohexstr(X
) << ')';
438 } else if (isa
<UndefValue
>(C
)) {
439 // Undefined constant value = NULL.
442 cerr
<< "Constant = " << *C
<< '\n';
443 assert(0 && "Invalid constant value");
449 void MSILWriter::printValueLoad(const Value
* V
) {
450 MSILWriter::ValueType Location
= getValueLocation(V
);
452 // Global variable or function address.
455 if (const Function
* F
= dyn_cast
<Function
>(V
)) {
456 std::string Name
= getConvModopt(F
->getCallingConv())+getValueName(F
);
457 printSimpleInstruction("ldftn",
458 getCallSignature(F
->getFunctionType(),NULL
,Name
).c_str());
461 const Type
* ElemTy
= cast
<PointerType
>(V
->getType())->getElementType();
462 if (Location
==GlobalVT
&& cast
<GlobalVariable
>(V
)->hasDLLImportLinkage()) {
463 Tmp
= "void* "+getValueName(V
);
464 printSimpleInstruction("ldsfld",Tmp
.c_str());
466 Tmp
= getTypeName(ElemTy
)+getValueName(V
);
467 printSimpleInstruction("ldsflda",Tmp
.c_str());
471 // Function argument.
473 printSimpleInstruction("ldarg",getValueName(V
).c_str());
475 // Local function variable.
477 printSimpleInstruction("ldloc",getValueName(V
).c_str());
481 if (isa
<ConstantPointerNull
>(V
))
484 printConstLoad(cast
<Constant
>(V
));
486 // Constant expression.
488 printConstantExpr(cast
<ConstantExpr
>(V
));
491 cerr
<< "Value = " << *V
<< '\n';
492 assert(0 && "Invalid value location");
497 void MSILWriter::printValueSave(const Value
* V
) {
498 switch (getValueLocation(V
)) {
500 printSimpleInstruction("starg",getValueName(V
).c_str());
503 printSimpleInstruction("stloc",getValueName(V
).c_str());
506 cerr
<< "Value = " << *V
<< '\n';
507 assert(0 && "Invalid value location");
512 void MSILWriter::printBinaryInstruction(const char* Name
, const Value
* Left
,
513 const Value
* Right
) {
514 printValueLoad(Left
);
515 printValueLoad(Right
);
516 Out
<< '\t' << Name
<< '\n';
520 void MSILWriter::printSimpleInstruction(const char* Inst
, const char* Operand
) {
522 Out
<< '\t' << Inst
<< '\t' << Operand
<< '\n';
524 Out
<< '\t' << Inst
<< '\n';
528 void MSILWriter::printPHICopy(const BasicBlock
* Src
, const BasicBlock
* Dst
) {
529 for (BasicBlock::const_iterator I
= Dst
->begin(), E
= Dst
->end();
530 isa
<PHINode
>(I
); ++I
) {
531 const PHINode
* Phi
= cast
<PHINode
>(I
);
532 const Value
* Val
= Phi
->getIncomingValueForBlock(Src
);
533 if (isa
<UndefValue
>(Val
)) continue;
540 void MSILWriter::printBranchToBlock(const BasicBlock
* CurrBB
,
541 const BasicBlock
* TrueBB
,
542 const BasicBlock
* FalseBB
) {
543 if (TrueBB
==FalseBB
) {
544 // "TrueBB" and "FalseBB" destination equals
545 printPHICopy(CurrBB
,TrueBB
);
546 printSimpleInstruction("pop");
547 printSimpleInstruction("br",getLabelName(TrueBB
).c_str());
548 } else if (FalseBB
==NULL
) {
549 // If "FalseBB" not used the jump have condition
550 printPHICopy(CurrBB
,TrueBB
);
551 printSimpleInstruction("brtrue",getLabelName(TrueBB
).c_str());
552 } else if (TrueBB
==NULL
) {
553 // If "TrueBB" not used the jump is unconditional
554 printPHICopy(CurrBB
,FalseBB
);
555 printSimpleInstruction("br",getLabelName(FalseBB
).c_str());
557 // Copy PHI instructions for each block
558 std::string TmpLabel
;
559 // Print PHI instructions for "TrueBB"
560 if (isa
<PHINode
>(TrueBB
->begin())) {
561 TmpLabel
= getLabelName(TrueBB
)+"$phi_"+utostr(getUniqID());
562 printSimpleInstruction("brtrue",TmpLabel
.c_str());
564 printSimpleInstruction("brtrue",getLabelName(TrueBB
).c_str());
566 // Print PHI instructions for "FalseBB"
567 if (isa
<PHINode
>(FalseBB
->begin())) {
568 printPHICopy(CurrBB
,FalseBB
);
569 printSimpleInstruction("br",getLabelName(FalseBB
).c_str());
571 printSimpleInstruction("br",getLabelName(FalseBB
).c_str());
573 if (isa
<PHINode
>(TrueBB
->begin())) {
574 // Handle "TrueBB" PHI Copy
575 Out
<< TmpLabel
<< ":\n";
576 printPHICopy(CurrBB
,TrueBB
);
577 printSimpleInstruction("br",getLabelName(TrueBB
).c_str());
583 void MSILWriter::printBranchInstruction(const BranchInst
* Inst
) {
584 if (Inst
->isUnconditional()) {
585 printBranchToBlock(Inst
->getParent(),NULL
,Inst
->getSuccessor(0));
587 printValueLoad(Inst
->getCondition());
588 printBranchToBlock(Inst
->getParent(),Inst
->getSuccessor(0),
589 Inst
->getSuccessor(1));
594 void MSILWriter::printSelectInstruction(const Value
* Cond
, const Value
* VTrue
,
595 const Value
* VFalse
) {
596 std::string TmpLabel
= std::string("select$true_")+utostr(getUniqID());
597 printValueLoad(VTrue
);
598 printValueLoad(Cond
);
599 printSimpleInstruction("brtrue",TmpLabel
.c_str());
600 printSimpleInstruction("pop");
601 printValueLoad(VFalse
);
602 Out
<< TmpLabel
<< ":\n";
606 void MSILWriter::printIndirectLoad(const Value
* V
) {
607 const Type
* Ty
= V
->getType();
609 if (const PointerType
* P
= dyn_cast
<PointerType
>(Ty
))
610 Ty
= P
->getElementType();
611 std::string Tmp
= "ldind."+getTypePostfix(Ty
, false);
612 printSimpleInstruction(Tmp
.c_str());
616 void MSILWriter::printIndirectSave(const Value
* Ptr
, const Value
* Val
) {
619 printIndirectSave(Val
->getType());
623 void MSILWriter::printIndirectSave(const Type
* Ty
) {
624 // Instruction need signed postfix for any type.
625 std::string postfix
= getTypePostfix(Ty
, false);
626 if (*postfix
.begin()=='u') *postfix
.begin() = 'i';
627 postfix
= "stind."+postfix
;
628 printSimpleInstruction(postfix
.c_str());
632 void MSILWriter::printCastInstruction(unsigned int Op
, const Value
* V
,
638 case Instruction::SExt
:
639 case Instruction::SIToFP
:
640 case Instruction::FPToSI
:
641 Tmp
= "conv."+getTypePostfix(Ty
,false,true);
642 printSimpleInstruction(Tmp
.c_str());
645 case Instruction::FPTrunc
:
646 case Instruction::FPExt
:
647 case Instruction::UIToFP
:
648 case Instruction::Trunc
:
649 case Instruction::ZExt
:
650 case Instruction::FPToUI
:
651 case Instruction::PtrToInt
:
652 case Instruction::IntToPtr
:
653 Tmp
= "conv."+getTypePostfix(Ty
,false);
654 printSimpleInstruction(Tmp
.c_str());
657 case Instruction::BitCast
:
658 // FIXME: meaning that ld*/st* instruction do not change data format.
661 cerr
<< "Opcode = " << Op
<< '\n';
662 assert(0 && "Invalid conversion instruction");
667 void MSILWriter::printGepInstruction(const Value
* V
, gep_type_iterator I
,
668 gep_type_iterator E
) {
671 printValuePtrLoad(V
);
672 // Calculate element offset.
675 const Value
* IndexValue
= I
.getOperand();
676 if (const StructType
* StrucTy
= dyn_cast
<StructType
>(*I
)) {
677 uint64_t FieldIndex
= cast
<ConstantInt
>(IndexValue
)->getZExtValue();
678 // Offset is the sum of all previous structure fields.
679 for (uint64_t F
= 0; F
<FieldIndex
; ++F
)
680 Size
+= TD
->getTypeSize(StrucTy
->getContainedType((unsigned)F
));
682 printSimpleInstruction("add");
684 } else if (const SequentialType
* SeqTy
= dyn_cast
<SequentialType
>(*I
)) {
685 Size
= TD
->getTypeSize(SeqTy
->getElementType());
687 Size
= TD
->getTypeSize(*I
);
689 // Add offset of current element to stack top.
690 if (!isZeroValue(IndexValue
)) {
691 // Constant optimization.
692 if (const ConstantInt
* C
= dyn_cast
<ConstantInt
>(IndexValue
)) {
693 if (C
->getValue().isNegative()) {
694 printPtrLoad(C
->getValue().abs().getZExtValue()*Size
);
695 printSimpleInstruction("sub");
698 printPtrLoad(C
->getZExtValue()*Size
);
701 printValuePtrLoad(IndexValue
);
702 printSimpleInstruction("mul");
704 printSimpleInstruction("add");
710 std::string
MSILWriter::getCallSignature(const FunctionType
* Ty
,
711 const Instruction
* Inst
,
714 if (Ty
->isVarArg()) Tmp
+= "vararg ";
715 // Name and return type.
716 Tmp
+= getTypeName(Ty
->getReturnType())+Name
+"(";
717 // Function argument type list.
718 unsigned NumParams
= Ty
->getNumParams();
719 for (unsigned I
= 0; I
!=NumParams
; ++I
) {
720 if (I
!=0) Tmp
+= ",";
721 Tmp
+= getTypeName(Ty
->getParamType(I
));
723 // CLR needs to know the exact amount of parameters received by vararg
724 // function, because caller cleans the stack.
725 if (Ty
->isVarArg() && Inst
) {
726 // Origin to function arguments in "CallInst" or "InvokeInst".
727 unsigned Org
= isa
<InvokeInst
>(Inst
) ? 3 : 1;
728 // Print variable argument types.
729 unsigned NumOperands
= Inst
->getNumOperands()-Org
;
730 if (NumParams
<NumOperands
) {
731 if (NumParams
!=0) Tmp
+= ", ";
733 for (unsigned J
= NumParams
; J
!=NumOperands
; ++J
) {
734 if (J
!=NumParams
) Tmp
+= ", ";
735 Tmp
+= getTypeName(Inst
->getOperand(J
+Org
)->getType());
743 void MSILWriter::printFunctionCall(const Value
* FnVal
,
744 const Instruction
* Inst
) {
745 // Get function calling convention.
746 std::string Name
= "";
747 if (const CallInst
* Call
= dyn_cast
<CallInst
>(Inst
))
748 Name
= getConvModopt(Call
->getCallingConv());
749 else if (const InvokeInst
* Invoke
= dyn_cast
<InvokeInst
>(Inst
))
750 Name
= getConvModopt(Invoke
->getCallingConv());
752 cerr
<< "Instruction = " << Inst
->getName() << '\n';
753 assert(0 && "Need \"Invoke\" or \"Call\" instruction only");
755 if (const Function
* F
= dyn_cast
<Function
>(FnVal
)) {
757 Name
+= getValueName(F
);
758 printSimpleInstruction("call",
759 getCallSignature(F
->getFunctionType(),Inst
,Name
).c_str());
761 // Indirect function call.
762 const PointerType
* PTy
= cast
<PointerType
>(FnVal
->getType());
763 const FunctionType
* FTy
= cast
<FunctionType
>(PTy
->getElementType());
764 // Load function address.
765 printValueLoad(FnVal
);
766 printSimpleInstruction("calli",getCallSignature(FTy
,Inst
,Name
).c_str());
771 void MSILWriter::printIntrinsicCall(const IntrinsicInst
* Inst
) {
773 switch (Inst
->getIntrinsicID()) {
774 case Intrinsic::vastart
:
775 Name
= getValueName(Inst
->getOperand(1));
776 Name
.insert(Name
.length()-1,"$valist");
777 // Obtain the argument handle.
778 printSimpleInstruction("ldloca",Name
.c_str());
779 printSimpleInstruction("arglist");
780 printSimpleInstruction("call",
781 "instance void [mscorlib]System.ArgIterator::.ctor"
782 "(valuetype [mscorlib]System.RuntimeArgumentHandle)");
783 // Save as pointer type "void*"
784 printValueLoad(Inst
->getOperand(1));
785 printSimpleInstruction("ldloca",Name
.c_str());
786 printIndirectSave(PointerType::get(IntegerType::get(8)));
788 case Intrinsic::vaend
:
789 // Close argument list handle.
790 printIndirectLoad(Inst
->getOperand(1));
791 printSimpleInstruction("call","instance void [mscorlib]System.ArgIterator::End()");
793 case Intrinsic::vacopy
:
794 // Copy "ArgIterator" valuetype.
795 printIndirectLoad(Inst
->getOperand(1));
796 printIndirectLoad(Inst
->getOperand(2));
797 printSimpleInstruction("cpobj","[mscorlib]System.ArgIterator");
800 cerr
<< "Intrinsic ID = " << Inst
->getIntrinsicID() << '\n';
801 assert(0 && "Invalid intrinsic function");
806 void MSILWriter::printCallInstruction(const Instruction
* Inst
) {
807 if (isa
<IntrinsicInst
>(Inst
)) {
808 // Handle intrinsic function.
809 printIntrinsicCall(cast
<IntrinsicInst
>(Inst
));
811 // Load arguments to stack and call function.
812 for (int I
= 1, E
= Inst
->getNumOperands(); I
!=E
; ++I
)
813 printValueLoad(Inst
->getOperand(I
));
814 printFunctionCall(Inst
->getOperand(0),Inst
);
819 void MSILWriter::printICmpInstruction(unsigned Predicate
, const Value
* Left
,
820 const Value
* Right
) {
822 case ICmpInst::ICMP_EQ
:
823 printBinaryInstruction("ceq",Left
,Right
);
825 case ICmpInst::ICMP_NE
:
826 // Emulate = not neg (Op1 eq Op2)
827 printBinaryInstruction("ceq",Left
,Right
);
828 printSimpleInstruction("neg");
829 printSimpleInstruction("not");
831 case ICmpInst::ICMP_ULE
:
832 case ICmpInst::ICMP_SLE
:
833 // Emulate = (Op1 eq Op2) or (Op1 lt Op2)
834 printBinaryInstruction("ceq",Left
,Right
);
835 if (Predicate
==ICmpInst::ICMP_ULE
)
836 printBinaryInstruction("clt.un",Left
,Right
);
838 printBinaryInstruction("clt",Left
,Right
);
839 printSimpleInstruction("or");
841 case ICmpInst::ICMP_UGE
:
842 case ICmpInst::ICMP_SGE
:
843 // Emulate = (Op1 eq Op2) or (Op1 gt Op2)
844 printBinaryInstruction("ceq",Left
,Right
);
845 if (Predicate
==ICmpInst::ICMP_UGE
)
846 printBinaryInstruction("cgt.un",Left
,Right
);
848 printBinaryInstruction("cgt",Left
,Right
);
849 printSimpleInstruction("or");
851 case ICmpInst::ICMP_ULT
:
852 printBinaryInstruction("clt.un",Left
,Right
);
854 case ICmpInst::ICMP_SLT
:
855 printBinaryInstruction("clt",Left
,Right
);
857 case ICmpInst::ICMP_UGT
:
858 printBinaryInstruction("cgt.un",Left
,Right
);
859 case ICmpInst::ICMP_SGT
:
860 printBinaryInstruction("cgt",Left
,Right
);
863 cerr
<< "Predicate = " << Predicate
<< '\n';
864 assert(0 && "Invalid icmp predicate");
869 void MSILWriter::printFCmpInstruction(unsigned Predicate
, const Value
* Left
,
870 const Value
* Right
) {
871 // FIXME: Correct comparison
872 std::string NanFunc
= "bool [mscorlib]System.Double::IsNaN(float64)";
874 case FCmpInst::FCMP_UGT
:
875 // X > Y || llvm_fcmp_uno(X, Y)
876 printBinaryInstruction("cgt",Left
,Right
);
877 printFCmpInstruction(FCmpInst::FCMP_UNO
,Left
,Right
);
878 printSimpleInstruction("or");
880 case FCmpInst::FCMP_OGT
:
882 printBinaryInstruction("cgt",Left
,Right
);
884 case FCmpInst::FCMP_UGE
:
885 // X >= Y || llvm_fcmp_uno(X, Y)
886 printBinaryInstruction("ceq",Left
,Right
);
887 printBinaryInstruction("cgt",Left
,Right
);
888 printSimpleInstruction("or");
889 printFCmpInstruction(FCmpInst::FCMP_UNO
,Left
,Right
);
890 printSimpleInstruction("or");
892 case FCmpInst::FCMP_OGE
:
894 printBinaryInstruction("ceq",Left
,Right
);
895 printBinaryInstruction("cgt",Left
,Right
);
896 printSimpleInstruction("or");
898 case FCmpInst::FCMP_ULT
:
899 // X < Y || llvm_fcmp_uno(X, Y)
900 printBinaryInstruction("clt",Left
,Right
);
901 printFCmpInstruction(FCmpInst::FCMP_UNO
,Left
,Right
);
902 printSimpleInstruction("or");
904 case FCmpInst::FCMP_OLT
:
906 printBinaryInstruction("clt",Left
,Right
);
908 case FCmpInst::FCMP_ULE
:
909 // X <= Y || llvm_fcmp_uno(X, Y)
910 printBinaryInstruction("ceq",Left
,Right
);
911 printBinaryInstruction("clt",Left
,Right
);
912 printSimpleInstruction("or");
913 printFCmpInstruction(FCmpInst::FCMP_UNO
,Left
,Right
);
914 printSimpleInstruction("or");
916 case FCmpInst::FCMP_OLE
:
918 printBinaryInstruction("ceq",Left
,Right
);
919 printBinaryInstruction("clt",Left
,Right
);
920 printSimpleInstruction("or");
922 case FCmpInst::FCMP_UEQ
:
923 // X == Y || llvm_fcmp_uno(X, Y)
924 printBinaryInstruction("ceq",Left
,Right
);
925 printFCmpInstruction(FCmpInst::FCMP_UNO
,Left
,Right
);
926 printSimpleInstruction("or");
928 case FCmpInst::FCMP_OEQ
:
930 printBinaryInstruction("ceq",Left
,Right
);
932 case FCmpInst::FCMP_UNE
:
934 printBinaryInstruction("ceq",Left
,Right
);
935 printSimpleInstruction("neg");
936 printSimpleInstruction("not");
938 case FCmpInst::FCMP_ONE
:
939 // X != Y && llvm_fcmp_ord(X, Y)
940 printBinaryInstruction("ceq",Left
,Right
);
941 printSimpleInstruction("not");
943 case FCmpInst::FCMP_ORD
:
944 // return X == X && Y == Y
945 printBinaryInstruction("ceq",Left
,Left
);
946 printBinaryInstruction("ceq",Right
,Right
);
947 printSimpleInstruction("or");
949 case FCmpInst::FCMP_UNO
:
951 printBinaryInstruction("ceq",Left
,Left
);
952 printSimpleInstruction("not");
953 printBinaryInstruction("ceq",Right
,Right
);
954 printSimpleInstruction("not");
955 printSimpleInstruction("or");
958 assert(0 && "Illegal FCmp predicate");
963 void MSILWriter::printInvokeInstruction(const InvokeInst
* Inst
) {
964 std::string Label
= "leave$normal_"+utostr(getUniqID());
967 for (int I
= 3, E
= Inst
->getNumOperands(); I
!=E
; ++I
)
968 printValueLoad(Inst
->getOperand(I
));
969 // Print call instruction
970 printFunctionCall(Inst
->getOperand(0),Inst
);
971 // Save function result and leave "try" block
972 printValueSave(Inst
);
973 printSimpleInstruction("leave",Label
.c_str());
975 Out
<< "catch [mscorlib]System.Exception {\n";
976 // Redirect to unwind block
977 printSimpleInstruction("pop");
978 printBranchToBlock(Inst
->getParent(),NULL
,Inst
->getUnwindDest());
979 Out
<< "}\n" << Label
<< ":\n";
980 // Redirect to continue block
981 printBranchToBlock(Inst
->getParent(),NULL
,Inst
->getNormalDest());
985 void MSILWriter::printSwitchInstruction(const SwitchInst
* Inst
) {
986 // FIXME: Emulate with IL "switch" instruction
987 // Emulate = if () else if () else if () else ...
988 for (unsigned int I
= 1, E
= Inst
->getNumCases(); I
!=E
; ++I
) {
989 printValueLoad(Inst
->getCondition());
990 printValueLoad(Inst
->getCaseValue(I
));
991 printSimpleInstruction("ceq");
992 // Condition jump to successor block
993 printBranchToBlock(Inst
->getParent(),Inst
->getSuccessor(I
),NULL
);
995 // Jump to default block
996 printBranchToBlock(Inst
->getParent(),NULL
,Inst
->getDefaultDest());
1000 void MSILWriter::printVAArgInstruction(const VAArgInst
* Inst
) {
1001 printIndirectLoad(Inst
->getOperand(0));
1002 printSimpleInstruction("call",
1003 "instance typedref [mscorlib]System.ArgIterator::GetNextArg()");
1004 printSimpleInstruction("refanyval","void*");
1005 std::string Name
= "ldind."+getTypePostfix(PointerType::get(IntegerType::get(8)),false);
1006 printSimpleInstruction(Name
.c_str());
1010 void MSILWriter::printAllocaInstruction(const AllocaInst
* Inst
) {
1011 uint64_t Size
= TD
->getTypeSize(Inst
->getAllocatedType());
1012 // Constant optimization.
1013 if (const ConstantInt
* CInt
= dyn_cast
<ConstantInt
>(Inst
->getOperand(0))) {
1014 printPtrLoad(CInt
->getZExtValue()*Size
);
1017 printValueLoad(Inst
->getOperand(0));
1018 printSimpleInstruction("mul");
1020 printSimpleInstruction("localloc");
1024 void MSILWriter::printInstruction(const Instruction
* Inst
) {
1025 const Value
*Left
= 0, *Right
= 0;
1026 if (Inst
->getNumOperands()>=1) Left
= Inst
->getOperand(0);
1027 if (Inst
->getNumOperands()>=2) Right
= Inst
->getOperand(1);
1028 // Print instruction
1029 // FIXME: "ShuffleVector","ExtractElement","InsertElement" support.
1030 switch (Inst
->getOpcode()) {
1032 case Instruction::Ret
:
1033 if (Inst
->getNumOperands()) {
1034 printValueLoad(Left
);
1035 printSimpleInstruction("ret");
1037 printSimpleInstruction("ret");
1039 case Instruction::Br
:
1040 printBranchInstruction(cast
<BranchInst
>(Inst
));
1043 case Instruction::Add
:
1044 printBinaryInstruction("add",Left
,Right
);
1046 case Instruction::Sub
:
1047 printBinaryInstruction("sub",Left
,Right
);
1049 case Instruction::Mul
:
1050 printBinaryInstruction("mul",Left
,Right
);
1052 case Instruction::UDiv
:
1053 printBinaryInstruction("div.un",Left
,Right
);
1055 case Instruction::SDiv
:
1056 case Instruction::FDiv
:
1057 printBinaryInstruction("div",Left
,Right
);
1059 case Instruction::URem
:
1060 printBinaryInstruction("rem.un",Left
,Right
);
1062 case Instruction::SRem
:
1063 case Instruction::FRem
:
1064 printBinaryInstruction("rem",Left
,Right
);
1067 case Instruction::ICmp
:
1068 printICmpInstruction(cast
<ICmpInst
>(Inst
)->getPredicate(),Left
,Right
);
1070 case Instruction::FCmp
:
1071 printFCmpInstruction(cast
<FCmpInst
>(Inst
)->getPredicate(),Left
,Right
);
1074 case Instruction::And
:
1075 printBinaryInstruction("and",Left
,Right
);
1077 case Instruction::Or
:
1078 printBinaryInstruction("or",Left
,Right
);
1080 case Instruction::Xor
:
1081 printBinaryInstruction("xor",Left
,Right
);
1083 case Instruction::Shl
:
1084 printValueLoad(Left
);
1085 printValueLoad(Right
);
1086 printSimpleInstruction("conv.i4");
1087 printSimpleInstruction("shl");
1089 case Instruction::LShr
:
1090 printValueLoad(Left
);
1091 printValueLoad(Right
);
1092 printSimpleInstruction("conv.i4");
1093 printSimpleInstruction("shr.un");
1095 case Instruction::AShr
:
1096 printValueLoad(Left
);
1097 printValueLoad(Right
);
1098 printSimpleInstruction("conv.i4");
1099 printSimpleInstruction("shr");
1101 case Instruction::Select
:
1102 printSelectInstruction(Inst
->getOperand(0),Inst
->getOperand(1),Inst
->getOperand(2));
1104 case Instruction::Load
:
1105 printIndirectLoad(Inst
->getOperand(0));
1107 case Instruction::Store
:
1108 printIndirectSave(Inst
->getOperand(1), Inst
->getOperand(0));
1110 case Instruction::Trunc
:
1111 case Instruction::ZExt
:
1112 case Instruction::SExt
:
1113 case Instruction::FPTrunc
:
1114 case Instruction::FPExt
:
1115 case Instruction::UIToFP
:
1116 case Instruction::SIToFP
:
1117 case Instruction::FPToUI
:
1118 case Instruction::FPToSI
:
1119 case Instruction::PtrToInt
:
1120 case Instruction::IntToPtr
:
1121 case Instruction::BitCast
:
1122 printCastInstruction(Inst
->getOpcode(),Left
,
1123 cast
<CastInst
>(Inst
)->getDestTy());
1125 case Instruction::GetElementPtr
:
1126 printGepInstruction(Inst
->getOperand(0),gep_type_begin(Inst
),
1127 gep_type_end(Inst
));
1129 case Instruction::Call
:
1130 printCallInstruction(cast
<CallInst
>(Inst
));
1132 case Instruction::Invoke
:
1133 printInvokeInstruction(cast
<InvokeInst
>(Inst
));
1135 case Instruction::Unwind
:
1136 printSimpleInstruction("newobj",
1137 "instance void [mscorlib]System.Exception::.ctor()");
1138 printSimpleInstruction("throw");
1140 case Instruction::Switch
:
1141 printSwitchInstruction(cast
<SwitchInst
>(Inst
));
1143 case Instruction::Alloca
:
1144 printAllocaInstruction(cast
<AllocaInst
>(Inst
));
1146 case Instruction::Malloc
:
1147 assert(0 && "LowerAllocationsPass used");
1149 case Instruction::Free
:
1150 assert(0 && "LowerAllocationsPass used");
1152 case Instruction::Unreachable
:
1153 printSimpleInstruction("ldstr", "\"Unreachable instruction\"");
1154 printSimpleInstruction("newobj",
1155 "instance void [mscorlib]System.Exception::.ctor(string)");
1156 printSimpleInstruction("throw");
1158 case Instruction::VAArg
:
1159 printVAArgInstruction(cast
<VAArgInst
>(Inst
));
1162 cerr
<< "Instruction = " << Inst
->getName() << '\n';
1163 assert(0 && "Unsupported instruction");
1168 void MSILWriter::printLoop(const Loop
* L
) {
1169 Out
<< getLabelName(L
->getHeader()->getName()) << ":\n";
1170 const std::vector
<BasicBlock
*>& blocks
= L
->getBlocks();
1171 for (unsigned I
= 0, E
= blocks
.size(); I
!=E
; I
++) {
1172 BasicBlock
* BB
= blocks
[I
];
1173 Loop
* BBLoop
= LInfo
->getLoopFor(BB
);
1175 printBasicBlock(BB
);
1176 else if (BB
==BBLoop
->getHeader() && BBLoop
->getParentLoop()==L
)
1179 printSimpleInstruction("br",getLabelName(L
->getHeader()->getName()).c_str());
1183 void MSILWriter::printBasicBlock(const BasicBlock
* BB
) {
1184 Out
<< getLabelName(BB
) << ":\n";
1185 for (BasicBlock::const_iterator I
= BB
->begin(), E
= BB
->end(); I
!=E
; ++I
) {
1186 const Instruction
* Inst
= I
;
1187 // Comment llvm original instruction
1188 Out
<< "\n//" << *Inst
<< "\n";
1189 // Do not handle PHI instruction in current block
1190 if (Inst
->getOpcode()==Instruction::PHI
) continue;
1191 // Print instruction
1192 printInstruction(Inst
);
1194 if (Inst
->getType()!=Type::VoidTy
) {
1195 // Do not save value after invoke, it done in "try" block
1196 if (Inst
->getOpcode()==Instruction::Invoke
) continue;
1197 printValueSave(Inst
);
1203 void MSILWriter::printLocalVariables(const Function
& F
) {
1205 const Type
* Ty
= NULL
;
1206 std::set
<const Value
*> Printed
;
1207 const Value
* VaList
= NULL
;
1208 unsigned StackDepth
= 8;
1209 // Find local variables
1210 for (const_inst_iterator I
= inst_begin(&F
), E
= inst_end(&F
); I
!=E
; ++I
) {
1211 if (I
->getOpcode()==Instruction::Call
||
1212 I
->getOpcode()==Instruction::Invoke
) {
1213 // Test stack depth.
1214 if (StackDepth
<I
->getNumOperands())
1215 StackDepth
= I
->getNumOperands();
1217 const AllocaInst
* AI
= dyn_cast
<AllocaInst
>(&*I
);
1218 if (AI
&& !isa
<GlobalVariable
>(AI
)) {
1219 // Local variable allocation.
1220 Ty
= PointerType::get(AI
->getAllocatedType());
1221 Name
= getValueName(AI
);
1222 Out
<< "\t.locals (" << getTypeName(Ty
) << Name
<< ")\n";
1223 } else if (I
->getType()!=Type::VoidTy
) {
1224 // Operation result.
1226 Name
= getValueName(&*I
);
1227 Out
<< "\t.locals (" << getTypeName(Ty
) << Name
<< ")\n";
1229 // Test on 'va_list' variable
1230 bool isVaList
= false;
1231 if (const VAArgInst
* VaInst
= dyn_cast
<VAArgInst
>(&*I
)) {
1232 // "va_list" as "va_arg" instruction operand.
1234 VaList
= VaInst
->getOperand(0);
1235 } else if (const IntrinsicInst
* Inst
= dyn_cast
<IntrinsicInst
>(&*I
)) {
1236 // "va_list" as intrinsic function operand.
1237 switch (Inst
->getIntrinsicID()) {
1238 case Intrinsic::vastart
:
1239 case Intrinsic::vaend
:
1240 case Intrinsic::vacopy
:
1242 VaList
= Inst
->getOperand(1);
1248 // Print "va_list" variable.
1249 if (isVaList
&& Printed
.insert(VaList
).second
) {
1250 Name
= getValueName(VaList
);
1251 Name
.insert(Name
.length()-1,"$valist");
1252 Out
<< "\t.locals (valuetype [mscorlib]System.ArgIterator "
1256 printSimpleInstruction(".maxstack",utostr(StackDepth
*2).c_str());
1260 void MSILWriter::printFunctionBody(const Function
& F
) {
1262 for (Function::const_iterator I
= F
.begin(), E
= F
.end(); I
!=E
; ++I
) {
1263 if (Loop
*L
= LInfo
->getLoopFor(I
)) {
1264 if (L
->getHeader()==I
&& L
->getParentLoop()==0)
1273 void MSILWriter::printConstantExpr(const ConstantExpr
* CE
) {
1274 const Value
*left
= 0, *right
= 0;
1275 if (CE
->getNumOperands()>=1) left
= CE
->getOperand(0);
1276 if (CE
->getNumOperands()>=2) right
= CE
->getOperand(1);
1277 // Print instruction
1278 switch (CE
->getOpcode()) {
1279 case Instruction::Trunc
:
1280 case Instruction::ZExt
:
1281 case Instruction::SExt
:
1282 case Instruction::FPTrunc
:
1283 case Instruction::FPExt
:
1284 case Instruction::UIToFP
:
1285 case Instruction::SIToFP
:
1286 case Instruction::FPToUI
:
1287 case Instruction::FPToSI
:
1288 case Instruction::PtrToInt
:
1289 case Instruction::IntToPtr
:
1290 case Instruction::BitCast
:
1291 printCastInstruction(CE
->getOpcode(),left
,CE
->getType());
1293 case Instruction::GetElementPtr
:
1294 printGepInstruction(CE
->getOperand(0),gep_type_begin(CE
),gep_type_end(CE
));
1296 case Instruction::ICmp
:
1297 printICmpInstruction(CE
->getPredicate(),left
,right
);
1299 case Instruction::FCmp
:
1300 printFCmpInstruction(CE
->getPredicate(),left
,right
);
1302 case Instruction::Select
:
1303 printSelectInstruction(CE
->getOperand(0),CE
->getOperand(1),CE
->getOperand(2));
1305 case Instruction::Add
:
1306 printBinaryInstruction("add",left
,right
);
1308 case Instruction::Sub
:
1309 printBinaryInstruction("sub",left
,right
);
1311 case Instruction::Mul
:
1312 printBinaryInstruction("mul",left
,right
);
1314 case Instruction::UDiv
:
1315 printBinaryInstruction("div.un",left
,right
);
1317 case Instruction::SDiv
:
1318 case Instruction::FDiv
:
1319 printBinaryInstruction("div",left
,right
);
1321 case Instruction::URem
:
1322 printBinaryInstruction("rem.un",left
,right
);
1324 case Instruction::SRem
:
1325 case Instruction::FRem
:
1326 printBinaryInstruction("rem",left
,right
);
1328 case Instruction::And
:
1329 printBinaryInstruction("and",left
,right
);
1331 case Instruction::Or
:
1332 printBinaryInstruction("or",left
,right
);
1334 case Instruction::Xor
:
1335 printBinaryInstruction("xor",left
,right
);
1337 case Instruction::Shl
:
1338 printBinaryInstruction("shl",left
,right
);
1340 case Instruction::LShr
:
1341 printBinaryInstruction("shr.un",left
,right
);
1343 case Instruction::AShr
:
1344 printBinaryInstruction("shr",left
,right
);
1347 cerr
<< "Expression = " << *CE
<< "\n";
1348 assert(0 && "Invalid constant expression");
1353 void MSILWriter::printStaticInitializerList() {
1354 // List of global variables with uninitialized fields.
1355 for (std::map
<const GlobalVariable
*,std::vector
<StaticInitializer
> >::iterator
1356 VarI
= StaticInitList
.begin(), VarE
= StaticInitList
.end(); VarI
!=VarE
;
1358 const std::vector
<StaticInitializer
>& InitList
= VarI
->second
;
1359 if (InitList
.empty()) continue;
1360 // For each uninitialized field.
1361 for (std::vector
<StaticInitializer
>::const_iterator I
= InitList
.begin(),
1362 E
= InitList
.end(); I
!=E
; ++I
) {
1363 if (const ConstantExpr
*CE
= dyn_cast
<ConstantExpr
>(I
->constant
)) {
1364 Out
<< "\n// Init " << getValueName(VarI
->first
) << ", offset " <<
1365 utostr(I
->offset
) << ", type "<< *I
->constant
->getType() << "\n\n";
1366 // Load variable address
1367 printValueLoad(VarI
->first
);
1370 printPtrLoad(I
->offset
);
1371 printSimpleInstruction("add");
1374 printConstantExpr(CE
);
1375 // Save result at offset
1376 std::string postfix
= getTypePostfix(CE
->getType(),true);
1377 if (*postfix
.begin()=='u') *postfix
.begin() = 'i';
1378 postfix
= "stind."+postfix
;
1379 printSimpleInstruction(postfix
.c_str());
1381 cerr
<< "Constant = " << *I
->constant
<< '\n';
1382 assert(0 && "Invalid static initializer");
1389 void MSILWriter::printFunction(const Function
& F
) {
1390 const FunctionType
* FTy
= F
.getFunctionType();
1391 const ParamAttrsList
*Attrs
= FTy
->getParamAttrs();
1392 bool isSigned
= Attrs
&& Attrs
->paramHasAttr(0, ParamAttr::SExt
);
1393 Out
<< "\n.method static ";
1394 Out
<< (F
.hasInternalLinkage() ? "private " : "public ");
1395 if (F
.isVarArg()) Out
<< "vararg ";
1396 Out
<< getTypeName(F
.getReturnType(),isSigned
) <<
1397 getConvModopt(F
.getCallingConv()) << getValueName(&F
) << '\n';
1400 unsigned ArgIdx
= 1;
1401 for (Function::const_arg_iterator I
= F
.arg_begin(), E
= F
.arg_end(); I
!=E
;
1403 isSigned
= Attrs
&& Attrs
->paramHasAttr(ArgIdx
, ParamAttr::SExt
);
1404 if (I
!=F
.arg_begin()) Out
<< ", ";
1405 Out
<< getTypeName(I
->getType(),isSigned
) << getValueName(I
);
1407 Out
<< ") cil managed\n";
1410 printLocalVariables(F
);
1411 printFunctionBody(F
);
1416 void MSILWriter::printDeclarations(const TypeSymbolTable
& ST
) {
1418 std::set
<const Type
*> Printed
;
1419 for (std::set
<const Type
*>::const_iterator
1420 UI
= UsedTypes
->begin(), UE
= UsedTypes
->end(); UI
!=UE
; ++UI
) {
1421 const Type
* Ty
= *UI
;
1422 if (isa
<ArrayType
>(Ty
) || isa
<VectorType
>(Ty
) || isa
<StructType
>(Ty
))
1423 Name
= getTypeName(Ty
, false, true);
1424 // Type with no need to declare.
1426 // Print not duplicated type
1427 if (Printed
.insert(Ty
).second
) {
1428 Out
<< ".class value explicit ansi sealed '" << Name
<< "'";
1429 Out
<< " { .pack " << 1 << " .size " << TD
->getTypeSize(Ty
) << " }\n\n";
1435 unsigned int MSILWriter::getBitWidth(const Type
* Ty
) {
1436 unsigned int N
= Ty
->getPrimitiveSizeInBits();
1437 assert(N
!=0 && "Invalid type in getBitWidth()");
1446 cerr
<< "Bits = " << N
<< '\n';
1447 assert(0 && "Unsupported integer width");
1452 void MSILWriter::printStaticConstant(const Constant
* C
, uint64_t& Offset
) {
1453 uint64_t TySize
= 0;
1454 const Type
* Ty
= C
->getType();
1455 // Print zero initialized constant.
1456 if (isa
<ConstantAggregateZero
>(C
) || C
->isNullValue()) {
1457 TySize
= TD
->getTypeSize(C
->getType());
1459 Out
<< "int8 (0) [" << TySize
<< "]";
1462 // Print constant initializer
1463 switch (Ty
->getTypeID()) {
1464 case Type::IntegerTyID
: {
1465 TySize
= TD
->getTypeSize(Ty
);
1466 const ConstantInt
* Int
= cast
<ConstantInt
>(C
);
1467 Out
<< getPrimitiveTypeName(Ty
,true) << "(" << Int
->getSExtValue() << ")";
1470 case Type::FloatTyID
:
1471 case Type::DoubleTyID
: {
1472 TySize
= TD
->getTypeSize(Ty
);
1473 const ConstantFP
* FP
= cast
<ConstantFP
>(C
);
1474 if (Ty
->getTypeID() == Type::FloatTyID
)
1476 (uint32_t)FP
->getValueAPF().convertToAPInt().getZExtValue() << ')';
1479 FP
->getValueAPF().convertToAPInt().getZExtValue() << ')';
1482 case Type::ArrayTyID
:
1483 case Type::VectorTyID
:
1484 case Type::StructTyID
:
1485 for (unsigned I
= 0, E
= C
->getNumOperands(); I
<E
; I
++) {
1486 if (I
!=0) Out
<< ",\n";
1487 printStaticConstant(C
->getOperand(I
),Offset
);
1490 case Type::PointerTyID
:
1491 TySize
= TD
->getTypeSize(C
->getType());
1492 // Initialize with global variable address
1493 if (const GlobalVariable
*G
= dyn_cast
<GlobalVariable
>(C
)) {
1494 std::string name
= getValueName(G
);
1495 Out
<< "&(" << name
.insert(name
.length()-1,"$data") << ")";
1497 // Dynamic initialization
1498 if (!isa
<ConstantPointerNull
>(C
) && !C
->isNullValue())
1499 InitListPtr
->push_back(StaticInitializer(C
,Offset
));
1500 // Null pointer initialization
1501 if (TySize
==4) Out
<< "int32 (0)";
1502 else if (TySize
==8) Out
<< "int64 (0)";
1503 else assert(0 && "Invalid pointer size");
1507 cerr
<< "TypeID = " << Ty
->getTypeID() << '\n';
1508 assert(0 && "Invalid type in printStaticConstant()");
1515 void MSILWriter::printStaticInitializer(const Constant
* C
,
1516 const std::string
& Name
) {
1517 switch (C
->getType()->getTypeID()) {
1518 case Type::IntegerTyID
:
1519 case Type::FloatTyID
:
1520 case Type::DoubleTyID
:
1521 Out
<< getPrimitiveTypeName(C
->getType(), false);
1523 case Type::ArrayTyID
:
1524 case Type::VectorTyID
:
1525 case Type::StructTyID
:
1526 case Type::PointerTyID
:
1527 Out
<< getTypeName(C
->getType());
1530 cerr
<< "Type = " << *C
<< "\n";
1531 assert(0 && "Invalid constant type");
1533 // Print initializer
1534 std::string label
= Name
;
1535 label
.insert(label
.length()-1,"$data");
1536 Out
<< Name
<< " at " << label
<< '\n';
1537 Out
<< ".data " << label
<< " = {\n";
1538 uint64_t offset
= 0;
1539 printStaticConstant(C
,offset
);
1544 void MSILWriter::printVariableDefinition(const GlobalVariable
* G
) {
1545 const Constant
* C
= G
->getInitializer();
1546 if (C
->isNullValue() || isa
<ConstantAggregateZero
>(C
) || isa
<UndefValue
>(C
))
1549 InitListPtr
= &StaticInitList
[G
];
1550 printStaticInitializer(C
,getValueName(G
));
1554 void MSILWriter::printGlobalVariables() {
1555 if (ModulePtr
->global_empty()) return;
1556 Module::global_iterator I
,E
;
1557 for (I
= ModulePtr
->global_begin(), E
= ModulePtr
->global_end(); I
!=E
; ++I
) {
1558 // Variable definition
1559 Out
<< ".field static " << (I
->isDeclaration() ? "public " :
1561 if (I
->isDeclaration()) {
1562 Out
<< getTypeName(I
->getType()) << getValueName(&*I
) << "\n\n";
1564 printVariableDefinition(&*I
);
1569 const char* MSILWriter::getLibraryName(const Function
* F
) {
1570 return getLibraryForSymbol(F
->getName().c_str(), true, F
->getCallingConv());
1574 const char* MSILWriter::getLibraryName(const GlobalVariable
* GV
) {
1575 return getLibraryForSymbol(Mang
->getValueName(GV
).c_str(), false, 0);
1579 const char* MSILWriter::getLibraryForSymbol(const char* Name
, bool isFunction
,
1580 unsigned CallingConv
) {
1581 // TODO: Read *.def file with function and libraries definitions.
1582 return "MSVCRT.DLL";
1586 void MSILWriter::printExternals() {
1587 Module::const_iterator I
,E
;
1589 for (I
=ModulePtr
->begin(),E
=ModulePtr
->end(); I
!=E
; ++I
) {
1591 if (I
->getIntrinsicID()) continue;
1592 if (I
->isDeclaration()) {
1593 const Function
* F
= I
;
1594 std::string Name
= getConvModopt(F
->getCallingConv())+getValueName(F
);
1596 getCallSignature(cast
<FunctionType
>(F
->getFunctionType()), NULL
, Name
);
1597 Out
<< ".method static hidebysig pinvokeimpl(\""
1598 << getLibraryName(F
) << "\")\n\t" << Sig
<< " preservesig {}\n\n";
1601 // External variables and static initialization.
1603 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1604 " native int LoadLibrary(string) preservesig {}\n"
1605 ".method public hidebysig static pinvokeimpl(\"KERNEL32.DLL\" ansi winapi)"
1606 " native int GetProcAddress(native int, string) preservesig {}\n";
1608 ".method private static void* $MSIL_Import(string lib,string sym)\n"
1611 "\tcall\tnative int LoadLibrary(string)\n"
1613 "\tcall\tnative int GetProcAddress(native int,string)\n"
1616 "\tldstr\t\"Can no import variable\"\n"
1617 "\tnewobj\tinstance void [mscorlib]System.Exception::.ctor(string)\n"
1622 ".method static private void $MSIL_Init() managed cil\n{\n";
1623 printStaticInitializerList();
1624 // Foreach global variable.
1625 for (Module::global_iterator I
= ModulePtr
->global_begin(),
1626 E
= ModulePtr
->global_end(); I
!=E
; ++I
) {
1627 if (!I
->isDeclaration() || !I
->hasDLLImportLinkage()) continue;
1628 // Use "LoadLibrary"/"GetProcAddress" to recive variable address.
1629 std::string Label
= "not_null$_"+utostr(getUniqID());
1630 std::string Tmp
= getTypeName(I
->getType())+getValueName(&*I
);
1631 printSimpleInstruction("ldsflda",Tmp
.c_str());
1632 Out
<< "\tldstr\t\"" << getLibraryName(&*I
) << "\"\n";
1633 Out
<< "\tldstr\t\"" << Mang
->getValueName(&*I
) << "\"\n";
1634 printSimpleInstruction("call","void* $MSIL_Import(string,string)");
1635 printIndirectSave(I
->getType());
1637 printSimpleInstruction("ret");
1642 //===----------------------------------------------------------------------===//
1643 // External Interface declaration
1644 //===----------------------------------------------------------------------===//
1646 bool MSILTarget::addPassesToEmitWholeFile(PassManager
&PM
, std::ostream
&o
,
1647 CodeGenFileType FileType
, bool Fast
)
1649 if (FileType
!= TargetMachine::AssemblyFile
) return true;
1650 MSILWriter
* Writer
= new MSILWriter(o
);
1651 PM
.add(createLowerGCPass());
1652 PM
.add(createLowerAllocationsPass(true));
1653 // FIXME: Handle switch trougth native IL instruction "switch"
1654 PM
.add(createLowerSwitchPass());
1655 PM
.add(createCFGSimplificationPass());
1656 PM
.add(new MSILModule(Writer
->UsedTypes
,Writer
->TD
));