Jump to content
  • Advertisement

Miss

Member
  • Content count

    73
  • Joined

  • Last visited

Community Reputation

175 Neutral

About Miss

  • Rank
    Member

Personal Information

Social

  • Twitter
    codecatt
  • Github
    codecat

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Thank you, I'll experiment with this.
  2. Hmm, the problem with the #pragma approach is that if you have multiple modules, registering a function will be available to each module rather than only 1 module. Is there anything that can be done about that?
  3. Miss

    MSVC optimization bug?

    Okay, so Microsoft reported back to me (very quickly!), saying they've filed this bug and that they're working on it. As a workaround, there's 2 possibilities, either using #pragma optimize("", off) on CallGlobalFunction, or - which I think makes more sense since this bug might cause problems elsewhere in Angelscript - is to use a new undocumented (and completely unsupported) compiler flag /d2SSAOptimizerCFG- which "turns off all of our new control-flow-graph (CFG) based optimizations for the compilation, of which the erroneous optimization is a part". It's not recommended to use this compiler flag though, as it's completely unsupported and might disappear in the future, but if anyone is looking for a critical fix for this problem for the time being, it's probably a nice temporary solution. PS: Sorry for the triple post, but I figured it's fine since these are sequential updates..
  4. Miss

    MSVC optimization bug?

    Okay, I've narrowed it down a bit. This is caused by the latest Visual Studio 15.7.1 update, and this is isolated reproduction code: https://pastebin.com/nGW11NAx It will run on a debug build, but crash on a release build (it jumps to 0x1337 at the end of main() because the stack isn't cleaned up). I've sent a bugreport to Microsoft regarding this issue.
  5. Miss

    MSVC optimization bug?

    So did you reproduce it as well? Edit: Here's the reproduce steps that work for me. https://gist.github.com/codecat/9128e290b7f3fc74374a3035ff79e9af
  6. Miss

    Exposing a Point class to Angelscript

    I mean instead of doing: Point &opAssign(const int, const int) You should do this instead: Point &opAssign(const Point &in)
  7. Miss

    Exposing a Point class to Angelscript

    Yes, you're going about this the wrong way. Your opAssign() method needs to be passed a "const Point &in" instead of 2 integers, since that's what you're setting it to in your script.
  8. Miss

    MSVC optimization bug?

    Sorry, you're right, it is indeed cleaning the stack there, but at that point it's already too late. I should've added the code that is being returned to as well in my post. Here's the disassembly right after CallGlobalFunction, where it's using esi as thisptr (popped from the stack before the stack is cleaned up): 03EC65B1 E8 CA 73 00 00 call asCScriptEngine::CallGlobalFunction (03ECD980h) preMessage.isSet = false; 03EC65B6 8B 45 08 mov eax,dword ptr [section] 03EC65B9 C6 86 BC 0B 00 00 00 mov byte ptr [esi+0BBCh],0 Basically, I think msvc is confusing the stdcall code with the cdecl code in the optimization. If there's an "add esp, 8" above "pop esi", everything would be fine. For reference, at the time of "pop esi", this is what the stack looks like: $ param1 $+04 param2 $+08 esi (thisptr)
  9. Miss

    MSVC optimization bug?

    Not sure if this is an Angelscript bug or somehow an MSVC bug. I'm compiling Angelscript 2.23.0 on 32 bit in release build using platform toolset v141 and SDK 8.1, 10.0.x.0 (I've tried 8.1, 10.0.16299.0, and 10.0.17134.0) Though it's quite strange, because this only started happening on 1 project after the most recent Visual Studio 2017 update. (It seems to be fine in another project, which is using the 8.1 SDK, but that project is also a custom build from GENie, this project is built from the msvc2015 folder that comes with Angelscript itself.) The problem I'm seeing comes from the script engine message callback. I'm registering it like this, as a CDECL call: int r = 0; m_engine->SetMessageCallback(asFUNCTION(ScriptMessageCallback), nullptr, asCALL_CDECL); assert(r >= 0); And the actual function is empty: (actually commented out just to test this problem) static void ScriptMessageCallback(const asSMessageInfo *msg, void *param) { } Which results in a single "ret" instruction in memory. This makes sense, it's a cdecl call, so the caller does the cleanup. So, this function is eventually called on some script error. The actual call to the function is in "asCScriptEngine::CallGlobalFunction". In the debug version of Angelscript, the assembly is fine: 03F22B9F 8B 45 0C mov eax,dword ptr [param2] 03F22BA2 50 push eax 03F22BA3 8B 4D 08 mov ecx,dword ptr [param1] 03F22BA6 51 push ecx 03F22BA7 FF 55 F0 call dword ptr [ebp-10h] 03F22BAA 83 C4 08 add esp,8 In the release build it works a little different, it sets up the call and calls the function, but it doesn't clean up the stack: 0400C461 56 push esi 0400C462 8B 30 mov esi,dword ptr [eax] 0400C464 83 FA 02 cmp edx,2 0400C467 74 5F je asCScriptEngine::CallGlobalFunction+88h (0400C4C8h) ... 0400C4C8 FF 75 0C push dword ptr [param2] 0400C4CB FF 75 08 push dword ptr [param1] 0400C4CE FF D6 call esi 0400C4D0 8B 4D F4 mov ecx,dword ptr [ebp-0Ch] 0400C4D3 64 89 0D 00 00 00 00 mov dword ptr fs:[0],ecx 0400C4DA 5E pop esi 0400C4DB 8B E5 mov esp,ebp 0400C4DD 5D pop ebp 0400C4DE C2 10 00 ret 10h Note that "esi" on the first instruction above is the thisptr, and is how the caller eventually picks up thisptr again. Since the stack is not cleaned up (before esi is restored at "pop esi"), esi actually ends up being param1. Even if I explicitly write the function pointer as __cdecl, it doesn't clean up the stack in time: (results in the same assembly) typedef void (__cdecl *func_t)(void *, void *); func_t f = (func_t)(i->func); f(param1, param2); For reference, here's the CallGlobalFunction C++ code directly from Angelscript: void asCScriptEngine::CallGlobalFunction(void *param1, void *param2, asSSystemFunctionInterface *i, asCScriptFunction *s) const { if( i->callConv == ICC_CDECL ) { void (*f)(void *, void *) = (void (*)(void *, void *))(i->func); f(param1, param2); } else if( i->callConv == ICC_STDCALL ) { typedef void (STDCALL *func_t)(void *, void *); func_t f = (func_t)(i->func); f(param1, param2); } else { // We must guarantee the order of the arguments which is why we copy them to this // array. Otherwise the compiler may put them anywhere it likes, or even keep them // in the registers which causes problem. void *params[2] = {param1, param2}; asCGeneric gen(const_cast<asCScriptEngine*>(this), s, 0, (asDWORD*)&params); void (*f)(asIScriptGeneric *) = (void (*)(asIScriptGeneric *))(i->func); f(&gen); } } What's going on here? Am I missing something? Do I need to report this as an optimization bug to Microsoft? Do I need to make this a stdcall for some reason..?
  10. I'd understand this was the default behavior if there was not another item added, but as this creates another item with an undefined default value, and it seems rather unexpected, maybe it'd be better to disallow this by default?
  11. That would be very nice too. I'd love to have such a thing as an addon if you end up putting it in asrun!
  12. Miss

    Passing a block of memory (AngelScript newb)

    It sounds like you want to register TestClass in the application interface. In which case, take a look at the documentation here: http://www.angelcode.com/angelscript/sdk/docs/manual/doc_register_type.html Basically, you would do something like this in C++: (untested) class TestClass { private: int mRefCount = 0; public: int mInt; float mFloat; public: void AddRef() { mRefCount++; } void Release() { if (--mRefCount == 0) { delete this; } } }; static TestClass* GetTestClassInstance() { TestClass* ret = new TestClass; ret->mInt = 11; ret->mFloat = 3.33f; return ret; } void RegisterTestClass() { int r; // Register TestClass r = gEngine->RegisterObjectType("TestClass", sizeof(TestClass), asOBJ_REF); assert(r >= 0); r = gEngine->RegisterObjectBehaviour("TestClass", asBEHAVE_ADDREF, "void f()", asMETHOD(TestClass, AddRef), asCALL_THISCALL); assert(r >= 0); r = gEngine->RegisterObjectBehaviour("TestClass", asBEHAVE_RELEASE, "void f()", asMETHOD(TestClass, Release), asCALL_THISCALL); assert(r >= 0); r = gEngine->RegisterObjectProperty("TestClass", "int mInt", asOFFSET(TestClass, mInt)); assert(r >= 0); r = gEngine->RegisterObjectProperty("TestClass", "float mInt", asOFFSET(TestClass, mFloat)); assert(r >= 0); // Register function to get test class instance r = gEngine->RegisterGlobalFunction("TestClass@ GetTestClassInstance()", asFUNCTION(GetTestClassInstance), asCALL_CDECL); assert(r >= 0); } And then just call GetTestClassInstance() in your script, you don't have to write the entire class structure in your script, it will already be registered by the application. Note that I've added the AddRef/Release methods, which are called by the ADDREF and RELEASE behaviors, since I'm guessing you want to do it with handles. I've also used asCALL_CDECL above for the global function (we've never really had any compatibility issues, so we just never really bother with generic calling convention). Also, what's ScriptParams in your example? I assume it's something that implements asIScriptGeneric? As for your question on the "block of memory", yes, if you're using handles, then you basically just give Angelscript and pointer and it'll pass that along just like in C++. It will then know which offsets to use for properties from RegisterObjectProperty. It's not "mapping" on top of a type defined in scripts. Make sure you read the documentation though, it explains it much better than I ever could explain it.
  13. I would like to implement loading functions from external DLL's, in a syntax such as this: [Dll file="Test.dll"] external void DoSomething(); Currently, the external keyword requires that the function be defined in a module already before this declaration is compiled (since it's (implicitly?) a shared function), which breaks my ability to get the metadata from CScriptBuilder about the function. My suggestion is to have a callback function for external functions where I can resolve the function manually, possibly referring it to some asCALL_GENERIC function that handles the dll call. Perhaps this should be implemented in the CScriptBuilder addon rather than the library itself, since that holds the info on the metadata above the declaration. Any tips/workarounds would be nice to hear as well.
  14. Miss

    Compiler crash with ?: operator

    Thanks for checking! Will this ever be working in the future, or is it not possible to make this work?
  15. The following code crashes the Angelscript compiler on 2.32.0: array<int> foo = true ? { 1, 2, 3 } : { 4, 5, 6 }; Edit: The changelist for the WIP version actually says: Is this the same thing?
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!