ejsval Module_prototype_getOrInsertFunction(ejsval env, ejsval _this, int argc, ejsval *args) { Module *module = ((Module*)EJSVAL_TO_OBJECT(_this)); REQ_UTF8_ARG(0, name); REQ_LLVM_TYPE_ARG(1, returnType); REQ_ARRAY_ARG(2, paramTypes); std::vector< llvm::Type*> param_types; for (int i = 0; i < EJSARRAY_LEN(paramTypes); i ++) { param_types.push_back (Type_GetLLVMObj(EJSDENSEARRAY_ELEMENTS(paramTypes)[i])); } llvm::FunctionType *FT = llvm::FunctionType::get(returnType, param_types, false); llvm::Function* f = static_cast< llvm::Function*>(module->llvm_module->getOrInsertFunction(name, FT)); // XXX this needs to come from the js call, since when we hoist anonymous methods we'll need to give them a private linkage. f->setLinkage (llvm::Function::ExternalLinkage); // XXX the args might not be identifiers but might instead be destructuring expressions. punt for now. #if notyet // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); #endif return Function_new (f); }
static ejsval ConstantArray_get (ejsval env, ejsval _this, int argc, ejsval *args) { REQ_LLVM_TYPE_ARG(0, array_type); REQ_ARRAY_ARG(1, elements); std::vector< llvm::Constant*> element_constants; for (int i = 0; i < EJSARRAY_LEN(elements); i ++) { element_constants.push_back (static_cast<llvm::Constant*>(Value_GetLLVMObj(EJSDENSEARRAY_ELEMENTS(elements)[i]))); } return Value_new (llvm::ConstantArray::get(static_cast<llvm::ArrayType*>(array_type), element_constants)); }
ejsval IRBuilder_createInBoundsGetElementPointer(ejsval env, ejsval _this, int argc, ejsval *args) { REQ_LLVM_VAL_ARG(0, val); REQ_ARRAY_ARG(1, idxv); FALLBACK_EMPTY_UTF8_ARG(2, name); std::vector<llvm::Value*> IdxV; for (unsigned i = 0, e = EJSARRAY_LEN(idxv); i != e; ++i) { IdxV.push_back (Value_GetLLVMObj(EJSDENSEARRAY_ELEMENTS(idxv)[i])); if (IdxV.back() == 0) abort(); // XXX throw an exception here } return Value_new (_llvm_builder.CreateInBoundsGEP(val, IdxV, name)); }
ejsval IRBuilder_createCall(ejsval env, ejsval _this, int argc, ejsval *args) { REQ_LLVM_VAL_ARG(0, callee); REQ_ARRAY_ARG(1, argv); FALLBACK_EMPTY_UTF8_ARG(2, name); std::vector<llvm::Value*> ArgsV; for (unsigned i = 0, e = EJSARRAY_LEN(argv); i != e; ++i) { ArgsV.push_back (Value_GetLLVMObj(EJSDENSEARRAY_ELEMENTS(argv)[i])); if (ArgsV.back() == 0) abort(); // XXX throw an exception here } return Call_new (_llvm_builder.CreateCall(callee, ArgsV, name)); }
ejsval StructType_create(ejsval env, ejsval _this, int argc, ejsval *args) { REQ_UTF8_ARG (0, name); REQ_ARRAY_ARG (1, elementTypes); std::vector<llvm::Type*> element_types; for (int i = 0; i < EJSARRAY_LEN(elementTypes); i ++) { element_types.push_back (Type_GetLLVMObj(EJSDENSEARRAY_ELEMENTS(elementTypes)[i])); } ejsval rv = StructType_new(llvm::StructType::create(llvm::getGlobalContext(), element_types, name)); free (name); return rv; }
static ejsval FunctionType_get (ejsval env, ejsval _this, int argc, ejsval *args) { REQ_LLVM_TYPE_ARG(0, returnType); REQ_ARRAY_ARG(1, argTypes); std::vector<llvm::Type*> arg_types; for (int i = 0; i < EJSARRAY_LEN(argTypes); i ++) { arg_types.push_back (Type_GetLLVMObj(EJSDENSEARRAY_ELEMENTS(argTypes)[i])); } llvm::FunctionType *FT = llvm::FunctionType::get(returnType, arg_types, false); EJSObject* result = FunctionType_alloc_instance(); _ejs_init_object (result, _ejs_FunctionType_proto, NULL); ((FunctionType*)result)->type = FT; return OBJECT_TO_EJSVAL(result); }
static ejsval _ejs_child_process_spawn (ejsval env, ejsval _this, uint32_t argc, ejsval* args) { char* argv0 = ucs2_to_utf8(EJSVAL_TO_FLAT_STRING(args[0])); EJSArray* argv_rest = (EJSArray*)EJSVAL_TO_OBJECT(args[1]); char **argv = (char**)calloc(sizeof(char*), EJSARRAY_LEN(argv_rest) + 2); argv[0] = argv0; for (uint32_t i = 0; i < EJSARRAY_LEN(argv_rest); i ++) argv[1+i] = ucs2_to_utf8(EJSVAL_TO_FLAT_STRING(ToString(EJSDENSEARRAY_ELEMENTS(argv_rest)[i]))); pid_t pid; switch (pid = fork()) { case -1: /* error */ perror("fork"); printf ("we should totally throw an exception here\n"); break; case 0: /* child */ execvp (argv0, argv); perror("execv"); EJS_NOT_REACHED(); break; default: /* parent */ { int stat; int wait_rv; do { wait_rv = waitpid(pid, &stat, 0); } while (wait_rv == -1 && errno == EINTR); if (wait_rv != pid) { perror ("waitpid"); printf ("we should totally throw an exception here\n"); } break; } } for (uint32_t i = 0; i < EJSARRAY_LEN(argv_rest)+1; i ++) free (argv[i]); free (argv); return _ejs_undefined; }
ejsval Module_prototype_getOrInsertExternalFunction(ejsval env, ejsval _this, int argc, ejsval *args) { Module *module = ((Module*)EJSVAL_TO_OBJECT(_this)); REQ_UTF8_ARG(0, name); REQ_LLVM_TYPE_ARG(1, returnType); REQ_ARRAY_ARG(2, paramTypes); std::vector< llvm::Type*> param_types; for (int i = 0; i < EJSARRAY_LEN(paramTypes); i ++) { param_types.push_back (Type_GetLLVMObj(EJSDENSEARRAY_ELEMENTS(paramTypes)[i])); } llvm::FunctionType *FT = llvm::FunctionType::get(returnType, param_types, false); llvm::Function* f = static_cast< llvm::Function*>(module->llvm_module->getOrInsertFunction(name, FT)); f->setLinkage (llvm::Function::ExternalLinkage); return Function_new (f); }
// ECMA262 15.3.4.3 static ejsval _ejs_Function_prototype_apply (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval func = _this; /* 1. If IsCallable(func) is false, then throw a TypeError exception. */ if (!EJSVAL_IS_CALLABLE(_this)) { printf ("throw TypeError, func is not callable\n"); EJS_NOT_IMPLEMENTED(); } ejsval thisArg = _ejs_undefined; ejsval argArray = _ejs_undefined; if (argc > 0) thisArg = args[0]; if (argc > 1) argArray = args[1]; /* 2. If argArray is null or undefined, then */ if (EJSVAL_IS_UNDEFINED(argArray) || EJSVAL_IS_NULL(argArray)) { /* a. Return the result of calling the [[Call]] internal method of func, providing thisArg as the this value */ /* and an empty list of arguments. */ return _ejs_invoke_closure (func, thisArg, 0, NULL); } /* 3. If Type(argArray) is not Object, then throw a TypeError exception. */ if (!EJSVAL_IS_OBJECT(argArray)) { printf ("throw TypeError, argArray is not an object\n"); EJS_NOT_IMPLEMENTED(); } EJSObject* argArray_ = EJSVAL_TO_OBJECT(argArray); /* 4. Let len be the result of calling the [[Get]] internal method of argArray with argument "length". */ ejsval len = OP(argArray_,Get) (argArray, _ejs_atom_length, argArray); /* 5. Let n be ToUint32(len). */ uint32_t n = (uint32_t)EJSVAL_TO_NUMBER(len); ejsval* argList; EJSBool argList_allocated = EJS_FALSE; if (EJSVAL_IS_DENSE_ARRAY(argArray)) { argList = EJSDENSEARRAY_ELEMENTS(argArray_); } else { /* 6. Let argList be an empty List. */ argList = (ejsval*)malloc(sizeof(ejsval) * n); argList_allocated = EJS_TRUE; /* 7. Let index be 0. */ int index = 0; /* 8. Repeat while index < n */ while (index < n) { /* a. Let indexName be ToString(index). */ ejsval indexName = NUMBER_TO_EJSVAL(index); /* b. Let nextArg be the result of calling the [[Get]] internal method of argArray with indexName as the */ /* argument. */ ejsval nextArg = OP(argArray_,Get)(argArray, indexName, argArray); /* c. Append nextArg as the last element of argList. */ argList[index] = nextArg; /* d. Set index to index + 1. */ ++index; } } /* 9. Return the result of calling the [[Call]] internal method of func, providing thisArg as the this value and */ /* argList as the list of arguments. */ ejsval rv = EJSVAL_TO_FUNC(func) (EJSVAL_TO_ENV(func), thisArg, n, argList); if (argList_allocated) free (argList); return rv; }