bool CompileFunction(CompileInstance &inst, const mtlChars &ret_type, const mtlChars &name, const mtlChars ¶ms, const mtlChars &body) { if (!IsGlobal(inst)) { // TODO: I want to support this eventually, but I need to emit jump instructions AddError(inst, "Nested functions not allowed", name); return false; } PushScope(inst, false); inst.scopes.GetLast()->GetItem().rel_sptr = 0; // reset the relative stack pointer bool result = true; bool is_main = false; result &= DeclareVar(inst, ret_type, name, ""); if (name.Compare("main", true)) { ++inst.main; if (inst.main > 1) { AddError(inst, "Multiple entry points", ""); return false; } *inst.prog_entry = (char)inst.program.GetSize(); is_main = true; } Parser p; p.SetBuffer(params); mtlList<mtlChars> m; int stack_start = inst.scopes.GetLast()->GetItem().size; while (!p.IsEnd()) { if (p.MatchPart("%w%w", m, NULL) == 0) { result &= DeclareVar(inst, m.GetFirst()->GetItem(), m.GetFirst()->GetNext()->GetItem(), ""); } else { AddError(inst, "Parameter syntax", params); return false; } p.MatchPart(",", m); } int stack_end = inst.scopes.GetLast()->GetItem().size; result &= CompileScope(inst, body, false); PopScope(inst); if (is_main) { *inst.prog_inputs = stack_end - stack_start; EmitInstruction(inst, swsl::END); } else { // FIX: This is a placeholder to prevent the compiler from optimizing stack manipulations EmitInstruction(inst, swsl::NOP); // this should emit a SET instruction (set the value of the return value) } return result; }
/// encodeInstruction - Emit the instruction. /// Size the instruction (currently only 4 bytes) void Cpu0MCCodeEmitter:: encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { uint32_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); // Check for unimplemented opcodes. // Unfortunately in CPU0 both NOT and SLL will come in with Binary == 0 // so we have to special check for them. unsigned Opcode = MI.getOpcode(); if ((Opcode != Cpu0::NOP) && (Opcode != Cpu0::SHL) && !Binary) llvm_unreachable("unimplemented opcode in encodeInstruction()"); const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); uint64_t TSFlags = Desc.TSFlags; // Pseudo instructions don't get encoded and shouldn't be here // in the first place! if ((TSFlags & Cpu0II::FormMask) == Cpu0II::Pseudo) llvm_unreachable("Pseudo opcode found in encodeInstruction()"); // For now all instructions are 4 bytes int Size = 4; // FIXME: Have Desc.getSize() return the correct value! EmitInstruction(Binary, Size, OS); }
void MipsMCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI, raw_ostream &OS) const { // Output the instruction encoding in little endian byte order. // Little-endian byte ordering: // mips32r2: 4 | 3 | 2 | 1 // microMIPS: 2 | 1 | 4 | 3 if (IsLittleEndian && Size == 4 && isMicroMips(STI)) { EmitInstruction(Val >> 16, 2, STI, OS); EmitInstruction(Val, 2, STI, OS); } else {
bool AssignVar(CompileInstance &inst, const mtlChars &name, const mtlChars &expr) { mtlChars base_name = GetBaseName(name); Definition *type = GetType(inst, base_name); if (type == NULL) { AddError(inst, "Undeclared variable", name); return false; } if (type->mut != Mutable) { AddError(inst, "Modifying a constant", name); return false; } ExpressionNode *tree = GenerateTree(expr); if (tree == NULL) { AddError(inst, "Malformed expression", expr); return false; } mtlChars base_mem = GetBaseMembers(name); bool result = true; Parser parser; mtlList<mtlChars> ops; mtlList<mtlChars> m; mtlString order_str; const int num_lanes = (base_mem.GetSize() > 0) ? base_mem.GetSize() : type->type.size; for (int lane = 0; lane < num_lanes; ++lane) { order_str.Free(); const int stack_size = tree->Evaluate(name, order_str, lane, 0); PushStack(inst, stack_size); order_str.SplitByChar(ops, ';'); mtlItem<mtlChars> *op = ops.GetFirst(); while (op != NULL && op->GetItem().GetSize() > 0) { parser.SetBuffer(op->GetItem()); switch (parser.MatchPart("%s+=%s%|%s-=%s%|%s*=%s%|%s/=%s%|%s=%s", m, NULL)) { case 0: EmitInstruction(inst, swsl::FLT_ADD_MM); break; case 1: EmitInstruction(inst, swsl::FLT_SUB_MM); break; case 2: EmitInstruction(inst, swsl::FLT_MUL_MM); break; case 3: EmitInstruction(inst, swsl::FLT_DIV_MM); break; case 4: EmitInstruction(inst, swsl::FLT_SET_MM); break; default: AddError(inst, "Invalid syntax", op->GetItem()); return false; break; } mtlItem<swsl::Instruction> *instr_item = inst.program.GetLast(); const mtlChars dst = m.GetFirst()->GetItem(); const mtlChars src = m.GetFirst()->GetNext()->GetItem(); EmitOperand(inst, dst); if (src.IsFloat()) { *((int*)(&instr_item->GetItem().instr)) += 1; } EmitOperand(inst, src); op = op->GetNext(); } PopStack(inst, stack_size); } delete tree; return result; }