const ConstOperator* ESolver::CreateConstant(const string& ConstantName, const ESFixedTypeBase* Type, const string& ConstantString) { const ConcreteValueBase* TheValue = CreateValue(Type, ConstantString); return CreateConstant(ConstantName, TheValue); }
const ESFixedTypeBase* ESolver::CreateEnumType(const string& TypeName, const vector<string>& EnumConstructors) { if(TypeMgr->LookupType(TypeName) != NULL) { throw TypeException("Redeclaration of Type \"" + TypeName + "\""); } // Safety check to ensure that enum constructors are not // repeated set<string> EnumConstructorSet; const uint32 NumEnumConstructors = EnumConstructors.size(); for(uint32 i = 0; i < NumEnumConstructors; ++i) { if(EnumConstructorSet.find(EnumConstructors[i]) != EnumConstructorSet.end()) { throw TypeException((string)"Duplicate Enum constructor \"" + EnumConstructors[i] + "\""); } EnumConstructorSet.insert(EnumConstructors[i]); } auto Retval = TypeMgr->CreateType<ESEnumType>(TypeName, EnumConstructors); TypeMgr->BindType(TypeName, Retval); RegisterType(Retval); // Create values and constant operators for each constructor // Push a bunch of constant operators into the fray. One for each enum constructor for(auto const& EnumConstructor : EnumConstructors) { CreateConstant(TypeName + "::" + EnumConstructor, Retval, EnumConstructor); } return Retval; }
static struct KVirtualCode *FuelVM_GenerateVirtualCode(KonohaContext *kctx, kMethod *mtd, kNode *block, int option) { if(unlikely(AbstractMethodPtr == 0)) { AbstractMethodPtr = mtd->invokeKMethodFunc; } kNameSpace *ns = kNode_ns(block); KBuilder builderbuf = {}, *builder = &builderbuf; FuelIRBuilder Builder = {}; INIT_GCSTACK(); IRBuilder_Init(&Builder, kctx, ns); builder->builder = &Builder; builder->common.api = ns->builderApi; Block *EntryBlock = CreateBlock(BLD(builder)); IRBuilder_setBlock(BLD(builder), EntryBlock); INode *Self = SetUpArguments(kctx, &Builder, mtd); SUGAR VisitNode(kctx, builder, block, NULL); if(!Block_HasTerminatorInst(BLD(builder)->Current)) { if(mtd->mn == MN_new) { INode *Ret = CreateReturn(BLD(builder), Self); INode_setType(Ret, ConvertToTypeId(kctx, mtd->typeId)); } else { ktypeattr_t retTy = kMethod_GetReturnType(mtd)->typeId; if(retTy == KType_void) { CreateReturn(BLD(builder), 0); } else { enum TypeId Type = ConvertToTypeId(kctx, retTy); INode *Ret; if(KType_Is(UnboxType, retTy)) { SValue V; V.bits = 0; Ret = CreateConstant(BLD(builder), Type, V); } else { kObject *obj = KLIB Knull(kctx, KClass_(retTy)); Ret = CreateObject(BLD(builder), Type, (void *)obj); } Ret = CreateReturn(BLD(builder), Ret); INode_setType(Ret, Type); CreateReturn(BLD(builder), 0); } } } RESET_GCSTACK(); IMethod Mtd = {kctx, mtd, EntryBlock, ns}; BLD(builder)->Method = &Mtd; bool JITCompiled = false; union ByteCode *code = IRBuilder_Compile(BLD(builder), &Mtd, option, &JITCompiled); if(mtd->invokeKMethodFunc == FuelVM_RunVirtualMachine) { mtd->virtualCodeApi_plus1[-1]->FreeVirtualCode(kctx, mtd->vcode_start); } KLIB kMethod_SetFunc(kctx, mtd, 0); if(JITCompiled) { KLIB kMethod_SetFunc(kctx, mtd, (KMethodFunc) code); } KFieldSet(mtd, ((kMethodVar *)mtd)->CompiledNode, block); IRBuilder_Exit(&Builder); return (struct KVirtualCode *) code; }
static kbool_t FuelVM_VisitUnboxConstNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { DBG_ASSERT(KType_Is(UnboxType, expr->attrTypeId)); //DBG_ASSERT(!kNode_HasObjectConstValue(expr)); SValue Val = {}; Val.bits = expr->unboxConstValue; builder->Value = CreateConstant(BLD(builder), ConvertToTypeId(kctx, expr->attrTypeId), Val); return true; }
static kbool_t FuelVM_VisitNullNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { SValue Val = {}; ktypeattr_t type = expr->attrTypeId; if(KType_Is(UnboxType, type)) { Val.bits = 0; } else { Val.ptr = (void *) KLIB Knull(kctx, KClass_(type)); } builder->Value = CreateConstant(BLD(builder), ConvertToTypeId(kctx, expr->attrTypeId), Val); return true; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void AggregateCopyPropagation::ReplaceWithOriginal(LoadInstr* instr, TOperandToIdDict& availableCopies, BitVector& killSet) { if(availableCopies.Count() == 0) { return; } // Try to replace each operand with the original one // (the one from which the copy was made). Instruction* lastInstr = nullptr; auto candidateOp = GetBaseOperand(instr->SourceOp(), &lastInstr); // Give up if we couldn't find a candidate, // or if the candidate is an instruction whose result // is used in more than one place. if((candidateOp == nullptr) || (lastInstr == nullptr) || (lastInstr->GetDestinationOp()->HasSingleUser() == false)) { return; } // We can replace the operand if it's a copy // (found in 'availableCopies') and the source or copy // was not killed until this point. CopySetInfo info; if(GetOldestAvailable(candidateOp, availableCopies, killSet, info)) { if(info.IsCopy) { // Replace the operand with the original. auto originalOp = info.Source; lastInstr->ReplaceSourceOp(0, originalOp); info.Replacements++; CopyPropagated(instr); } else if(instr->HasDestinationOp()) { // The load itself is replaced by the value // to which the record/array was set. auto requiredType = instr->GetDestinationOp()->GetType(); auto constantOp = CreateConstant(requiredType, info); instr->GetDestinationOp()->ReplaceWith(constantOp); info.Replacements++; CopyPropagated(instr); } } }
EvalAtom::EvalAtom(std::wstring& src, EvalAtomType atomType) { AtomType = atomType; Value = 0.0; Index = -1; Function = NULL; Operator = NULL; switch (atomType) { case EvalAtomType::Operator: CreateOperator(src); break; case EvalAtomType::Function: CreateFunction(src); break; case EvalAtomType::Variable: /** * If identifier of variable will be found in * internal constants table we will store this * constant, not variable. */ if (EvalTable::IsConstExists(src)) { AtomType = EvalAtomType::Constant; CreateNamedConstant(src); } else { CreateVariable(src); } break; case EvalAtomType::Constant: CreateConstant(src); break; } }
/* PreprocessLine() is the "preprocessor". * 1. the line is tokenized with Tokenize(), Token_Count set * 2. (text) macros are expanded by ExpandLine() * 3. "preprocessor" directives are executed */ int PreprocessLine( char *line, struct asm_tok tokenarray[] ) /***********************************************************/ { int i; /* v2.11: GetTextLine() removed - this is now done in ProcessFile() */ /* v2.08: moved here from GetTextLine() */ ModuleInfo.CurrComment = NULL; /* v2.06: moved here from Tokenize() */ ModuleInfo.line_flags = 0; /* Token_Count is the number of tokens scanned */ Token_Count = Tokenize( line, 0, tokenarray, TOK_DEFAULT ); #ifdef DEBUG_OUT cntppl0++; if ( ModuleInfo.GeneratedCode ) DebugMsg1(("PreprocessLine: >%s<\n", line )); else DebugMsg1(("PreprocessLine(%s): >%s< cmt=%s\n", GetTopSrcName(), line, ModuleInfo.CurrComment ? ModuleInfo.CurrComment : "" )); #endif #if REMOVECOMENT == 0 if ( Token_Count == 0 && ( CurrIfState == BLOCK_ACTIVE || ModuleInfo.listif ) ) LstWriteSrcLine(); #endif if ( Token_Count == 0 ) return( 0 ); #ifdef DEBUG_OUT /* option -np, skip preprocessor? */ if ( Options.skip_preprocessor ) return( Token_Count ); #endif /* CurrIfState != BLOCK_ACTIVE && Token_Count == 1 | 3 may happen * if a conditional assembly directive has been detected by Tokenize(). * However, it's important NOT to expand then */ if ( CurrIfState == BLOCK_ACTIVE ) { if ( ( tokenarray[Token_Count].bytval & TF3_EXPANSION ? ExpandText( line, tokenarray, TRUE ) : ExpandLine( line, tokenarray ) ) < NOT_ERROR ) return( 0 ); } DebugCmd( cntppl1++ ); i = 0; if ( Token_Count > 2 && ( tokenarray[1].token == T_COLON || tokenarray[1].token == T_DBL_COLON ) ) i = 2; /* handle "preprocessor" directives: * IF, ELSE, ENDIF, ... * FOR, REPEAT, WHILE, ... * PURGE * INCLUDE * since v2.05, error directives are no longer handled here! */ if ( tokenarray[i].token == T_DIRECTIVE && tokenarray[i].dirtype <= DRT_INCLUDE ) { /* if i != 0, then a code label is located before the directive */ if ( i > 1 ) { if ( ERROR == WriteCodeLabel( line, tokenarray ) ) return( 0 ); } directive_tab[tokenarray[i].dirtype]( i, tokenarray ); return( 0 ); } /* handle preprocessor directives which need a label */ if ( tokenarray[0].token == T_ID && tokenarray[1].token == T_DIRECTIVE ) { struct asym *sym; switch ( tokenarray[1].dirtype ) { case DRT_EQU: /* * EQU is a special case: * If an EQU directive defines a text equate * it MUST be handled HERE and 0 must be returned to the caller. * This will prevent further processing, nothing will be stored * if FASTPASS is on. * Since one cannot decide whether EQU defines a text equate or * a number before it has scanned its argument, we'll have to * handle it in ANY case and if it defines a number, the line * must be stored and, if -EP is set, written to stdout. */ if ( sym = CreateConstant( tokenarray ) ) { if ( sym->state != SYM_TMACRO ) { #if FASTPASS if ( StoreState ) FStoreLine( 0 ); #endif if ( Options.preprocessor_stdout == TRUE ) WritePreprocessedLine( line ); } /* v2.03: LstWrite() must be called AFTER StoreLine()! */ if ( ModuleInfo.list == TRUE ) { LstWrite( sym->state == SYM_INTERNAL ? LSTTYPE_EQUATE : LSTTYPE_TMACRO, 0, sym ); } } return( 0 ); case DRT_MACRO: case DRT_CATSTR: /* CATSTR + TEXTEQU directives */ case DRT_SUBSTR: directive_tab[tokenarray[1].dirtype]( 1, tokenarray ); return( 0 ); } } DebugCmd( cntppl2++ ); return( Token_Count ); }