本文整理汇总了C#中ILOpcode类的典型用法代码示例。如果您正苦于以下问题:C# ILOpcode类的具体用法?C# ILOpcode怎么用?C# ILOpcode使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
ILOpcode类属于命名空间,在下文中一共展示了ILOpcode类的19个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C#代码示例。
示例1: ImportBranch
private void ImportBranch(ILOpcode opcode, BasicBlock target, BasicBlock fallthrough)
{
AppendLine();
if (opcode != ILOpcode.br)
{
Append("if (");
if (opcode == ILOpcode.brfalse || opcode == ILOpcode.brtrue)
{
var op = _stack.Pop();
Append(op);
Append((opcode == ILOpcode.brtrue) ? " != 0" : " == 0");
}
else
{
var op1 = _stack.Pop();
var op2 = _stack.Pop();
// StackValueKind is carefully ordered to make this work (assuming the IL is valid)
StackValueKind kind;
if (op1.Kind > op2.Kind)
{
kind = op1.Kind;
}
else
{
kind = op2.Kind;
}
string op = null;
bool unsigned = false;
bool inverted = false;
switch (opcode)
{
case ILOpcode.beq: op = "=="; break;
case ILOpcode.bge: op = ">="; break;
case ILOpcode.bgt: op = ">"; break;
case ILOpcode.ble: op = "<="; break;
case ILOpcode.blt: op = "<"; break;
case ILOpcode.bne_un: op = "!="; break;
case ILOpcode.bge_un:
if (kind == StackValueKind.Float)
{
op = "<"; inverted = true;
}
else
{
op = ">=";
}
if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
unsigned = true;
break;
case ILOpcode.bgt_un:
if (kind == StackValueKind.Float)
{
op = "<="; inverted = true;
}
else
{
op = ">";
}
if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
unsigned = true;
break;
case ILOpcode.ble_un:
if (kind == StackValueKind.Float)
{
op = ">"; inverted = true;
}
else
{
op = "<=";
}
if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
unsigned = true;
break;
case ILOpcode.blt_un:
if (kind == StackValueKind.Float)
{
op = ">="; inverted = true;
}
else
{
op = "<";
}
if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
unsigned = true;
break;
}
if (kind == StackValueKind.ByRef)
unsigned = false;
if (inverted)
{
Append("!(");
}
if (unsigned)
{
Append("(u");
//.........这里部分代码省略.........
开发者ID:nguerrera,项目名称:corert,代码行数:101,代码来源:ILToCppImporter.cs
示例2: ImportBinaryOperation
private void ImportBinaryOperation(ILOpcode opcode)
{
var op1 = _stack.Pop();
var op2 = _stack.Pop();
// StackValueKind is carefully ordered to make this work (assuming the IL is valid)
StackValueKind kind;
TypeDesc type;
if (op1.Kind > op2.Kind)
{
kind = op1.Kind;
type = op1.Type;
}
else
{
kind = op2.Kind;
type = op2.Type;
}
// The one exception from the above rule
if ((kind == StackValueKind.ByRef) &&
(opcode == ILOpcode.sub || opcode == ILOpcode.sub_ovf || opcode == ILOpcode.sub_ovf_un))
{
kind = StackValueKind.NativeInt;
type = null;
}
PushTemp(kind, type);
string op = null;
bool unsigned = false;
switch (opcode)
{
case ILOpcode.add: op = "+"; break;
case ILOpcode.sub: op = "-"; break;
case ILOpcode.mul: op = "*"; break;
case ILOpcode.div: op = "/"; break;
case ILOpcode.div_un: op = "/"; unsigned = true; break;
case ILOpcode.rem: op = "%"; break;
case ILOpcode.rem_un: op = "%"; unsigned = true; break;
case ILOpcode.and: op = "&"; break;
case ILOpcode.or: op = "|"; break;
case ILOpcode.xor: op = "^"; break;
// TODO: Overflow checks
case ILOpcode.add_ovf: op = "+"; break;
case ILOpcode.add_ovf_un: op = "+"; unsigned = true; break;
case ILOpcode.sub_ovf: op = "-"; break;
case ILOpcode.sub_ovf_un: op = "-"; unsigned = true; break;
case ILOpcode.mul_ovf: op = "*"; break;
case ILOpcode.mul_ovf_un: op = "*"; unsigned = true; break;
default: Debug.Assert(false, "Unexpected opcode"); break;
}
if (unsigned)
{
Append("(u");
Append(GetStackValueKindCPPTypeName(kind));
Append(")");
}
Append(op2);
Append(" ");
Append(op);
Append(" ");
if (unsigned)
{
Append("(u");
Append(GetStackValueKindCPPTypeName(kind));
Append(")");
}
Append(op1);
AppendSemicolon();
}
开发者ID:nguerrera,项目名称:corert,代码行数:76,代码来源:ILToCppImporter.cs
示例3: ImportLdFtn
private void ImportLdFtn(int token, ILOpcode opCode)
{
MethodDesc method = (MethodDesc)_methodIL.GetObject(token);
if (opCode == ILOpcode.ldvirtftn)
{
if (method.IsVirtual)
throw new NotImplementedException();
}
_compilation.AddMethod(method);
PushTemp(StackValueKind.NativeInt);
Append("(intptr_t)&");
Append(_writer.GetCppTypeName(method.OwningType));
Append("::");
Append(_writer.GetCppMethodName(method));
_stack[_stackTop - 1].Value.Aux = method;
Finish();
}
开发者ID:smartmaster,项目名称:corert,代码行数:22,代码来源:ILToCppImporter.cs
示例4: ImportLdFtn
private void ImportLdFtn(int token, ILOpcode opCode)
{
MethodDesc method = (MethodDesc)_methodIL.GetObject(token);
if (opCode == ILOpcode.ldvirtftn)
{
if (method.IsVirtual)
throw new NotImplementedException();
}
AddMethodReference(method);
var entry = new LdTokenEntry<MethodDesc>(StackValueKind.NativeInt, NewTempName(), method);
PushTemp(entry);
Append("(intptr_t)&");
Append(_writer.GetCppTypeName(method.OwningType));
Append("::");
Append(_writer.GetCppMethodName(method));
AppendSemicolon();
}
开发者ID:nguerrera,项目名称:corert,代码行数:21,代码来源:ILToCppImporter.cs
示例5: ImportCasting
private void ImportCasting(ILOpcode opcode, int token)
{
TypeDesc type = (TypeDesc)_methodIL.GetObject(token);
var value = _stack.Pop();
PushTemp(StackValueKind.ObjRef, type);
AddTypeReference(type, false);
Append(opcode == ILOpcode.isinst ? "__isinst" : "__castclass");
Append("(");
Append(value);
Append(", ");
Append(_writer.GetCppTypeName(type));
Append("::__getMethodTable())");
AppendSemicolon();
}
开发者ID:nguerrera,项目名称:corert,代码行数:17,代码来源:ILToCppImporter.cs
示例6: Emit
public void Emit(ILOpcode opcode, int token)
{
Emit(opcode);
EmitUInt32(token);
}
开发者ID:niemyjski,项目名称:corert,代码行数:5,代码来源:ILEmitter.cs
示例7: Emit
public void Emit(ILOpcode opcode, ILToken token)
{
Emit(opcode);
EmitUInt32((int)token);
}
开发者ID:nguerrera,项目名称:corert,代码行数:5,代码来源:ILEmitter.cs
示例8: ImportUnaryOperation
private void ImportUnaryOperation(ILOpcode opCode)
{
var argument = _stack.Pop();
if (argument.Kind == StackValueKind.Float)
throw new NotImplementedException();
PushTemp(argument.Kind, argument.Type);
Append((opCode == ILOpcode.neg) ? "~" : "!");
Append(argument);
AppendSemicolon();
}
开发者ID:nguerrera,项目名称:corert,代码行数:14,代码来源:ILToCppImporter.cs
示例9: ImportCall
private void ImportCall(ILOpcode opcode, int token)
{
bool callViaSlot = false;
bool delegateInvoke = false;
bool callViaInterfaceDispatch = false;
DelegateCreationInfo delegateInfo = null;
MethodDesc method = (MethodDesc)_methodIL.GetObject(token);
if (method.IsIntrinsic)
{
if (ImportIntrinsicCall(method))
return;
}
TypeDesc constrained = null;
if (opcode != ILOpcode.newobj)
{
if ((_pendingPrefix & Prefix.Constrained) != 0 && opcode == ILOpcode.callvirt)
{
_pendingPrefix &= ~Prefix.Constrained;
constrained = _constrained;
bool forceUseRuntimeLookup;
MethodDesc directMethod = constrained.GetClosestDefType().TryResolveConstraintMethodApprox(method.OwningType, method, out forceUseRuntimeLookup);
if (forceUseRuntimeLookup)
throw new NotImplementedException();
if (directMethod != null)
{
method = directMethod;
opcode = ILOpcode.call;
}
else
{
// Dereference "this"
int thisPosition = _stack.Top - (method.Signature.Length + 1);
string tempName = NewTempName();
Append(GetStackValueKindCPPTypeName(StackValueKind.ObjRef));
Append(" ");
Append(tempName);
Append(" = *(");
Append(GetStackValueKindCPPTypeName(StackValueKind.ObjRef));
Append("*)");
Append(_stack[thisPosition]);
AppendSemicolon();
_stack[thisPosition] = new ExpressionEntry(StackValueKind.ObjRef, tempName);
}
}
}
TypeDesc owningType = method.OwningType;
TypeDesc retType = null;
{
if (opcode == ILOpcode.newobj)
{
retType = owningType;
if (owningType.IsString)
{
// String constructors actually look like regular method calls
method = method.GetStringInitializer();
opcode = ILOpcode.call;
}
else if (owningType.IsArray)
{
ImportNewObjArray(owningType, method);
return;
}
else if (owningType.IsDelegate)
{
delegateInfo = _compilation.GetDelegateCtor(owningType, ((LdTokenEntry<MethodDesc>)_stack.Peek()).LdToken);
method = delegateInfo.Constructor.Method;
}
}
else
if (owningType.IsDelegate)
{
if (method.Name == "Invoke")
{
opcode = ILOpcode.call;
delegateInvoke = true;
}
}
}
if (opcode == ILOpcode.callvirt)
{
// TODO: Null checks
if (method.IsVirtual)
{
// TODO: Full resolution of virtual methods
if (!method.IsNewSlot)
throw new NotImplementedException();
//.........这里部分代码省略.........
开发者ID:krytarowski,项目名称:corert,代码行数:101,代码来源:ILToCppImporter.cs
示例10: ImportUnaryOperation
private void ImportUnaryOperation(ILOpcode opCode)
{
var argument = _stack.Pop();
PushTemp(argument.Kind, argument.Type);
Debug.Assert((opCode == ILOpcode.neg) || (opCode == ILOpcode.not));
Append((opCode == ILOpcode.neg) ? "-" : "~");
Append(argument);
AppendSemicolon();
}
开发者ID:krytarowski,项目名称:corert,代码行数:12,代码来源:ILToCppImporter.cs
示例11: ImportCall
private void ImportCall(ILOpcode opcode, int token)
{
bool callViaSlot = false;
bool delegateInvoke = false;
DelegateInfo delegateInfo = null;
bool mdArrayCreate = false;
MethodDesc method = (MethodDesc)_methodIL.GetObject(token);
if (method.IsIntrinsic)
{
if (ImportIntrinsicCall(method))
return;
}
TypeDesc constrained = null;
if (opcode != ILOpcode.newobj)
{
if ((_pendingPrefix & Prefix.Constrained) != 0 && opcode == ILOpcode.callvirt)
{
_pendingPrefix &= ~Prefix.Constrained;
constrained = _constrained;
// TODO:
throw new NotImplementedException();
}
}
TypeDesc owningType = method.OwningType;
TypeDesc retType = null;
{
if (opcode == ILOpcode.newobj)
retType = owningType;
if (opcode == ILOpcode.newobj)
{
if (owningType.IsString)
{
// String constructors actually look like regular method calls
method = method.GetStringInitializer();
opcode = ILOpcode.call;
// WORKAROUND: the static method expects an extra arg
// Annoyingly, it needs to be before all the others
if (_stackTop >= _stack.Length)
Array.Resize(ref _stack, 2 * _stackTop + 3);
for (int i = _stackTop - 1; i > _stackTop - method.Signature.Length; i--)
_stack[i + 1] = _stack[i];
_stackTop++;
_stack[_stackTop - method.Signature.Length] =
new StackValue { Kind = StackValueKind.ObjRef, Value = new Value("0") };
}
else if (owningType.IsArray)
{
mdArrayCreate = true;
}
else if (owningType.IsDelegate)
{
delegateInfo = _compilation.GetDelegateCtor((MethodDesc)_stack[_stackTop - 1].Value.Aux);
method = delegateInfo.Ctor;
}
}
else
if (owningType.IsDelegate)
{
if (method.Name == "Invoke")
{
opcode = ILOpcode.call;
delegateInvoke = true;
}
}
}
if (opcode == ILOpcode.callvirt)
{
// TODO: Null checks
if (method.IsVirtual)
{
// TODO: Full resolution of virtual methods
if (!method.IsNewSlot)
throw new NotImplementedException();
// TODO: Interface calls
if (method.OwningType.IsInterface)
throw new NotImplementedException();
_dependencies.Add(_nodeFactory.VirtualMethodUse(method));
callViaSlot = true;
}
}
if (!callViaSlot && !delegateInvoke && !mdArrayCreate)
AddMethodReference(method);
if (opcode == ILOpcode.newobj)
AddTypeReference(retType, true);
//.........这里部分代码省略.........
开发者ID:Priya91,项目名称:corert,代码行数:101,代码来源:ILToCppImporter.cs
示例12: ImportShiftOperation
private void ImportShiftOperation(ILOpcode opcode)
{
var shiftAmount = _stack.Pop();
var op = _stack.Pop();
PushTemp(op.Kind, op.Type);
if (opcode == ILOpcode.shr_un)
{
Append("(u");
Append(GetStackValueKindCPPTypeName(op.Kind));
Append(")");
}
Append(op);
Append((opcode == ILOpcode.shl) ? " << " : " >> ");
Append(shiftAmount);
AppendSemicolon();
}
开发者ID:nguerrera,项目名称:corert,代码行数:20,代码来源:ILToCppImporter.cs
示例13: ImportUnaryOperation
private void ImportUnaryOperation(ILOpcode opCode)
{
var argument = Pop();
PushTemp(argument.Kind, argument.Type);
Append((opCode == ILOpcode.neg) ? "~" : "!");
Append(argument.Value.Name);
Finish();
}
开发者ID:smartmaster,项目名称:corert,代码行数:11,代码来源:ILToCppImporter.cs
示例14: ImportCompareOperation
private void ImportCompareOperation(ILOpcode opcode)
{
var op1 = _stack.Pop();
var op2 = _stack.Pop();
// StackValueKind is carefully ordered to make this work (assuming the IL is valid)
StackValueKind kind;
if (op1.Kind > op2.Kind)
{
kind = op1.Kind;
}
else
{
kind = op2.Kind;
}
PushTemp(StackValueKind.Int32);
string op = null;
bool unsigned = false;
bool inverted = false;
switch (opcode)
{
case ILOpcode.ceq: op = "=="; break;
case ILOpcode.cgt: op = ">"; break;
case ILOpcode.clt: op = "<"; break;
case ILOpcode.cgt_un:
if (kind == StackValueKind.Float)
{
op = "<="; inverted = true;
}
else
{
op = ">";
if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
unsigned = true;
}
break;
case ILOpcode.clt_un:
if (kind == StackValueKind.Float)
{
op = ">="; inverted = true;
}
else
{
op = "<";
if (kind == StackValueKind.Int32 || kind == StackValueKind.Int64)
unsigned = true;
}
break;
}
if (kind == StackValueKind.ByRef)
unsigned = false;
if (inverted)
{
Append("!(");
}
if (unsigned)
{
Append("(u");
Append(GetStackValueKindCPPTypeName(kind));
Append(")");
}
Append(op2);
Append(" ");
Append(op);
Append(" ");
if (unsigned)
{
Append("(u");
Append(GetStackValueKindCPPTypeName(kind));
Append(")");
}
Append(op1);
if (inverted)
{
Append(")");
}
AppendSemicolon();
}
开发者ID:nguerrera,项目名称:corert,代码行数:83,代码来源:ILToCppImporter.cs
示例15: ImportCasting
private void ImportCasting(ILOpcode opcode, int token)
{
TypeDesc type = (TypeDesc)_methodIL.GetObject(token);
if (type.IsInterface || type.IsArray)
throw new NotImplementedException();
var value = Pop();
PushTemp(StackValueKind.ObjRef, type);
Append(opcode == ILOpcode.isinst ? "__isinst_class" : "__castclass_class");
Append("(");
Append(value.Value.Name);
Append(", ");
Append(_writer.GetCppTypeName(type));
Append("::__getMethodTable())");
Finish();
}
开发者ID:smartmaster,项目名称:corert,代码行数:18,代码来源:ILToCppImporter.cs
示例16: ImportUnbox
private void ImportUnbox(int token, ILOpcode opCode)
{
var type = ResolveTypeToken(token);
var obj = _stack.Pop();
if (opCode == ILOpcode.unbox)
{
PushTemp(StackValueKind.ByRef, type.MakeByRefType());
}
else
{
PushTemp(GetStackValueKind(type), type);
}
if (type.IsValueType)
{
// TODO: Unbox of nullable types
if (type.IsNullable)
throw new NotImplementedException();
if (opCode == ILOpcode.unbox_any)
{
string typeName = GetStackValueKindCPPTypeName(GetStackValueKind(type), type);
Append("*(");
Append(typeName);
Append("*)");
}
Append("(");
Append(_writer.GetCppSignatureTypeName(type));
Append("*)");
Append("((void **)");
Append(obj);
Append("+1)");
}
else
{
// TODO: Cast
Append(obj);
}
AppendSemicolon();
}
开发者ID:nguerrera,项目名称:corert,代码行数:44,代码来源:ILToCppImporter.cs
示例17: ImportCall
private void ImportCall(ILOpcode opcode, int token)
{
bool callViaSlot = false;
bool delegateInvoke = false;
DelegateInfo delegateInfo = null;
bool mdArrayCreate = false;
MethodDesc method = (MethodDesc)_methodIL.GetObject(token);
var intrinsicClassification = IntrinsicMethods.GetIntrinsicMethodClassification(method);
if (intrinsicClassification != IntrinsicMethodKind.None)
{
ImportIntrinsicCall(intrinsicClassification);
return;
}
if (opcode == ILOpcode.calli)
throw new NotImplementedException();
TypeDesc constrained = null;
if (opcode != ILOpcode.newobj)
{
if ((_pendingPrefix & Prefix.Constrained) != 0 && opcode == ILOpcode.callvirt)
{
_pendingPrefix &= ~Prefix.Constrained;
constrained = _constrained;
// TODO:
throw new NotImplementedException();
}
}
TypeDesc retType = null;
{
TypeDesc owningType = method.OwningType;
if (opcode == ILOpcode.newobj)
retType = owningType;
if (opcode == ILOpcode.newobj)
{
if (owningType.IsString)
{
// String constructors actually look like regular method calls
method = IntrinsicMethods.GetStringInitializer(method);
opcode = ILOpcode.call;
// WORKAROUND: the static method expects an extra arg
// Annoyingly, it needs to be before all the others
if (_stackTop >= _stack.Length)
Array.Resize(ref _stack, 2 * _stackTop + 3);
for (int i = _stackTop - 1; i > _stackTop - method.Signature.Length; i--)
_stack[i + 1] = _stack[i];
_stackTop++;
_stack[_stackTop - method.Signature.Length] =
new StackValue { Kind = StackValueKind.ObjRef, Value = new Value("0") };
}
else if (owningType.IsArray)
{
mdArrayCreate = true;
}
else if (owningType.IsDelegate)
{
delegateInfo = _compilation.GetDelegateCtor((MethodDesc)_stack[_stackTop - 1].Value.Aux);
method = delegateInfo.Ctor;
}
}
else
if (owningType.IsDelegate)
{
if (method.Name == "Invoke")
{
opcode = ILOpcode.call;
delegateInvoke = true;
}
}
}
if (opcode == ILOpcode.callvirt)
{
// TODO: Null checks
if (method.IsVirtual)
{
// TODO: Full resolution of virtual methods
if (!method.IsNewSlot)
throw new NotImplementedException();
// TODO: Interface calls
if (method.OwningType.IsInterface)
throw new NotImplementedException();
_compilation.AddVirtualSlot(method);
callViaSlot = true;
}
}
if (!callViaSlot && !delegateInvoke && !mdArrayCreate)
_compilation.AddMethod(method);
//.........这里部分代码省略.........
开发者ID:smartmaster,项目名称:corert,代码行数:101,代码来源:ILToCppImporter.cs
示例18: ImportCall
private void ImportCall(ILOpcode opcode, int token)
{
bool callViaSlot = false;
bool delegateInvoke = false;
DelegateCreationInfo delegateInfo = null;
bool mdArrayCreate = false;
MethodDesc method = (MethodDesc)_methodIL.GetObject(token);
if (method.IsIntrinsic)
{
if (ImportIntrinsicCall(method))
return;
}
TypeDesc constrained = null;
if (opcode != ILOpcode.newobj)
{
if ((_pendingPrefix & Prefix.Constrained) != 0 && opcode == ILOpcode.callvirt)
{
_pendingPrefix &= ~Prefix.Constrained;
constrained = _constrained;
bool forceUseRuntimeLookup;
MethodDesc directMethod = constrained.GetClosestMetadataType().TryResolveConstraintMethodApprox(method.OwningType, method, out forceUseRuntimeLookup);
if (directMethod == null || forceUseRuntimeLookup)
throw new NotImplementedException();
method = directMethod;
opcode = ILOpcode.call;
}
}
TypeDesc owningType = method.OwningType;
TypeDesc retType = null;
{
if (opcode == ILOpcode.newobj)
retType = owningType;
if (opcode == ILOpcode.newobj)
{
if (owningType.IsString)
{
// String constructors actually look like regular method calls
method = method.GetStringInitializer();
opcode = ILOpcode.call;
// WORKAROUND: the static method expects an extra arg
// Annoyingly, it needs to be before all the others
_stack.InsertAt(new ExpressionEntry(StackValueKind.ObjRef, "0"), _stack.Top - method.Signature.Length + 1);
}
else if (owningType.IsArray)
{
mdArrayCreate = true;
}
else if (owningType.IsDelegate)
{
delegateInfo = _compilation.GetDelegateCtor(owningType, ((LdTokenEntry<MethodDesc>)_stack.Peek()).LdToken);
method = delegateInfo.Constructor.Method;
}
}
else
if (owningType.IsDelegate)
{
if (method.Name == "Invoke")
{
opcode = ILOpcode.call;
delegateInvoke = true;
}
}
}
if (opcode == ILOpcode.callvirt)
{
// TODO: Null checks
if (method.IsVirtual)
{
// TODO: Full resolution of virtual methods
if (!method.IsNewSlot)
throw new NotImplementedException();
// TODO: Interface calls
if (method.OwningType.IsInterface)
throw new NotImplementedException();
_dependencies.Add(_nodeFactory.VirtualMethodUse(method));
callViaSlot = true;
}
}
if (!callViaSlot && !delegateInvoke && !mdArrayCreate)
AddMethodReference(method);
if (opcode == ILOpcode.newobj)
AddTypeReference(retType, true);
//.........这里部分代码省略.........
开发者ID:nguerrera,项目名称:corert,代码行数:101,代码来源:ILToCppImporter.cs
示例19: ImportShiftOperation
void ImportShiftOperation(ILOpcode opcode)
{
var shiftAmount = Pop();
var op = Pop();
PushTemp(op.Kind, op.Type);
if (opcode == ILOpcode.shr_un)
{
Append("(u");
Append(GetStackValueKindCPPTypeName(op.Kind));
Append(")");
}
Append(op.Value.Name);
Append((opcode == ILOpcode.shl) ? "<<" : ">>");
Append(shiftAmount.Value.Name);
Finish();
}
开发者ID:niemyjski,项目名称:corert,代码行数:20,代码来源:ILToCppImporter.cs
注:本文中的ILOpcode类示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论