llvm_value CompileExpression::DoPrefix(Prefix *what) // ---------------------------------------------------------------------------- // Compile prefix expressions // ---------------------------------------------------------------------------- { if (Name *name = what->left->AsName()) { if (name->value == "data" || name->value == "extern") return NULL; if (name->value == "opcode") { // This is a builtin, find if we write to code or data llvm_builder bld = unit->code; Tree *builtin = what->right; if (Prefix *prefix = builtin->AsPrefix()) { if (Name *name = prefix->left->AsName()) { if (name->value == "data") { bld = unit->data; builtin = prefix->right; } } } // Take args list for current function as input llvm_values args; Function *function = unit->function; uint i, max = function->arg_size(); Function::arg_iterator arg = function->arg_begin(); for (i = 0; i < max; i++) { llvm_value inputArg = arg++; args.push_back(inputArg); } // Call the primitive (effectively creating a wrapper for it) Name *name = builtin->AsName(); assert(name || !"Malformed primitive"); Compiler *compiler = unit->compiler; text op = name->value; uint sz = args.size(); llvm_value *a = &args[0]; return compiler->Primitive(bld, op, sz, a); } } return DoCall(what); }
llvm_value CompileExpression::DoRewrite(RewriteCandidate &cand) // ---------------------------------------------------------------------------- // Generate code for a particular rewwrite candidate // ---------------------------------------------------------------------------- { Infix *rw = cand.rewrite; llvm_value result = NULL; IFTRACE(calltypes) std::cerr << "Rewrite: " << rw << "\n"; // Evaluate parameters llvm_values args; RewriteBindings &bnds = cand.bindings; RewriteBindings::iterator b; for (b = bnds.begin(); b != bnds.end(); b++) { Tree *tree = (*b).value; IFTRACE(calltypes) std::cerr << " Arg: " << tree << ": "; if (llvm_value closure = (*b).Closure(unit)) { args.push_back(closure); IFTRACE(calltypes) llvm::errs() << " closure " << *closure << "\n"; } else if (llvm_value value = Value(tree)) { args.push_back(value); llvm_type mtype = value->getType(); if (unit->compiler->IsClosureType(mtype)) (*b).closure = value; IFTRACE(calltypes) llvm::errs() << " value " << *value << " mtype " << *mtype << "\n"; } } // Check if this is an LLVM builtin Tree *builtin = NULL; if (Tree *value = rw->right) if (Prefix *prefix = value->AsPrefix()) if (Name *name = prefix->left->AsName()) if (name->value == "opcode") builtin = prefix->right; if (builtin) { llvm_builder bld = unit->code; if (Prefix *prefix = builtin->AsPrefix()) { if (Name *name = prefix->left->AsName()) { if (name->value == "data") { bld = unit->data; builtin = prefix->right; } } } Name *name = builtin->AsName(); if (!name) { Ooops("Malformed primitive $1", builtin); result = unit->CallFormError(builtin); } else { Compiler *compiler = unit->compiler; text op = name->value; uint sz = args.size(); llvm_value *a = &args[0]; result = compiler->Primitive(*unit, bld, op, sz, a); if (!result) Ooops("Invalid primitive $1", builtin); IFTRACE(calltypes) llvm::errs() << " = Primitive: " << *result << "\n"; } } else { llvm_value function = unit->Compile(cand, args); IFTRACE(calltypes) llvm::errs() << " < Function: " << *function << "\n"; if (function) result = unit->code->CreateCall(function, LLVMS_ARGS(args)); IFTRACE(calltypes) llvm::errs() << " =Call: " << *result << "\n"; } return result; }
Function *CompiledUnit::RewriteFunction(RewriteCandidate &rc) // ---------------------------------------------------------------------------- // Create a function for a tree rewrite // ---------------------------------------------------------------------------- { Types *types = rc.types; Infix *rewrite = rc.rewrite; // We must have verified the types before assert((types && !this->types) || !"RewriteFunction: bogus type check"); this->types = types; Tree *source = RewriteDefined(rewrite->left); Tree *def = rewrite->right; IFTRACE(llvm) std::cerr << "CompiledUnit::RewriteFunction T" << (void *) source; // Extract parameters from source form ParameterList parameters(this); if (!source->Do(parameters)) return NULL; // Create the function signature, one entry per parameter llvm_types signature; Signature(parameters.parameters, rc, signature); // Compute return type: // - If explicitly specified, use that (TODO: Check compatibility) // - For definitions, infer from definition // - For data forms, this is the type of the data form llvm_type retTy; if (llvm_type specifiedRetTy = parameters.returned) retTy = specifiedRetTy; else if (def) retTy = ReturnType(def); else retTy = StructureType(signature, source); text label = "_ELFE_" + parameters.name; IFTRACE(labels) label += "[" + text(*source) + "]"; // Check if we are actually declaring a C function bool isC = false; bool isVararg = false; if (Tree *defined = parameters.defined) { if (Name *name = def->AsName()) if (name->value == "C") if (ValidCName(defined, label)) isC = true; if (Prefix *prefix = def->AsPrefix()) if (Name *name = prefix->left->AsName()) if (name->value == "C") if (ValidCName(prefix->right, label)) isC = true; } FunctionType *fnTy = FunctionType::get(retTy, signature, isVararg); Function *f = InitializeFunction(fnTy, ¶meters.parameters, label.c_str(), isC, isC); if (isC) { void *address = sys::DynamicLibrary::SearchForAddressOfSymbol(label); if (!address) { Ooops("No library function matching $1", rewrite->left); return NULL; } sys::DynamicLibrary::AddSymbol(label, address); } return f; }
llvm_value CompileExpression::DoRewrite(RewriteCandidate &cand) // ---------------------------------------------------------------------------- // Generate code for a particular rewwrite candidate // ---------------------------------------------------------------------------- { Rewrite *rw = cand.rewrite; llvm_value result = NULL; // Evaluate parameters llvm_values args; RewriteBindings &bnds = cand.bindings; RewriteBindings::iterator b; for (b = bnds.begin(); b != bnds.end(); b++) { Tree *tree = (*b).value; if (llvm_value closure = (*b).Closure(unit)) { args.push_back(closure); } else if (llvm_value value = Value(tree)) { args.push_back(value); llvm_type mtype = value->getType(); if (unit->compiler->IsClosureType(mtype)) (*b).closure = value; } } // Check if this is an LLVM builtin Tree *builtin = NULL; if (rw->to) if (Prefix *prefix = rw->to->AsPrefix()) if (Name *name = prefix->left->AsName()) if (name->value == "opcode") builtin = prefix->right; if (builtin) { llvm_builder bld = unit->code; if (Prefix *prefix = builtin->AsPrefix()) { if (Name *name = prefix->left->AsName()) { if (name->value == "data") { bld = unit->data; builtin = prefix->right; } } } Name *name = builtin->AsName(); assert(name || !"Malformed primitive"); Compiler *compiler = unit->compiler; text op = name->value; uint sz = args.size(); llvm_value *a = &args[0]; result = compiler->Primitive(bld, op, sz, a); } else { llvm_value function = unit->Compile(cand, args); if (function) result = unit->code->CreateCall(function, LLVMS_ARGS(args)); } return result; }