gavelino

Hi,

I want to work with Generics in MSIL code. IĄŻm trying to instanciate a generic class, but I am not obtain success. What is the diference to instanciate a generic class and a normal class My big problem is when I should instanciate the generic class and the .ctor method (with Intanciate() method).

Please, help me.
Thanks.















Re: Phoenix TypeVariable

gavelino

Please, Andy.

Give me a guidance. Tell me the steps I should follow to instanciate a Generic class. My research depends this answer.

Thanks for your attention.




Re: Phoenix TypeVariable

Andy Ayers - MSFT

I'm not sure I understand what you are trying to accomplish, so let me ask you a question (and sorry for not replying sooner, I realize you are facing some kind of deadline). Are you trying to (a) create a new generic class, or (b) insert code that refers to some pre-existing generic class, or (c) analyze code that contains references to a generic class

The reason I ask is that when you work at the MSIL level there is no actual representation for an instantiated generic class. That is, if you are creating a generic or referring to a pre-existing one, you will never end up instantiating it -- instantiation happens implicitly within the .Net runtime, when an object of the class is created.

It's my impression that instantation only really makes sense for problem (c), where you want to understand the behavior of some generic class.

So, tell me more precisely what you are trying to do, and I'll do my best to help you do it.






Re: Phoenix TypeVariable

gavelino

Hi,

My doubt is how to instanciate a pre-existing generic class and use its methods. My compiler use a import library, and this library has many generic class. For example: you can tell me how to instanciate the generic class "List<>" (.NET Library) and how to use its method "add".

thanks




Re: Phoenix TypeVariable

gavelino

Hi Andy,

Sorry my insistence, but I really need this information the fastest possible. My project is stoped waiting for this answer. If I have not been clear about my question tell me and IĄŻll try to explain better.


thanks





Re: Phoenix TypeVariable

Andy Ayers - MSFT

I appreciate that this is a blocking issue for you -- expect an answer in the next day or two.






Re: Phoenix TypeVariable

Andy Ayers - MSFT

Ok, here is some code that can more or less drop into the msil compiler sample. It's long enough that I am going to post in two parts.

First, here's how you create a reference to List and then specify a specialization List<int32>. I've only put in the .ctor and Add methods but other methods can be included depending on what you need in a similar manner.

Code Block

// Create a reference to [mscorlib] System.Collections.Generic.List<T>

Phx.Name genericListTypeName =

Phx.Name.New(lifetime, "System.Collections.Generic.List`1");

Phx.Symbols.MsilTypeSymbol genericListTypeSymbol =

Phx.Symbols.MsilTypeSymbol.New(peModuleUnit.SymbolTable, genericListTypeName, 0);

Phx.Types.AggregateType genericListType =

Phx.Types.AggregateType.NewDynamicSize(typeTable, genericListTypeSymbol);

genericListTypeSymbol.Visibility = Phx.Symbols.Visibility.ClrTokenReference;

Phx.Name tName = Phx.Name.New(lifetime, "T");

Phx.Symbols.MsilTypeSymbol tSymbol =

Phx.Symbols.MsilTypeSymbol.New(peModuleUnit.SymbolTable, tName, 0);

Phx.Types.TypeVariableType tType =

genericListType.GenerateTypeVariable(tSymbol);

genericListType.IsSelfDescribing = true;

genericListType.IsDefinition = false;

// Now, attach the class type to the mscorlib assembly reference.

mscorlibSymbol.InsertInLexicalScope(genericListTypeSymbol, genericListTypeName);

// Create a .ctor for this class.

Phx.Types.FunctionTypeBuilder genericListTypeBuilder =

Phx.Types.FunctionTypeBuilder.New(peModuleUnit.TypeTable);

genericListTypeBuilder.CallingConventionKind = Phx.Types.CallingConventionKind.ClrCall;

genericListTypeBuilder.AppendReturnType(peModuleUnit.TypeTable.VoidType);

genericListTypeBuilder.AppendArgumentType(
typeTable.GetObjectPointerType (genericListType),

Phx.Types.FunctionArgumentKind.ThisPointer);

Phx.Types.FunctionType genericCtorFunctionType =
genericListTypeBuilder.GetFunctionType();

Phx.Name genericListCtorFunctionName =

Phx.Name.New(Phx.GlobalData.GlobalLifetime, ".ctor");

Phx.Symbols.FunctionSymbol genericListCtorFuncSym =

Phx.Symbols.FunctionSymbol.New(peModuleUnit.SymbolTable,

0, genericListCtorFunctionName, genericCtorFunctionType,

Phx.Symbols.Visibility.GlobalReference);

genericListCtorFuncSym.IsRuntimeSpecialName = true;

// Add as methods of the genericListType.

genericListType.AddMethod(genericListCtorFuncSym);

genericListTypeSymbol.InsertInLexicalScope(genericListCtorFuncSym,
genericListCtorFunctionName);

// Create the void Add<T> method.

genericListTypeBuilder.Begin();

genericListTypeBuilder.CallingConventionKind = Phx.Types.CallingConventionKind.ClrCall;

genericListTypeBuilder.AppendReturnType(peModuleUnit.TypeTable.VoidType);

