func parseInstructionBody()

in Sources/SIL/SILParser.swift [104:363]


    func parseInstructionBody(_ instructionName: String) throws -> Instruction {
        switch instructionName {
        case "alloc_stack":
            let type = try parseType()
            let attributes = try parseUntilNil { try parseDebugAttribute() }
            return .operator(.allocStack(type, attributes))
        case "apply":
            let nothrow = skip("[nothrow]")
            let value = try parseValue()
            let substitutions = try parseNilOrMany("<", ",", ">") { try parseNakedType() } ?? []
            let arguments = try parseMany("(", ",", ")") { try parseValue() }
            try take(":")
            let type = try parseType()
            return .operator(.apply(nothrow, value, substitutions, arguments, type))
        case "begin_access":
            try take("[")
            let access = try parseAccess()
            try take("]")
            try take("[")
            let enforcement = try parseEnforcement()
            try take("]")
            let noNestedConflict = skip("[no_nested_conflict]")
            let builtin = skip("[builtin]")
            let operand = try parseOperand()
            return .operator(.beginAccess(access, enforcement, noNestedConflict, builtin, operand))
        case "begin_apply":
            let nothrow = skip("[nothrow]")
            let value = try parseValue()
            let substitutions = try parseNilOrMany("<", ",", ">") { try parseNakedType() } ?? []
            let arguments = try parseMany("(", ",", ")") { try parseValue() }
            try take(":")
            let type = try parseType()
            return .operator(.beginApply(nothrow, value, substitutions, arguments, type))
        case "begin_borrow":
            let operand = try parseOperand()
            return .operator(.beginBorrow(operand))
        case "br":
            let label = try parseIdentifier()
            let operands = try parseNilOrMany("(", ",", ")") { try parseOperand() } ?? []
            return .terminator(.br(label, operands))
        case "builtin":
            let name = try parseString()
            let operands = try parseMany("(", ",", ")") { try parseOperand() }
            try take(":")
            let type = try parseType()
            return .operator(.builtin(name, operands, type))
        case "cond_br":
            let cond = try parseValueName()
            try take(",")
            let trueLabel = try parseIdentifier()
            let trueOperands = try parseNilOrMany("(", ",", ")") { try parseOperand() } ?? []
            try take(",")
            let falseLabel = try parseIdentifier()
            let falseOperands = try parseNilOrMany("(", ",", ")") { try parseOperand() } ?? []
            return .terminator(.condBr(cond, trueLabel, trueOperands, falseLabel, falseOperands))
        case "cond_fail":
            let operand = try parseOperand()
            try take(",")
            let message = try parseString()
            return .operator(.condFail(operand, message))
        case "convert_escape_to_noescape":
            let notGuaranteed = skip("[not_guaranteed]")
            let escaped = skip("[escaped]")
            let operand = try parseOperand()
            try take("to")
            let type = try parseType()
            return .operator(.convertEscapeToNoescape(notGuaranteed, escaped, operand, type))
        case "convert_function":
            let operand = try parseOperand()
            try take("to")
            let withoutActuallyEscaping = skip("[without_actually_escaping]")
            let type = try parseType()
            return .operator(.convertFunction(operand, withoutActuallyEscaping, type))
        case "copy_addr":
            let take = skip("[take]")
            let value = try parseValue()
            try self.take("to")
            let initialization = skip("[initialization]")
            let operand = try parseOperand()
            return .operator(.copyAddr(take, value, initialization, operand))
        case "copy_value":
            let operand = try parseOperand()
            return .operator(.copyValue(operand))
        case "dealloc_stack":
            let operand = try parseOperand()
            return .operator(.deallocStack(operand))
        case "debug_value":
            let operand = try parseOperand()
            let attributes = try parseUntilNil { try parseDebugAttribute() }
            return .operator(.debugValue(operand, attributes))
        case "debug_value_addr":
            let operand = try parseOperand()
            let attributes = try parseUntilNil { try parseDebugAttribute() }
            return .operator(.debugValueAddr(operand, attributes))
        case "destroy_value":
            let operand = try parseOperand()
            return .operator(.destroyValue(operand))
        case "destructure_tuple":
            let operand = try parseOperand()
            return .operator(.destructureTuple(operand))
        case "end_access":
            let abort = skip("[abort]")
            let operand = try parseOperand()
            return .operator(.endAccess(abort, operand))
        case "end_apply":
            let value = try parseValue()
            return .operator(.endApply(value))
        case "end_borrow":
            let operand = try parseOperand()
            return .operator(.endBorrow(operand))
        case "enum":
            let type = try parseType()
            try take(",")
            let declRef = try parseDeclRef()
            let operand = skip(",") ? try parseOperand() : nil
            return .operator(.enum(type, declRef, operand))
        case "float_literal":
            let type = try parseType()
            try take(",")
            try take("0x")
            let value = take(while: { $0.isHexDigit })
            return .operator(.floatLiteral(type, value))
        case "function_ref":
            let name = try parseGlobalName()
            try take(":")
            let type = try parseType()
            return .operator(.functionRef(name, type))
        case "global_addr":
            let name = try parseGlobalName()
            try take(":")
            let type = try parseType()
            return .operator(.globalAddr(name, type))
        case "index_addr":
            let addr = try parseOperand()
            try take(",")
            let index = try parseOperand()
            return .operator(.indexAddr(addr, index))
        case "integer_literal":
            let type = try parseType()
            try take(",")
            let value = try parseInt()
            return .operator(.integerLiteral(type, value))
        case "load":
            var ownership: LoadOwnership?
            if skip("[copy]") {
                ownership = .copy
            } else if skip("[take]") {
                ownership = .take
            } else if skip("[trivial]") {
                ownership = .trivial
            }
            let operand = try parseOperand()
            return .operator(.load(ownership, operand))
        case "metatype":
            let type = try parseType()
            return .operator(.metatype(type))
        case "mark_dependence":
            let operand = try parseOperand()
            try take("on")
            let on = try parseOperand()
            return .operator(.markDependence(operand, on))
        case "partial_apply":
            let calleeGuaranteed = skip("[callee_guaranteed]")
            let onStack = skip("[on_stack]")
            let value = try parseValue()
            let substitutions = try parseNilOrMany("<", ",", ">") { try parseNakedType() } ?? []
            let arguments = try parseMany("(", ",", ")") { try parseValue() }
            try take(":")
            let type = try parseType()
            return .operator(.partialApply(calleeGuaranteed, onStack, value, substitutions, arguments, type))
        case "pointer_to_address":
            let operand = try parseOperand()
            try take("to")
            let strict = skip("[strict]")
            let type = try parseType()
            return .operator(.pointerToAddress(operand, strict, type))
        case "return":
            let operand = try parseOperand()
            return .terminator(.return(operand))
        case "release_value":
            let operand = try parseOperand()
            return .operator(.releaseValue(operand))
        case "retain_value":
            let operand = try parseOperand()
            return .operator(.retainValue(operand))
        case "select_enum":
            let operand = try parseOperand()
            let cases = try parseUntilNil { try parseCase(parseValue) }
            try take(":")
            let type = try parseType()
            return .operator(.selectEnum(operand, cases, type))
        case "store":
            let value = try parseValue()
            try take("to")
            var ownership: StoreOwnership?
            if skip("[init]") {
                ownership = .init
            } else if skip("[trivial]") {
                ownership = .trivial
            }
            let operand = try parseOperand()
            return .operator(.store(value, ownership, operand))
        case "string_literal":
            let encoding = try parseEncoding()
            let value = try parseString()
            return .operator(.stringLiteral(encoding, value))
        case "strong_release":
            let operand = try parseOperand()
            return .operator(.strongRelease(operand))
        case "strong_retain":
            let operand = try parseOperand()
            return .operator(.strongRetain(operand))
        case "struct":
            let type = try parseType()
            let operands = try parseMany("(", ",", ")") { try parseOperand() }
            return .operator(.struct(type, operands))
        case "struct_element_addr":
            let operand = try parseOperand()
            try take(",")
            let declRef = try parseDeclRef()
            return .operator(.structElementAddr(operand, declRef))
        case "struct_extract":
            let operand = try parseOperand()
            try take(",")
            let declRef = try parseDeclRef()
            return .operator(.structExtract(operand, declRef))
        case "switch_enum":
            let operand = try parseOperand()
            let cases = try parseUntilNil { try parseCase(parseIdentifier) }
            return .terminator(.switchEnum(operand, cases))
        case "thin_to_thick_function":
            let operand = try parseOperand()
            try take("to")
            let type = try parseType()
            return .operator(.thinToThickFunction(operand, type))
        case "tuple":
            let elements = try parseTupleElements()
            return .operator(.tuple(elements))
        case "tuple_extract":
            let operand = try parseOperand()
            try take(",")
            let declRef = try parseInt()
            return .operator(.tupleExtract(operand, declRef))
        case "unreachable":
            return .terminator(.unreachable)
        case "witness_method":
            let archeType = try parseType()
            try take(",")
            let declRef = try parseDeclRef()
            try take(":")
            let declType = try parseNakedType()
            try take(":")
            let type = try parseType()
            return .operator(.witnessMethod(archeType, declRef, declType, type))
        default:
            // TODO(#8): Actually parse this instruction.
            let _ = skip(while: { $0 != "\n" })
            return .operator(.unknown(instructionName))
        }
    }