void MultiVarAssi::codeGen(AstContext &astContext) { vector<AValue> vars; for (unsigned i = 0; i < leftExprList.size(); i++) { LeftValueExpr *leftExpr = leftExprList[i]; if (leftExpr == NULL) { vars.push_back(AValue()); } else { AValue var = leftExpr->lvalueGen(astContext); vars.push_back(var); } } vector<AValue> values = funcInvoke->multiCodeGen(astContext); if (values.size() < vars.size()) { errorMsg = "too few values returned from function '" + funcInvoke->funcName + "'"; throwError(funcInvoke); } for (unsigned i = 0; i < vars.size(); i++) { if (vars[i].llvmValue == NULL) { continue; } AValue v = values[i]; if (!v.castTo(vars[i].clazz)) { throwError(this); } builder.CreateStore(v.llvmValue, vars[i].llvmValue); } }
AValue InstanceOf::gen(AstContext &astContext) { AValue v = expr->codeGen(astContext); ClassInfo *destClass = typeDecl->getClassInfo(); if (v.clazz == nilClass && (destClass->isObjectType() || destClass->isArrayType())) { return AValue(bool_true, boolClass); } else if (v.clazz->isSubClassOf(destClass)) { return AValue(bool_true, boolClass); } else if (destClass->isObjectType() && v.isObject()) { Value *res = builder.CreateCall2(sysInstanceOf, v.llvmValue, destClass->info); res = builder.CreateTrunc(res, boolType); return AValue(res, boolClass); } else { return AValue(bool_false, boolClass); } }
AValue ThisExpr::gen(AstContext &astContext) { if (astContext.classContext == NULL) { errorMsg = "invalid use of 'this' outside of a class method"; throwError(this); } if (astContext.classContext->thisObject == NULL) { errorMsg = "invalid use of 'this' before current object create"; throwError(this); } return AValue(astContext.classContext->thisObject, astContext.classContext->currentClass); }
AValue String::gen(AstContext &astContext) { vector<Constant*> unicodes; for (unsigned i = 0; i < data->size(); i++) { int32_t unicode = data->at(i); unicodes.push_back(ConstantInt::get(int32Type, unicode)); } if (unicodes.size() > 0) { ArrayType *arrayType = ArrayType::get(int32Type, unicodes.size()); GlobalVariable *array = new GlobalVariable(module, arrayType, true, GlobalValue::PrivateLinkage, ConstantArray::get(arrayType, ArrayRef<Constant*>(unicodes))); Value *str = builder.CreateCall3(sysArrayAlloca, builder.getInt64(unicodes.size()), builder.getInt8(dataLayout->getTypeStoreSize(int32Type)), builder.CreateBitCast(array, ptrType)); return AValue(str, charClass->getArrayClass()); } else { Value *str = builder.CreateCall3(sysArrayAlloca, int64_0, builder.getInt8(dataLayout->getTypeStoreSize(int32Type)), ptr_null); return AValue(str, charClass->getArrayClass()); } }
void VarDef::globalGen() { ClassInfo *classInfo = typeDecl->getClassInfo(); Constant *initial = classInfo->getInitial(); for (unsigned i = 0; i < varInitList.size(); i++) { VarInit *varInit = varInitList[i]; Value *llvmVar = new GlobalVariable(module, classInfo->llvmType, false, GlobalValue::ExternalLinkage, initial); AstContext astContext; if (varInit->expr != NULL) { varInit->expr->expectedType = classInfo; AValue v = varInit->expr->codeGen(astContext); builder.CreateStore(v.llvmValue, llvmVar); } globalContext.addVar(varInit->varName, AValue(llvmVar, classInfo)); } }
void VarDef::codeGen(AstContext &astContext) { ClassInfo *classInfo = typeDecl->getClassInfo(); for (unsigned i = 0; i < varInitList.size(); i++) { VarInit *varInit = varInitList[i]; Value *value = NULL; if (varInit->expr != NULL) { varInit->expr->expectedType = classInfo; AValue v = varInit->expr->codeGen(astContext); value = v.llvmValue; } else { value = classInfo->getInitial(); } Value *var = createAlloca(classInfo->llvmType, astContext.allocBB); if (!astContext.addVar(varInit->varName, AValue(var, classInfo))) { throwError(varInit); } builder.CreateStore(value, var); } }
AValue SuperExpr::gen(AstContext &astContext) { if (astContext.classContext == NULL) { errorMsg = "invalid use of 'super' outside of a constructor"; throwError(this); } ClassInfo *currentClass = astContext.classContext->currentClass; if (astContext.classContext->superObject == NULL) { if (currentClass->superClassInfo == NULL) { errorMsg = "class '" + currentClass->name + "' has no super class"; throwError(this); } else if (astContext.classContext->thisObject == NULL) { errorMsg = "invalid use of 'super' before super object create"; throwError(this); } else { errorMsg = "invalid use of 'super' outside of a constructor"; throwError(this); } } return AValue(astContext.classContext->superObject, astContext.classContext->currentClass->superClassInfo); }
AValue Nil::gen(AstContext &astContext) { return AValue(ptr_null, nilClass); }
AValue Bool::gen(AstContext &astContext) { return AValue(builder.getInt1(value), boolClass); }
AValue Double::gen(AstContext &astContext) { return AValue(ConstantFP::get(doubleType, value), doubleClass); }
AValue Char::gen(AstContext &astContext) { return AValue(ConstantInt::getSigned(int32Type, value), charClass); }
AValue Long::gen(AstContext &astContext) { return AValue(ConstantInt::getSigned(int64Type, value), longClass); }
static void dumpeit(void *p_cb_data, dvbpsi_eit_t *p_new_eit) { (void)p_cb_data; const dvbpsi_eit_event_t *p_event = p_new_eit->p_first_event; while (p_event) { printf("Event: TS ID %u Network ID %u Event ID %u starttime %s duration %u\n", p_new_eit->i_ts_id, p_new_eit->i_network_id, p_event->i_event_id, AValue(p_event->i_start_time).ToString("016x").str(), p_event->i_duration); DumpDescriptors("Event", p_event->p_first_descriptor); p_event = p_event->p_next; } }
AValue BinaryOpExpr::gen(AstContext &astContext) { AValue lv = leftExpr->codeGen(astContext); AValue rv = rightExpr->codeGen(astContext); AValue res; if (op == '%') { if ((lv.isLong() || lv.isChar()) && (rv.isLong() || rv.isChar())) { if (lv.isLong()) { rv.castTo(longClass); } else { lv.castTo(rv.clazz); } res = AValue(builder.CreateSRem(lv.llvmValue, rv.llvmValue),lv.clazz); } } else if (lv.isBool() && rv.isBool()) { switch (op) { case EQUAL: res = AValue(builder.CreateICmpEQ(lv.llvmValue, rv.llvmValue), boolClass); break; case NEQUAL: res = AValue(builder.CreateICmpNE(lv.llvmValue, rv.llvmValue), boolClass); break; } } else if ((lv.isLong() || lv.isDouble() || lv.isChar()) && (rv.isLong() || rv.isDouble() || rv.isChar())) { if (lv.isDouble() || rv.isDouble()) { if (!lv.castTo(doubleClass)) { throwError(leftExpr); } if (!rv.castTo(doubleClass)) { throwError(rightExpr); } } else if (lv.isLong() || rv.isLong()) { if (!lv.castTo(longClass)) { throwError(leftExpr); } if (!rv.castTo(longClass)) { throwError(rightExpr); } } if (lv.isDouble()) { switch (op) { case '+': res = AValue(builder.CreateFAdd(lv.llvmValue, rv.llvmValue), doubleClass); break; case '-': res = AValue(builder.CreateFSub(lv.llvmValue, rv.llvmValue), doubleClass); break; case '*': res = AValue(builder.CreateFMul(lv.llvmValue, rv.llvmValue), doubleClass); break; case '/': res = AValue(builder.CreateFDiv(lv.llvmValue, rv.llvmValue), doubleClass); break; case EQUAL: res = AValue(builder.CreateFCmpOEQ(lv.llvmValue, rv.llvmValue), boolClass); break; case NEQUAL: res = AValue(builder.CreateFCmpONE(lv.llvmValue, rv.llvmValue), boolClass); break; case '<': res = AValue(builder.CreateFCmpOLT(lv.llvmValue, rv.llvmValue), boolClass); break; case '>': res = AValue(builder.CreateFCmpOGT(lv.llvmValue, rv.llvmValue), boolClass); break; case LE: res = AValue(builder.CreateFCmpOLE(lv.llvmValue, rv.llvmValue), boolClass); break; case GE: res = AValue(builder.CreateFCmpOGE(lv.llvmValue, rv.llvmValue), boolClass); break; } } else { switch (op) { case '+': res = AValue(builder.CreateAdd(lv.llvmValue, rv.llvmValue), lv.clazz); break; case '-': res = AValue(builder.CreateSub(lv.llvmValue, rv.llvmValue), lv.clazz); break; case '*': res = AValue(builder.CreateMul(lv.llvmValue, rv.llvmValue), lv.clazz); break; case '/': res = AValue(builder.CreateSDiv(lv.llvmValue, rv.llvmValue), lv.clazz); break; case EQUAL: res = AValue(builder.CreateICmpEQ(lv.llvmValue, rv.llvmValue), boolClass); break; case NEQUAL: res = AValue(builder.CreateICmpNE(lv.llvmValue, rv.llvmValue), boolClass); break; case '<': res = AValue(builder.CreateICmpSLT(lv.llvmValue, rv.llvmValue), boolClass); break; case '>': res = AValue(builder.CreateICmpSGT(lv.llvmValue, rv.llvmValue), boolClass); break; case LE: res = AValue(builder.CreateICmpSLE(lv.llvmValue, rv.llvmValue), boolClass); break; case GE: res = AValue(builder.CreateICmpSGE(lv.llvmValue, rv.llvmValue), boolClass); break; } } } else if ((lv.isObject() || lv.isArray()) && (rv.isObject() || rv.isArray())) { if (op == EQUAL) { res = AValue(builder.CreateICmpEQ(lv.llvmValue, rv.llvmValue), boolClass); } else if (op == NEQUAL) { res = AValue(builder.CreateICmpNE(lv.llvmValue, rv.llvmValue), boolClass); } } if (res.llvmValue == NULL) { errorMsg = "invalid operands to binary expression (" + lv.clazz->name + " " + getOperatorName(op) + " " + rv.clazz->name + ")"; throwError(this); } return res; }