genericListTypeBuilder.AppendArgumentType(
typeTable.GetObjectPointerType(genericListType),

Phx.Types.FunctionArgumentKind.ThisPointer);

genericListTypeBuilder.AppendArgumentType(tType);

Phx.Types.FunctionType genericListAddFunctionType =
genericListTypeBuilder.GetFunctionType();

Phx.Name genericListAddFunctionName =

Phx.Name.New(Phx.GlobalData.GlobalLifetime, "Add");

Phx.Symbols.FunctionSymbol genericListAddFuncSym =

Phx.Symbols.FunctionSymbol.New(peModuleUnit.SymbolTable,

0, genericListAddFunctionName, genericListAddFunctionType,

Phx.Symbols.Visibility.GlobalReference);

// and add as method of List<T>

genericListType.AddMethod(genericListAddFuncSym);

genericListTypeSymbol.InsertInLexicalScope(genericListAddFuncSym,
genericListAddFunctionName);

// Now create List<int32>

Phx.Name listInt32Name =

Phx.Name.New(
Phx.
GlobalData.GlobalLifetime, "System.Collections.Generic.List<int32>");

Phx.Symbols.TypeSymbol listInt32Sym =

Phx.Symbols.MsilTypeSymbol.New(peModuleUnit.SymbolTable, listInt32Name, 0);

Phx.Collections.TypeList typeList =

Phx.Collections.TypeList.New(lifetime);

typeList.Append(typeTable.Int32Type);

Phx.Types.AggregateType listIntType =

genericListType.Instantiate(listInt32Sym, typeList);






Re: Phoenix TypeVariable

Andy Ayers - MSFT

Second, here's some IR that declares a new local 'q' of type List<int32>, initializes it with an empty list, and then adds the element 5 to the list.

There are some workarounds here for limitations in how generic instantiation is done, but for the most part the code is similar to referencing a regular (non-generic) method.

Code Block

// Create a local q of type List<int32>.

Phx.Types.Type listIntRefType = typeTable.GetObjectPointerType(listIntType);

Phx.Name qName = Phx.Name.New(lifetime, "q");

Phx.Symbols.LocalVariableSymbol qSymbol =

Phx.Symbols.LocalVariableSymbol.New(functionSymbolTable, 0, hName,

listIntRefType, Phx.Symbols.StorageClass.Auto);

// Create IR:

// q = new List<int32>;

// q.Add(5);

// The following line causes the instantiated generic's function list to be populated.

// For now we need to search through the list for the instantiated methods
// we want to call.

Phx.Symbols.FunctionSymbol listIntFunctions = listIntType.FunctionSymbolList;

Phx.Symbols.FunctionSymbol listIntCtor = null;

Phx.Symbols.FunctionSymbol listAdd = null;

while (listIntFunctions != null)

{

if (listIntFunctions.UninstantiatedFunctionSymbol == genericListCtorFuncSym)

{

listIntCtor = listIntFunctions;

}

if (listIntFunctions.UninstantiatedFunctionSymbol == genericListAddFuncSym)

{

listAdd = listIntFunctions;

}

listIntFunctions = listIntFunctions.NextTypeFunctionSymbol;

}

// Workaround some limitations with instantiation. We need to add the new function

// symbols into the instantiated type's scope, and mark them as user functions.

listIntCtor.IsToolGenerated = false;

listAdd.IsToolGenerated = false;

listInt32Sym.InsertInLexicalScope(listIntCtor, genericListCtorFunctionName);

listInt32Sym.InsertInLexicalScope(listAdd, genericListAddFunctionName);

// End of workaround.

Phx.IR.CallInstruction newList = Phx.IR.CallInstruction.NewExpression(functionUnit,

Phx.Common.Opcode.NewObj, listIntRefType, listIntCtor);

Phx.IR.ValueInstruction store_q = Phx.IR.ValueInstruction.NewUnary(functionUnit,

Phx.Common.Opcode.Assign,
Phx.IR.
VariableOperand.New(functionUnit, listIntType, qSymbol),

newList.DestinationOperand);

Phx.IR.CallInstruction addToList = Phx.IR.CallInstruction.New(functionUnit,

Phx.Common.Opcode.Call, listAdd);

addToList.AppendSource(Phx.IR.VariableOperand.New(functionUnit, listIntType, qSymbol));

addToList.AppendSource(Phx.IR.ImmediateOperand.New(functionUnit, typeTable.Int32Type, 5));

addInstruction.InsertAfter(newList);

newList.InsertAfter(store_q);

store_q.InsertAfter(addToList);






Re: Phoenix TypeVariable

gavelino

Hi,

How can I access a generic field For example, if the List<T> class had a generic field:

Code Block

class List<T>
{

T field1;
}








Re: Phoenix TypeVariable

Andy Ayers - MSFT

There's a problem here that is similar to the case for fields regular classes -- I don't have a full solution yet.






Re: Phoenix TypeVariable

gavelino

Ok,

IĄŻll be waiting for a solution. Please, keep me informed!!!




Re: Phoenix TypeVariable

Andy Ayers - MSFT

Look at my recent post in the Local Symbol thread; the same technique should work for generics.