blob: 3bb69c402615a815962ead20fae6139db718c607 [file] [log] [blame]
//===--------------- PNetLib.cpp - PNetLib interface ----------------------===//
//
// N3
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <math.h>
#include <dlfcn.h>
#include <stdio.h>
#include "mvm/JIT.h"
#include "Assembly.h"
#include "CLIAccess.h"
#include "CLIJit.h"
#include "CLIString.h"
#include "NativeUtil.h"
#include "N3.h"
#include "PNetLib.h"
#include "Reader.h"
#include "VMArray.h"
#include "VMClass.h"
#include "VMObject.h"
#include "VMThread.h"
using namespace n3;
#define IL_CONSOLE_NORMAL 0
#define MEMBER_TYPES_CONSTRUCTOR 0x1
#define MEMBER_TYPES_EVENT 0x2
#define MEMBER_TYPES_FIELD 0x4
#define MEMBER_TYPES_METHOD 0x8
#define MEMBER_TYPES_PROPERTY 0x10
#define MEMBER_TYPES_TYPEINFO 0x20
#define MEMBER_TYPES_CUSTOM 0x40
#define MEMBER_TYPES_NESTEDTYPE 0x80
#define MEMBER_TYPES_ALL 0xBF
#define METHOD_SEMANTIC_ATTRIBUTES_SETTER 0x1
#define METHOD_SEMANTIC_ATTRIBUTES_GETTER 0x2
#define METHOD_SEMANTIC_ATTRIBUTES_OTHER 0x4
#define METHOD_SEMANTIC_ATTRIBUTES_ADDON 0x8
#define METHOD_SEMANTIC_ATTRIBUTES_REMOVEON 0x10
#define METHOD_SEMANTIC_ATTRIBUTES_FIRE 0x20
typedef uint32 (*uint32_void)(void);
typedef sint32 (*sint32_sint32)(sint32);
typedef char* (*string_void)(void);
typedef sint32 (*sint32_ptr_sint32_ptr_sint32)(uint16*, sint32, uint8*, sint32);
typedef void (*void_ptr_sint32)(void*, sint32);
typedef char (*char_sint32)(sint32);
typedef sint64 (*sint64_ptr)(void*);
typedef uint32 (*uint32_ptr_ptr_uint32)(void*, void*, uint32);
typedef sint32 (*sint32_ptr_ptr_sint32)(void*, void*, sint32);
static void* pnetLibSupport;
static void* pnetLibStdio;
static void* pnetLibTime;
static uint32_void ILGetCodePage;
static uint32_void ILGetCultureID;
static string_void ILGetCultureName;
static sint32_sint32 ILAnsiGetMaxByteCount;
static sint32_sint32 ILConsoleWriteChar;
static uint32_void ILConsoleGetMode;
static sint32_ptr_sint32_ptr_sint32 ILAnsiGetBytes;
static void_ptr_sint32 StdFlush;
static char_sint32 ILGetUnicodeCategory;
static sint64_ptr ILTimeMethodsGetCurrentTime;
static uint32_ptr_ptr_uint32 ILUnicodeStringToLower;
static sint32_ptr_ptr_sint32 ILUnicodeStringCompareIgnoreCase;
static sint32_ptr_ptr_sint32 ILUnicodeStringCompareNoIgnoreCase;
extern "C" void System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray(
VMArray* array, VMField* field) {
if (!array || !field) return;
VMClass* type = field->classDef;
VMClassArray* ts = (VMClassArray*)array->classOf;
VMCommonClass* bs = ts->baseClass;
Assembly* ass = type->assembly;
uint32 rva = ass->getRVAFromField(field->token);
Section* rsrcSection = ass->rsrcSection;
uint32 size = array->size;
uint32 offset = rsrcSection->rawAddress + (rva - rsrcSection->virtualAddress);
ArrayUInt8* bytes = ass->bytes;
if (bs == N3::pChar) {
for (uint32 i = 0; i < size; ++i) {
((uint16*)(void*)(array->elements))[i] = READ_U2(bytes, offset);
}
} else if (bs == N3::pSInt32) {
for (uint32 i = 0; i < size; ++i) {
((sint32*)(void*)(array->elements))[i] = READ_U4(bytes, offset);
}
} else if (bs == N3::pDouble) {
for (uint32 i = 0; i < size; ++i) {
((double*)(void*)(array->elements))[i] = READ_U8(bytes, offset);
}
} else {
VMThread::get()->vm->error("implement me");
}
}
extern "C" VMObject* System_Type_GetTypeFromHandle(VMCommonClass* cl) {
return cl->getClassDelegatee();
}
extern "C" void System_Threading_Monitor_Enter(VMObject* obj) {
obj->aquire();
}
extern "C" void System_Threading_Monitor_Exit(VMObject* obj) {
obj->unlock();
}
extern "C" uint32 System_Text_DefaultEncoding_InternalCodePage() {
return ILGetCodePage();
}
extern "C" VMObject* System_Reflection_Assembly_GetCallingAssembly() {
Assembly* ass = Assembly::getCallingAssembly();
assert(ass);
return ass->getAssemblyDelegatee();
}
extern "C" VMObject* System_Reflection_Assembly_GetExecutingAssembly() {
Assembly* ass = Assembly::getExecutingAssembly();
assert(ass);
return ass->getAssemblyDelegatee();
}
extern "C" uint32 System_Globalization_CultureInfo_InternalCultureID() {
return ILGetCultureID();
}
extern "C" VMObject* System_Globalization_CultureInfo_InternalCultureName() {
char* val = ILGetCultureName();
N3* vm = (N3*)(VMThread::get()->vm);
if (val) {
VMObject* ret = vm->asciizToStr(val);
free(val);
return ret;
} else {
VMObject* ret = vm->asciizToStr("iv");
return ret;
}
}
extern "C" void System_Reflection_Assembly_LoadFromFile() {
VMThread::get()->vm->error("implement me");
}
static const UTF8* newBuilder(N3* vm, CLIString* value, uint32 length) {
uint32 valueLength = value ? value->length : 0;
const UTF8* utf8 = value ? value->value : 0;
uint32 roundLength = (7 + length) & 0xfffffff8;
uint16* buf = (uint16*)alloca(roundLength * sizeof(uint16));
uint32 strLength = 0;
if (value != 0) {
if (valueLength <= roundLength) {
memcpy(buf, utf8->elements, valueLength * sizeof(uint16));
strLength = valueLength;
} else {
memcpy(buf, utf8->elements, roundLength * sizeof(uint16));
strLength = roundLength;
}
}
return vm->readerConstructUTF8(buf, strLength);
}
extern "C" VMObject* System_String_NewBuilder(CLIString* value,
uint32 length) {
N3* vm = (N3*)(VMThread::get()->vm);
CLIString* str = (CLIString*)vm->UTF8ToStr(newBuilder(vm, value, length));
return str;
}
extern "C" VMObject* Platform_SysCharInfo_GetNewLine() {
N3* vm = (N3*)(VMThread::get()->vm);
return vm->asciizToStr("\n");
}
extern "C" void System_String_CopyToChecked(CLIString* str, sint32 sstart,
ArrayUInt16* dest, sint32 dstart,
sint32 count) {
const UTF8* value = str->value;
memcpy(&dest->elements[dstart], &value->elements[sstart], count << 1);
}
extern "C" sint32 System_Text_DefaultEncoding_InternalGetMaxByteCount(sint32 val) {
return ILAnsiGetMaxByteCount(val);
}
extern "C" void Platform_Stdio_StdWrite(sint32 fd, ArrayUInt8* value,
sint32 index, sint32 count) {
if (fd == 1) {
if (ILConsoleGetMode() == IL_CONSOLE_NORMAL) {
fwrite(&value->elements[index], 1, count, stdout);
} else {
char* buf = (char*)(&value->elements[index]);
while (count > 0) {
ILConsoleWriteChar(*buf);
++buf;
--count;
}
fflush(stdout);
}
} else {
fwrite(&value->elements[index], 1, count, stderr);
}
}
extern "C" sint32 System_Text_DefaultEncoding_InternalGetBytes(ArrayUInt16* chars,
sint32 charIndex, sint32 charCount, ArrayUInt8* bytes, sint32 byteIndex) {
return ILAnsiGetBytes(&chars->elements[charIndex], charCount, &bytes->elements[byteIndex], bytes->size - byteIndex);
}
extern "C" void Platform_Stdio_StdFlush(sint32 fd) {
StdFlush(0, fd);
}
extern "C" void System_Array_InternalCopy(VMArray* src, sint32 sstart,
VMArray* dst, sint32 dstart,
sint32 len) {
N3* vm = (N3*)(VMThread::get()->vm);
verifyNull(src);
verifyNull(dst);
if (!(src->classOf->isArray && dst->classOf->isArray)) {
vm->arrayStoreException();
}
VMClassArray* ts = (VMClassArray*)src->classOf;
VMClassArray* td = (VMClassArray*)dst->classOf;
VMCommonClass* dstType = td->baseClass;
VMCommonClass* srcType = ts->baseClass;
if (len > src->size) {
vm->indexOutOfBounds(src, len);
} else if (len > dst->size) {
vm->indexOutOfBounds(dst, len);
} else if (len + sstart > src->size) {
vm->indexOutOfBounds(src, len + sstart);
} else if (len + dstart > dst->size) {
vm->indexOutOfBounds(dst, len + dstart);
} else if (dstart < 0) {
vm->indexOutOfBounds(dst, dstart);
} else if (sstart < 0) {
vm->indexOutOfBounds(src, sstart);
} else if (len < 0) {
vm->indexOutOfBounds(src, len);
}
bool doThrow = false;
if (srcType->super == N3::pValue && srcType != dstType) {
vm->arrayStoreException();
} else if (srcType->super != N3::pValue && srcType->super != N3::pEnum) {
sint32 i = sstart;
while (i < sstart + len && !doThrow) {
VMObject* cur = ((ArrayObject*)src)->at(i);
if (cur) {
if (!(cur->classOf->isAssignableFrom(dstType))) {
doThrow = true;
len = i;
}
}
++i;
}
}
uint32 size = srcType->naturalType->getPrimitiveSizeInBits() / 8;
if (size == 0) size = sizeof(void*);
void* ptrDst = (void*)((int64_t)(dst->elements) + size * dstart);
void* ptrSrc = (void*)((int64_t)(src->elements) + size * sstart);
memmove(ptrDst, ptrSrc, size * len);
if (doThrow)
vm->arrayStoreException();
}
extern "C" sint32 System_Array_GetRank(VMObject* arr) {
verifyNull(arr);
if (arr->classOf->isArray) {
return ((VMClassArray*)(arr->classOf))->dims;
} else {
VMThread::get()->vm->error("implement me");
return 0;
}
}
extern "C" sint32 System_Array_GetLength(VMObject* arr) {
verifyNull(arr);
if (arr->classOf->isArray) {
return ((VMArray*)arr)->size;
} else {
VMThread::get()->vm->error("implement me");
return 0;
}
}
extern "C" sint32 System_Array_GetLowerBound(VMObject* arr, sint32 dim) {
return 0;
}
extern "C" VMObject* System_Object_GetType(VMObject* obj) {
verifyNull(obj);
return obj->classOf->getClassDelegatee();
}
extern "C" VMObject* System_Reflection_ClrType_GetElementType(VMObject* Klass) {
VMCommonClass* cl = (VMCommonClass*)((*Klass)(N3::typeClrType).PointerVal);
if (!cl->isArray) {
VMThread::get()->vm->error("implement me");
return 0;
} else {
return ((VMClassArray*)cl)->baseClass->getClassDelegatee();
}
}
extern "C" CLIString* System_String_NewString(uint32 size) {
CLIString* str = (CLIString*)(N3::pString->doNew());
str->length = size;
return str;
}
extern "C" void System_String_Copy_3(CLIString* dest, sint32 pos,
CLIString* src) {
ArrayUInt16* arr = ArrayUInt16::acons(pos + src->value->size,
(VMClassArray*)N3::pChar);
for (sint32 i = 0; i < pos; ++i) {
arr->setAt(i, dest->value->at(i));
}
for (sint32 i = 0; i < src->length; ++i) {
arr->setAt(pos + i, src->value->at(i));
}
dest->value = ((UTF8*)arr)->extract(VMThread::get()->vm, 0, pos + src->value->size);
dest->length = dest->value->size;
}
extern "C" void System_String_Copy_5(CLIString* dest, sint32 destPos,
CLIString* src, sint32 srcPos,
sint32 length) {
const UTF8* utf8Src = src->value->extract(VMThread::get()->vm, srcPos,
srcPos + length);
if (destPos == 0) {
dest->value = utf8Src;
dest->length = dest->value->size;
} else {
const UTF8* utf8Dest = dest->value->extract(VMThread::get()->vm, 0,
destPos);
sint32 len1 = utf8Dest->size;
sint32 len2 = utf8Src->size;
uint16* buf = (uint16*)alloca((len1 + len2) * sizeof(uint16));
memcpy(buf, utf8Dest->elements, len1 * sizeof(uint16));
memcpy(buf + len1, utf8Dest->elements, len2 * sizeof(uint16));
const UTF8* utf8 = VMThread::get()->vm->readerConstructUTF8(buf,
len1 + len2);
dest->value = utf8;
dest->length = dest->value->size;
}
}
extern "C" bool System_String_Equals(CLIString* str1, CLIString* str2) {
return str1->value == str2->value;
}
extern "C" VMObject* System_Threading_Thread_InternalCurrentThread() {
return VMThread::get()->vmThread;
}
extern "C" sint32 Platform_SysCharInfo_GetUnicodeCategory(char c) {
return ILGetUnicodeCategory(c);
}
extern "C" uint16 System_String_GetChar(CLIString* str, sint32 index) {
return str->value->at(index);
}
extern "C" sint32 System_String_IndexOf(CLIString* str, uint16 value,
sint32 startIndex, sint32 count) {
if (startIndex < 0) {
VMThread::get()->vm->error("shoud throw arg range");
}
if ((count < 0) || (str->length - startIndex < count)) {
VMThread::get()->vm->error("shoud throw arg range");
}
sint32 i = startIndex;
const UTF8* utf8 = str->value;
while (i < startIndex + count) {
if (utf8->at(i) == value) return i;
else ++i;
}
return -1;
}
extern "C" sint32 System_String_GetHashCode(CLIString* str) {
sint32 hash = 0;
const UTF8* utf8 = str->value;
for (sint32 i = 0; i < utf8->size; ++i) {
hash += ((hash << 5) + utf8->elements[i]);
}
return hash;
}
extern "C" double System_Decimal_ToDouble(void* ptr) {
VMThread::get()->vm->error("implement me");
return 0.0;
}
extern "C" double System_Math_Log10(double val) {
return log10(val);
}
extern "C" double System_Math_Floor(double val) {
return floor(val);
}
extern "C" VMObject* System_Text_StringBuilder_Insert_System_Text_StringBuilder_System_Int32_System_Char(
StringBuilder* obj,
sint32 index,
uint16 value) {
N3* vm = (N3*)(VMThread::get()->vm);
CLIString* buildString = obj->buildString;
const UTF8* utf8 = buildString->value;
sint32 strLength = buildString->length;
sint32 length = (index + 1) > strLength ? index + 1 : strLength + 1;
uint16* buf = (uint16*)alloca(length * sizeof(uint16));
if (index != 0) {
memcpy(buf, utf8->elements, index * sizeof(uint16));
}
if (strLength > index) {
memcpy(&(buf[index + 1]), &(utf8->elements[index]),
(strLength - index) * sizeof(uint16));
}
buf[index] = value;
CLIString* str = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, length));
obj->buildString = str;
return obj;
}
extern "C" VMObject* System_Text_StringBuilder_Insert_System_Text_StringBuilder_System_Int32_System_String(
StringBuilder* obj,
sint32 index,
CLIString* str) {
N3* vm = (N3*)(VMThread::get()->vm);
CLIString* buildString = obj->buildString;
const UTF8* strUtf8 = str->value;
const UTF8* buildUtf8 = buildString->value;
sint32 strLength = str->length;
sint32 buildLength = buildString->length;
sint32 length = strLength + buildLength;
uint16* buf = (uint16*)alloca(length * sizeof(uint16));
if (index != 0) {
memcpy(buf, buildUtf8->elements, index * sizeof(uint16));
}
if (strLength != 0) {
memcpy(&(buf[index]), strUtf8->elements, strLength * sizeof(uint16));
}
if (buildLength - index > 0) {
memcpy(&(buf[strLength + index]), &(buildUtf8->elements[index]),
(buildLength - index) * sizeof(uint16));
}
CLIString* val = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, length));
obj->buildString = val;
return obj;
}
extern "C" VMObject* System_Text_StringBuilder_Append_System_Text_StringBuilder_System_Char(
StringBuilder* obj,
uint16 value) {
N3* vm = (N3*)(VMThread::get()->vm);
CLIString* buildString = obj->buildString;
const UTF8* utf8 = buildString->value;
sint32 length = buildString->length;
uint16* buf = (uint16*)alloca((length + 1) * sizeof(uint16));
memcpy(buf, utf8->elements, length * sizeof(uint16));
buf[length] = value;
CLIString* val = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, length + 1));
obj->buildString = val;
return obj;
}
extern "C" VMObject* System_Text_StringBuilder_Append_System_Text_StringBuilder_System_String(
StringBuilder* obj,
CLIString* str) {
N3* vm = (N3*)(VMThread::get()->vm);
CLIString* buildString = obj->buildString;
const UTF8* buildUtf8 = buildString->value;
const UTF8* strUtf8 = str->value;
sint32 buildLength = buildString->length;
sint32 strLength = str->length;
sint32 length = buildLength + strLength;
uint16* buf = (uint16*)alloca(length * sizeof(uint16));
memcpy(buf, buildUtf8->elements, buildLength * sizeof(uint16));
memcpy(&(buf[buildLength]), strUtf8->elements, strLength * sizeof(uint16));
CLIString* val = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, length));
obj->buildString = val;
return obj;
}
extern "C" sint32 System_String_FindInRange(CLIString* obj, sint32 srcFirst,
sint32 srcLast, sint32 step,
CLIString* dest) {
uint16* buf1 = (uint16*)&(obj->value->elements[srcFirst]);
uint16* buf2 = (uint16*)(dest->value->elements);
sint32 destLength = dest->length;
sint32 size = destLength * sizeof(uint16);
if (step > 0) {
if (destLength == 1) {
while (srcFirst <= srcLast) {
if (buf1[0] == buf2[0]) {
return srcFirst;
} else {
buf1 = &(buf1[1]);
++srcFirst;
}
}
} else {
while (srcFirst <= srcLast) {
if ((buf1[0] == buf2[0]) && !memcmp(buf1, buf2, size)) {
return srcFirst;
} else {
buf1 = &(buf1[1]);
++srcFirst;
}
}
}
} else {
if (destLength == 1) {
while (srcFirst >= srcLast) {
if (buf1[0] == buf2[0]) {
return srcFirst;
} else {
buf1 = buf1 - 1;
--srcFirst;
}
}
} else {
while (srcFirst >= srcLast) {
if ((buf1[0] == buf2[0]) && !memcmp(buf1, buf2, size)) {
return srcFirst;
} else {
buf1 = buf1 - 1;
--srcFirst;
}
}
}
}
return -1;
}
extern "C" VMObject* System_Reflection_Assembly_LoadFromName(CLIString* str, sint32 & error, VMObject* parent) {
N3* vm = (N3*)(VMThread::get()->vm);
Assembly* ass = vm->loadAssembly(str->value, "dll");
if (!ass) vm->error("unfound assembly %s\n", str->value->printString());
error = 0;
return ass->getAssemblyDelegatee();
}
extern "C" CLIString* System_String_Concat_2(CLIString* str1, CLIString* str2) {
N3* vm = (N3*)(VMThread::get()->vm);
const UTF8* u1 = str1->value;
const UTF8* u2 = str2->value;
sint32 len1 = str1->length;
sint32 len2 = str2->length;
uint16* buf = (uint16*)alloca((len1 + len2) * sizeof(uint16));
memcpy(buf, u1->elements, len1 * sizeof(uint16));
memcpy(&(buf[len1]), u2->elements, len2 * sizeof(uint16));
CLIString* val = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, len1 + len2));
return val;
}
extern "C" CLIString* System_String_Concat_3(CLIString* str1, CLIString* str2, CLIString* str3) {
N3* vm = (N3*)(VMThread::get()->vm);
const UTF8* u1 = str1->value;
const UTF8* u2 = str2->value;
const UTF8* u3 = str3->value;
sint32 len1 = str1->length;
sint32 len2 = str2->length;
sint32 len3 = str3->length;
uint16* buf = (uint16*)alloca((len1 + len2 + len3) * sizeof(uint16));
memcpy(buf, u1->elements, len1 * sizeof(uint16));
memcpy(&(buf[len1]), u2->elements, len2 * sizeof(uint16));
memcpy(&(buf[len1 + len2]), u3->elements, len3 * sizeof(uint16));
CLIString* val = (CLIString*)vm->UTF8ToStr(vm->readerConstructUTF8(buf, len1 + len2 + len3));
return val;
}
extern "C" void System_String_RemoveSpace(CLIString* str, sint32 index, sint32 length) {
const UTF8* utf8 = str->value;
sint32 strLength = str->length;
uint16* buf = (uint16*)alloca(strLength * sizeof(uint16));
sint32 j = index;
if (index != 0) {
memcpy(buf, utf8->elements, index * sizeof(uint16));
}
// 32 is space
for (sint32 i = 0; i < length; ++i) {
uint16 cur = utf8->elements[index + i];
if (cur != 32) {
buf[j] = cur;
} else {
++j;
}
}
if (strLength > (index + length)) {
memcpy(&(buf[j]), &(utf8->elements[index + length]), (strLength - (index + length)) * sizeof(uint16));
}
const UTF8* res = VMThread::get()->vm->readerConstructUTF8(buf, j);
str->value = res;
str->length = j;
}
extern "C" void System_String__ctor_3(CLIString* str, uint16 ch, sint32 count) {
ArrayUInt16* array = ArrayUInt16::acons(count, N3::arrayChar);
for (sint32 i = 0; i < count; ++i) {
array->elements[i] = ch;
}
const UTF8* utf8 = VMThread::get()->vm->readerConstructUTF8(array->elements, array->size);
str->value = utf8;
str->length = array->size;
str->capacity = array->size;
}
extern "C" int64_t Platform_TimeMethods_GetCurrentTime() {
return ILTimeMethodsGetCurrentTime(0);
}
#define ASSEMBLY_VALUE(obj) ((Assembly**)obj)[3]
extern "C" VMObject* System_Reflection_Assembly_GetType(VMObject* obj, CLIString* str, bool onError, bool ignoreCase) {
Assembly* ass = ASSEMBLY_VALUE(obj);
const UTF8* utf8 = str->value;
char* asciiz = utf8->UTF8ToAsciiz();
char* index = (char*)memrchr(asciiz, '.', strlen(asciiz));
N3* vm = ass->vm;
index[0] = 0;
++index;
VMCommonClass* cl = ass->loadTypeFromName(vm->asciizConstructUTF8(index), vm->asciizConstructUTF8(asciiz), true, true, true, onError);
if (!cl) VMThread::get()->vm->error("implement me");
return cl->getClassDelegatee();
}
static bool parameterMatch(std::vector<VMCommonClass*> params, ArrayObject* types, bool virt) {
uint32 v = virt ? 1 : 0;
if (types->size + v + 1 != params.size()) return false;
for (sint32 i = 0; i < types->size; ++i) {
VMCommonClass* cur = (VMCommonClass*)(*N3::typeClrType)(types->elements[i]).PointerVal;
if (cur != params[i + 1 + v]) return false;
}
return true;
}
extern "C" VMObject* System_Reflection_ClrType_GetMemberImpl(VMObject* Type, CLIString* str, sint32 memberTypes, sint32 bindingFlags, VMObject* binder,
sint32 callingConventions, ArrayObject* types, VMObject* modifiers) {
VMCommonClass* type = (VMCommonClass*)((*N3::typeClrType)(Type).PointerVal);
const UTF8* name = str->value;
if (memberTypes == MEMBER_TYPES_PROPERTY) {
std::vector<Property*> properties = type->properties;
Property *res = 0;
for (std::vector<Property*>::iterator i = properties.begin(),
e = properties.end(); i!= e; ++i) {
if ((*i)->name == name) {
res = *i;
break;
}
}
if (res == 0) VMThread::get()->vm->error("implement me");
return res->getPropertyDelegatee();
} else if (memberTypes == MEMBER_TYPES_METHOD) {
std::vector<VMMethod*> virtualMethods = type->virtualMethods;
std::vector<VMMethod*> staticMethods = type->staticMethods;
for (std::vector<VMMethod*>::iterator i = virtualMethods.begin(),
e = virtualMethods.end(); i!= e; ++i) {
VMMethod* meth = *i;
if (meth->name == name) {
if (parameterMatch(meth->parameters, types, true)) {
return meth->getMethodDelegatee();
}
}
}
for (std::vector<VMMethod*>::iterator i = staticMethods.begin(),
e = staticMethods.end(); i!= e; ++i) {
VMMethod* meth = *i;
if (meth->name == name) {
if (parameterMatch(meth->parameters, types, false)) {
return meth->getMethodDelegatee();
}
}
}
} else {
VMThread::get()->vm->error("implement me");
}
return 0;
}
extern "C" VMObject* System_Reflection_ClrHelpers_GetSemantics(mvm::Object* item, uint32 attributes, bool nonPublic) {
if (item->getVirtualTable() == Property::VT) {
Property* prop = (Property*)item;
if (attributes == METHOD_SEMANTIC_ATTRIBUTES_GETTER) {
char* asciiz = prop->name->UTF8ToAsciiz();
char* buf = (char*)alloca(strlen(asciiz) + 5);
sprintf(buf, "get_%s", asciiz);
VirtualMachine* vm = VMThread::get()->vm;
VMMethod* meth = prop->type->lookupMethod(vm->asciizConstructUTF8(buf), prop->parameters, true, false);
assert(meth);
return meth->getMethodDelegatee();
}
} else {
VMThread::get()->vm->error("implement me");
}
return 0;
}
static void decapsulePrimitive(VMObject* arg, const llvm::Type* type, std::vector<llvm::GenericValue>& args) {
if (type == llvm::Type::Int1Ty) {
llvm::GenericValue gv;
gv.IntVal = llvm::APInt(1, (bool)((uint32*)arg)[VALUE_OFFSET]);
args.push_back(gv);
} else if (type == llvm::Type::Int8Ty) {
llvm::GenericValue gv;
gv.IntVal = llvm::APInt(8, (uint8)((uint32*)arg)[VALUE_OFFSET]);
args.push_back(gv);
} else if (type == llvm::Type::Int16Ty) {
llvm::GenericValue gv;
gv.IntVal = llvm::APInt(16, (uint16)((uint32*)arg)[VALUE_OFFSET]);
args.push_back(gv);
} else if (type == llvm::Type::Int32Ty) {
llvm::GenericValue gv;
gv.IntVal = llvm::APInt(32, (uint32)((uint32*)arg)[VALUE_OFFSET]);
args.push_back(gv);
} else if (type == llvm::Type::Int64Ty) {
llvm::GenericValue gv;
uint32* ptr = &((uint32*)arg)[VALUE_OFFSET];
gv.IntVal = llvm::APInt(64, ((uint64*)ptr)[0]);
args.push_back(gv);
} else if (type == llvm::Type::FloatTy) {
llvm::GenericValue gv;
float* ptr = &((float*)arg)[VALUE_OFFSET];
gv.FloatVal = ((float*)ptr)[0];
args.push_back(gv);
} else if (type == llvm::Type::DoubleTy) {
llvm::GenericValue gv;
uint32* ptr = &((uint32*)arg)[VALUE_OFFSET];
gv.DoubleVal = ((double*)ptr)[0];
args.push_back(gv);
} else if (type == llvm::PointerType::getUnqual(llvm::Type::Int8Ty)) {
llvm::GenericValue gv(((void**)arg)[VALUE_OFFSET]);
args.push_back(gv);
} else {
VMThread::get()->vm->error("implement me");
}
}
extern "C" VMObject* System_Reflection_ClrMethod_Invoke(VMObject* Method, VMObject* obj, sint32 invokeAttr, VMObject* binder, ArrayObject* args, VMObject* culture) {
VMMethod* meth = (VMMethod*)(*N3::methodMethodType)(Method).PointerVal;
meth->getSignature();
meth->compiledPtr();
llvm::Function* func = CLIJit::compile(meth->classDef, meth);
VMClass* type = meth->classDef;
type->resolveStatic(true);
uint32 virt = meth->virt;
if ((obj != 0) && virt) {
if (!(obj->classOf->isAssignableFrom(type))) {
VMThread::get()->vm->illegalArgumentException(meth->name->printString());
}
verifyNull(obj);
}
std::vector<llvm::GenericValue> gvargs;
uint32 index = 0;
llvm::Function::arg_iterator i = func->arg_begin();
llvm::Function::arg_iterator e = func->arg_end();
if (virt) {
llvm::GenericValue gv(obj);
gvargs.push_back(gv);
++i;
}
for ( ;i != e; ++i, ++index) {
const llvm::Type* type = i->getType();
if (llvm::isa<llvm::PointerType>(type) && type != llvm::PointerType::getUnqual(llvm::Type::Int8Ty)) {
llvm::GenericValue gv(args->elements[index]);
gvargs.push_back(gv);
} else {
decapsulePrimitive(args->elements[index], type, gvargs);
}
}
llvm::GenericValue gv;
try{
gv = (*meth)(gvargs);
}catch(...) {
assert(0);
}
VMObject* res = 0;
VMCommonClass* retType = meth->parameters[0];
if (retType == N3::pVoid) {
res = (*N3::pVoid)();
} else if (retType == N3::pBoolean) {
res = (*N3::pBoolean)();
(*N3::ctorBoolean)(res, gv.IntVal.getBoolValue());
} else if (retType == N3::pUInt8) {
res = (*N3::pUInt8)();
(*N3::ctorUInt8)(res, (uint8)gv.IntVal.getZExtValue());
} else if (retType == N3::pSInt8) {
res = (*N3::pSInt8)();
(*N3::ctorSInt8)(res, (uint8)gv.IntVal.getSExtValue());
} else if (retType == N3::pChar) {
res = (*N3::pChar)();
(*N3::ctorChar)(res, (uint16)gv.IntVal.getZExtValue());
} else if (retType == N3::pSInt16) {
res = (*N3::pSInt16)();
(*N3::ctorSInt16)(res, (sint16)gv.IntVal.getSExtValue());
} else if (retType == N3::pUInt16) {
res = (*N3::pUInt16)();
(*N3::ctorUInt16)(res, (uint16)gv.IntVal.getZExtValue());
} else if (retType == N3::pSInt32) {
res = (*N3::pSInt32)();
(*N3::ctorSInt32)(res, (sint32)gv.IntVal.getSExtValue());
} else if (retType == N3::pUInt32) {
res = (*N3::pUInt32)();
(*N3::ctorUInt32)(res, (sint32)gv.IntVal.getZExtValue());
} else if (retType == N3::pSInt64) {
res = (*N3::pSInt64)();
(*N3::ctorSInt64)(res, (sint64)gv.IntVal.getSExtValue());
} else if (retType == N3::pUInt64) {
res = (*N3::pUInt64)();
(*N3::ctorUInt64)(res, (sint64)gv.IntVal.getZExtValue());
} else if (retType == N3::pIntPtr) {
res = (*N3::pIntPtr)();
(*N3::ctorIntPtr)(res, (void*)gv.IntVal.getSExtValue());
} else if (retType == N3::pUIntPtr) {
res = (*N3::pUIntPtr)();
(*N3::ctorUIntPtr)(res, (void*)gv.IntVal.getZExtValue());
} else if (retType == N3::pFloat) {
res = (*N3::pFloat)();
(*N3::ctorFloat)(res, gv.FloatVal);
} else if (retType == N3::pDouble) {
res = (*N3::pDouble)();
(*N3::ctorDouble)(res, gv.DoubleVal);
} else {
if (retType->super == N3::pValue || retType->super == N3::pEnum)
VMThread::get()->vm->error("implement me");
res = (VMObject*)gv.PointerVal;
}
return res;
}
static VMObject* createResourceStream(Assembly* ass, sint32 posn) {
uint32 resSize = ass->resSize;
uint32 resRva = ass->resRva;
Section* textSection = ass->textSection;
uint32 sectionLen = resSize;
uint32 section = 0;
uint32 start = 0;
uint32 length = 0;
uint32 pad = 0;
Reader* reader = Reader::allocateReader(ass->bytes);
section = textSection->rawAddress + (resRva - textSection->virtualAddress);
reader->seek(section, Reader::SeekSet);
while (posn > 0) {
if (sectionLen < 4) return 0;
length = reader->readU4();
if (length > (sectionLen - 4)) return 0;
if ((length % 4) != 0) {
pad = 4 - (length % 4);
} else {
pad = 0;
}
start = start + length + pad + 4;
section = section + length + pad + 4;
reader->seek(section + length + pad + 4, Reader::SeekSet);
sectionLen = sectionLen - (length + pad + 4);
posn = posn - 1;
}
start = start + 4;
if (sectionLen < 4) return 0;
length = reader->readU4();
if (length > (sectionLen - 4)) return 0;
VMObject* res = (*N3::resourceStreamType)();
(*N3::ctorResourceStreamType)(res, ass, (uint64)start, (uint64)length);
return res;
}
extern "C" VMObject* System_Reflection_Assembly_GetManifestResourceStream(VMObject* Ass, CLIString* str) {
Assembly* ass = (Assembly*)(*N3::assemblyAssemblyReflection)(Ass).PointerVal;
const UTF8* utf8 = str->value;
Header* header = ass->CLIHeader;
uint32 stringOffset = header->stringStream->realOffset;
Table* manTable = header->tables[CONSTANT_ManifestResource];
uint32 manRows = manTable->rowsNumber;
sint32 pos = -1;
uint32 i = 0;
VirtualMachine* vm = VMThread::get()->vm;
while ((pos == -1) && (i < manRows)) {
uint32 nameOffset = manTable->readIndexInRow(i + 1, CONSTANT_MANIFEST_RESOURCE_NAME, ass->bytes);
const UTF8* name = ass->readString(vm, stringOffset + nameOffset);
if (name == utf8) {
pos = i;
} else {
++i;
}
}
if (pos != -1) {
return createResourceStream(ass, pos);
} else {
return 0;
}
}
extern "C" ArrayObject* System_Reflection_ClrHelpers_GetCustomAttributes(Assembly* ass, VMCommonClass* clrTypePrivate, bool inherit) {
return ass->getCustomAttributes(clrTypePrivate->token, clrTypePrivate);
}
extern "C" VMObject* System_Globalization_TextInfo_ToLower(VMObject* obj, CLIString* str) {
verifyNull(str);
const UTF8* utf8 = str->value;
uint32 length = str->length;
uint16* buf = (uint16*)alloca(length * sizeof(uint16));
VirtualMachine* vm = VMThread::get()->vm;
memcpy(buf, utf8->elements, length * sizeof(uint16));
ILUnicodeStringToLower((void*)buf, (void*)utf8->elements, length);
const UTF8* res = vm->readerConstructUTF8(buf, length);
return ((N3*)vm)->UTF8ToStr(res);
}
extern "C" VMObject* System_String_Replace(CLIString* str, uint16 c1, uint16 c2) {
const UTF8* utf8 = str->value;
uint32 length = str->length;
if ((c1 == c2) || length == 0) return str;
uint16* buf = (uint16*)alloca(length * sizeof(uint16));
memcpy(buf, utf8->elements, length * sizeof(uint16));
for (uint32 i = 0; i < length; ++i) {
if (buf[i] == c1) buf[i] = c2;
}
N3* vm = (N3*)VMThread::get()->vm;
const UTF8* res = vm->readerConstructUTF8(buf, length);
return vm->UTF8ToStr(res);
}
// LLVM Bug
#if defined (__PPC__) && !defined (__MACH__)
extern "C" uint32 System_Reflection_ClrResourceStream_ResourceRead(Assembly* assembly, uint32 position1, uint32 position2, ArrayUInt8* buffer, uint32 offset, uint32 count) {
uint64 position = position1 << 32 + position2;
#else
extern "C" uint32 System_Reflection_ClrResourceStream_ResourceRead(Assembly* assembly, uint64 position, ArrayUInt8* buffer, uint32 offset, uint32 count) {
#endif
uint32 resRva = assembly->resRva;
ArrayUInt8* bytes = assembly->bytes;
Section* textSection = assembly->textSection;
uint32 section = 0;
section = textSection->rawAddress + (resRva - textSection->virtualAddress);
memcpy(&(buffer->elements[offset]), &(bytes->elements[section + position]), count);
return count;
}
extern "C" sint32 System_String_CompareInternal(CLIString* strA, sint32 indexA, sint32 lengthA, CLIString* strB, sint32 indexB, sint32 lengthB, bool ignoreCase) {
if (strA == 0) {
if (strB == 0) {
return 0;
}
return -1;
} else if (strB == 0) {
return 1;
} else {
sint32 cmp = 0;
if (lengthA >= lengthB) {
if (ignoreCase) {
cmp = ILUnicodeStringCompareIgnoreCase((void*)&(strA->value->elements[indexA]), (void*)&(strB->value->elements[indexB]), lengthB);
} else {
cmp = ILUnicodeStringCompareNoIgnoreCase((void*)&(strA->value->elements[indexA]), (void*)&(strB->value->elements[indexB]), lengthB);
}
if (cmp != 0) return cmp;
else if (lengthA > lengthB) return 1;
else return 0;
} else {
if (ignoreCase) {
cmp = ILUnicodeStringCompareIgnoreCase((void*)&(strA->value->elements[indexA]), (void*)&(strB->value->elements[indexB]), lengthA);
} else {
cmp = ILUnicodeStringCompareNoIgnoreCase((void*)&(strA->value->elements[indexA]), (void*)&(strB->value->elements[indexB]), lengthA);
}
if (cmp != 0) return cmp;
else return -1;
}
}
}
extern "C" void System_String_CharFill(CLIString* str, sint32 start, sint32 count, char ch) {
const UTF8* utf8 = str->value;
sint32 length = start + count;
uint16* buf = (uint16*)alloca(length * sizeof(uint16));
memcpy(buf, utf8->elements, start * sizeof(uint16));
for (sint32 i = 0; i < count; ++i) {
buf[i + start] = ch;
}
VirtualMachine* vm = VMThread::get()->vm;
const UTF8* val = vm->readerConstructUTF8(buf, length);
str->value = val;
str->length = length;
}
extern "C" sint32 System_String_InternalOrdinal(CLIString *strA, sint32 indexA, sint32 lengthA,
CLIString *strB, sint32 indexB, sint32 lengthB) {
const uint16 *bufA;
const uint16 *bufB;
/* Handle the easy cases first */
if(!strA)
{
if(!strB)
{
return 0;
}
else
{
return -1;
}
}
else if(!strB)
{
return 1;
}
/* Compare the two strings */
bufA = &(strA->value->elements[indexA]);
bufB = &(strB->value->elements[indexB]);
while(lengthA > 0 && lengthB > 0)
{
if(*bufA < *bufB)
{
return -1;
}
else if(*bufA > *bufB)
{
return 1;
}
++bufA;
++bufB;
--lengthA;
--lengthB;
}
/* Determine the ordering based on the tail sections */
if(lengthA > 0)
{
return 1;
}
else if(lengthB > 0)
{
return -1;
}
else
{
return 0;
}
}
extern "C" void System_GC_Collect() {
gc::collect();
}
void NativeUtil::initialise() {
void* p;
p = (void*)&System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray;
p = (void*)&System_Type_GetTypeFromHandle;
pnetLibSupport = dlopen("libILSupport.so", RTLD_LAZY | RTLD_GLOBAL);
if (!pnetLibSupport) {
printf("error = %s\n", dlerror());
}
pnetLibStdio = dlopen("libStdio.so", RTLD_LAZY | RTLD_GLOBAL);
pnetLibTime = dlopen("libTime.so", RTLD_LAZY | RTLD_GLOBAL);
ILGetCodePage = (uint32_void)dlsym(pnetLibSupport, "ILGetCodePage");
assert(ILGetCodePage);
ILGetCultureID = (uint32_void)dlsym(pnetLibSupport, "ILGetCultureID");
assert(ILGetCultureID);
ILGetCultureName = (string_void)dlsym(pnetLibSupport, "ILGetCultureName");
assert(ILGetCultureName);
ILAnsiGetMaxByteCount = (sint32_sint32)dlsym(pnetLibSupport, "ILAnsiGetMaxByteCount");
assert(ILAnsiGetMaxByteCount);
ILConsoleGetMode = (uint32_void)dlsym(pnetLibSupport, "ILConsoleGetMode");
assert(ILConsoleGetMode);
ILConsoleWriteChar = (sint32_sint32)dlsym(pnetLibSupport, "ILConsoleWriteChar");
assert(ILConsoleWriteChar);
ILUnicodeStringToLower = (uint32_ptr_ptr_uint32)dlsym(pnetLibSupport, "ILUnicodeStringToLower");
assert(ILUnicodeStringToLower);
ILAnsiGetBytes = (sint32_ptr_sint32_ptr_sint32)dlsym(pnetLibSupport, "ILAnsiGetBytes");
assert(ILAnsiGetBytes);
StdFlush = (void_ptr_sint32)dlsym(pnetLibStdio, "_IL_Stdio_StdFlush");
assert(StdFlush);
ILGetUnicodeCategory = (char_sint32)dlsym(pnetLibSupport, "ILGetUnicodeCategory");
assert(ILGetUnicodeCategory);
ILTimeMethodsGetCurrentTime = (sint64_ptr)dlsym(pnetLibTime, "_IL_TimeMethods_GetCurrentTime");
ILUnicodeStringCompareIgnoreCase = (sint32_ptr_ptr_sint32)dlsym(pnetLibSupport, "ILUnicodeStringCompareIgnoreCase");
ILUnicodeStringCompareNoIgnoreCase = (sint32_ptr_ptr_sint32)dlsym(pnetLibSupport, "ILUnicodeStringCompareNoIgnoreCase");
assert(ILUnicodeStringCompareIgnoreCase);
assert(ILUnicodeStringCompareNoIgnoreCase);
}