Пример #1
0
void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
    Timer _t("for compileModule()");

    ScopingAnalysis* scoping = runScopingAnalysis(m);

    SourceInfo* si = new SourceInfo(bm, scoping);
    si->cfg = computeCFG(AST_TYPE::Module, m->body);
    si->ast = m;
    si->liveness = computeLivenessInfo(si->cfg);
    si->phis = computeRequiredPhis(NULL, si->cfg, si->liveness, si->scoping->getScopeInfoForNode(si->ast));

    CLFunction* cl_f = new CLFunction(si);

    EffortLevel::EffortLevel effort = initialEffort();

    CompiledFunction* cf
        = compileFunction(cl_f, new FunctionSignature(VOID, &si->getArgNames(), 0, false, false), effort, NULL);
    assert(cf->clfunc->versions.size());

    _t.end();

    if (cf->is_interpreted)
        interpretFunction(cf->func, 0, NULL, NULL, NULL, NULL);
    else
        ((void (*)())cf->code)();
}
Пример #2
0
TEST_F(AnalysisTest, augassign) {
    const std::string fn("test/unittests/analysis_listcomp.py");
    AST_Module* module = caching_parse_file(fn.c_str());
    assert(module);

    ScopingAnalysis *scoping = new ScopingAnalysis(module, true);

    assert(module->body[0]->type == AST_TYPE::FunctionDef);
    AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]);

    ScopeInfo* scope_info = scoping->getScopeInfoForNode(func);
    ASSERT_FALSE(scope_info->getScopeTypeOfName(module->interned_strings->get("a")) == ScopeInfo::VarScopeType::GLOBAL);
    ASSERT_FALSE(scope_info->getScopeTypeOfName(module->interned_strings->get("b")) == ScopeInfo::VarScopeType::GLOBAL);

    FutureFlags future_flags = getFutureFlags(module->body, fn.c_str());

    SourceInfo* si = new SourceInfo(createModule("augassign", fn.c_str()), scoping, future_flags, func, func->body, fn);

    CFG* cfg = computeCFG(si, func->body);
    std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg);

    //cfg->print();

    for (CFGBlock* block : cfg->blocks) {
        //printf("%d\n", block->idx);
        if (block->body.back()->type != AST_TYPE::Return)
            ASSERT_TRUE(liveness->isLiveAtEnd(module->interned_strings->get("a"), block));
    }

    std::unique_ptr<PhiAnalysis> phis = computeRequiredPhis(ParamNames(func, si->getInternedStrings()), cfg, liveness.get(), scope_info);
}
Пример #3
0
HRESULT Variable9::SpecializedCasts( Value* pCached, const Value& value )
{
    HRESULT hr = S_OK;

    SASVARIABLE_TYPE type = Desc().Type;
    switch( type )
    {
        case SASVT_TEXTURE:
        case SASVT_TEXTURE1D:
        case SASVT_TEXTURE2D:
        case SASVT_TEXTURE3D:
        case SASVT_TEXTURECUBE:
        {
            if( value.Type() == SASVT_STRING )
            {
                IUnknown* pTexture = NULL;
                String* strValue = (String*) ((Object&)value).Get();
                const WCHAR* str = strValue->Get();

                if(str != NULL && str[0] != L'\0' )
                {
                    SourceInfo si;
                    if(! Sas::Host::GetIntegrator()->FindFile( str , m_Effect->GetCreation()->GetDirectoryPath(), si) )
                        return E_FAIL;

                    hr = m_Effect->LoadTexture(si.GetFilePath(), (IUnknown**)&pTexture);	
                    if( FAILED(hr) )
                    {
                        Sas::Host::Out( Sas::LEVEL_WARNING, L"Unable to cast string into texture: %s", si.GetFilePath() );
                        SAFE_RELEASE(pTexture);
                        return hr;
                    }
                }

                switch(Desc().Type)
                {
                    case SASVT_TEXTURE:
                        ((Object*)pCached)->Set( Texture(pTexture) );
                        break;
                    case SASVT_TEXTURE1D:
                        ((Object*)pCached)->Set( Texture1D(pTexture) );
                        break;
                    case SASVT_TEXTURE2D:
                        ((Object*)pCached)->Set( Texture2D(pTexture) );
                        break;
                    case SASVT_TEXTURE3D:
                        ((Object*)pCached)->Set( Texture3D(pTexture) );
                        break;
                    case SASVT_TEXTURECUBE:
                        ((Object*)pCached)->Set( TextureCube(pTexture) );
                        break;
                }
                SAFE_RELEASE(pTexture);
                return S_OK;
            }
        }
    }

    return E_NOTIMPL;//we don't support that cast;
}
Пример #4
0
void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
    CompiledFunction* cf;

    { // scope for limiting the locked region:
        LOCK_REGION(codegen_rwlock.asWrite());

        Timer _t("for compileModule()");

        bm->future_flags = getFutureFlags(m, bm->fn.c_str());

        ScopingAnalysis* scoping = runScopingAnalysis(m);

        SourceInfo* si = new SourceInfo(bm, scoping, m, m->body);
        si->cfg = computeCFG(si, m->body);
        si->liveness = computeLivenessInfo(si->cfg);
        si->phis = computeRequiredPhis(si->arg_names, si->cfg, si->liveness, si->getScopeInfo());

        CLFunction* cl_f = new CLFunction(0, 0, false, false, si);

        EffortLevel::EffortLevel effort = initialEffort();

        cf = compileFunction(cl_f, new FunctionSpecialization(VOID), effort, NULL);
        assert(cf->clfunc->versions.size());
    }

    if (cf->is_interpreted)
        interpretFunction(cf->func, 0, NULL, NULL, NULL, NULL, NULL, NULL);
    else
        ((void (*)())cf->code)();
}
Пример #5
0
extern "C" void caughtCapiException(AST_stmt* stmt, void* _source_info) {
    SourceInfo* source = static_cast<SourceInfo*>(_source_info);
    PyThreadState* tstate = PyThreadState_GET();

    exceptionAtLine(LineInfo(stmt->lineno, stmt->col_offset, source->getFn(), source->getName()),
                    &tstate->curexc_traceback);
}
Пример #6
0
	void DebugCLI::bt()
	{
		//core->stackTrace->dump(core->console);
		//core->console << '\n';

		// obtain information about each frame 
		int frameCount = core->debugger()->frameCount();
		for(int k=0; k<frameCount; k++)
		{
			Atom* ptr;
			int count, line; 
			SourceInfo* src;
			DebugFrame* frame = core->debugger()->frameAt(k);

			// source information
			frame->sourceLocation(src, line);

			core->console << "#" << k << "   ";

			// this 
			Atom a = nullObjectAtom;
			frame->dhis(a);
			core->console << core->format(a) << ".";

			// method
			MethodInfo* info = functionFor(src, line);
			if (info)
				core->console << info->getMethodName();
			else
				core->console << "<unknown>";

			core->console << "(";

			// dump args
			frame->arguments(ptr, count);
			for(int i=0; i<count; i++)
			{
				// write out the name
                Stringp nm = info->getArgName(i);
				if (info && (nm != core->kundefined))
					core->console << nm << "=";

				core->console << core->format(*ptr++);
				if (i<count-1)
					core->console << ",";
			}
			core->console << ") at ";
			if (src)
				core->console << src->name();
			else
				core->console << "???";

			core->console << ":" << (line) << "\n";
		}
	}
Пример #7
0
int OpenSLPlayer::createSource()
{
    map<int, ContextInfo>::iterator itr = contextInfos.find(contextIndex);
    if( itr == contextInfos.end() )
    {
        g2cerror(
            "Attempt to create source from context that doesn't exist."
            " index=%d\n", contextIndex);
        exit(0);
    }

    ContextInfo& contextInfo(itr->second);

    SourceInfo* sourceInfo = new SourceInfo;

    SLresult result;

    // configure audio source
    SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
    SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_44_1,
        SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
        SL_SPEAKER_FRONT_CENTER, SL_BYTEORDER_LITTLEENDIAN};
    SLDataSource audioSrc = {&loc_bufq, &format_pcm};

    // configure audio sink
    SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, contextInfo.outputMixObject};
    SLDataSink audioSnk = {&loc_outmix, NULL};

    // create audio player
    const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, SL_IID_EFFECTSEND, SL_IID_VOLUME};
    const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};

    result = (*contextInfo.engine)->CreateAudioPlayer(
        contextInfo.engine, &(sourceInfo->bqPlayerObject),
        &audioSrc, &audioSnk, 3, ids, req);

    if( SL_RESULT_SUCCESS != result )
    {
        g2cerror("OpenSL Failed to initialize OpenSL audio player.\n");
        exit(0);
    }

    int index = 1;
    while( sourceInfos.find(index) != sourceInfos.end() )
        index++;

    sourceInfos[index] = sourceInfo;
    sourceInfo->realize();

    return index;
}
Пример #8
0
void doOsrTest(bool is_osr, bool i_maybe_undefined) {
    const std::string fn("test/unittests/analysis_osr.py");
    AST_Module* module = caching_parse_file(fn.c_str());
    assert(module);

    ScopingAnalysis *scoping = new ScopingAnalysis(module, true);

    assert(module->body[0]->type == AST_TYPE::FunctionDef);
    AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]);

    FutureFlags future_flags = getFutureFlags(module->body, fn.c_str());

    ScopeInfo* scope_info = scoping->getScopeInfoForNode(func);
    SourceInfo* si = new SourceInfo(createModule("osr" + std::to_string((is_osr << 1) + i_maybe_undefined), fn.c_str()),
            scoping, future_flags, func, func->body, fn);

    CFG* cfg = computeCFG(si, func->body);
    std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg);

    // cfg->print();

    InternedString i_str = module->interned_strings->get("i");
    InternedString idi_str = module->interned_strings->get("!is_defined_i");
    InternedString iter_str = module->interned_strings->get("#iter_3");

    CFGBlock* loop_backedge = cfg->blocks[5];
    ASSERT_EQ(6, loop_backedge->idx);
    ASSERT_EQ(1, loop_backedge->body.size());

    ASSERT_EQ(AST_TYPE::Jump, loop_backedge->body[0]->type);
    AST_Jump* backedge = ast_cast<AST_Jump>(loop_backedge->body[0]);
    ASSERT_LE(backedge->target->idx, loop_backedge->idx);

    std::unique_ptr<PhiAnalysis> phis;

    if (is_osr) {
        OSREntryDescriptor* entry_descriptor = OSREntryDescriptor::create(NULL, backedge);
        entry_descriptor->args[i_str] = NULL;
        if (i_maybe_undefined)
            entry_descriptor->args[idi_str] = NULL;
        entry_descriptor->args[iter_str] = NULL;
        phis = computeRequiredPhis(entry_descriptor, liveness.get(), scope_info);
    } else {
        phis = computeRequiredPhis(ParamNames(func, si->getInternedStrings()), cfg, liveness.get(), scope_info);
    }

    // First, verify that we require phi nodes for the block we enter into.
    // This is somewhat tricky since the osr entry represents an extra entry
    // into the BB which the analysis might not otherwise track.

    auto required_phis = phis->getAllRequiredFor(backedge->target);
    EXPECT_EQ(1, required_phis.count(i_str));
    EXPECT_EQ(0, required_phis.count(idi_str));
    EXPECT_EQ(1, required_phis.count(iter_str));
    EXPECT_EQ(2, required_phis.size());

    EXPECT_EQ(!is_osr || i_maybe_undefined, phis->isPotentiallyUndefinedAt(i_str, backedge->target));
    EXPECT_FALSE(phis->isPotentiallyUndefinedAt(iter_str, backedge->target));
    EXPECT_EQ(!is_osr || i_maybe_undefined, phis->isPotentiallyUndefinedAfter(i_str, loop_backedge));
    EXPECT_FALSE(phis->isPotentiallyUndefinedAfter(iter_str, loop_backedge));

    // Now, let's verify that we don't need a phi after the loop

    CFGBlock* if_join = cfg->blocks[7];
    ASSERT_EQ(8, if_join->idx);
    ASSERT_EQ(2, if_join->predecessors.size());

    if (is_osr)
        EXPECT_EQ(0, phis->getAllRequiredFor(if_join).size());
    else
        EXPECT_EQ(1, phis->getAllRequiredFor(if_join).size());
}
Пример #9
0
// Compiles a new version of the function with the given signature and adds it to the list;
// should only be called after checking to see if the other versions would work.
CompiledFunction* compileFunction(CLFunction* f, FunctionSignature* sig, EffortLevel::EffortLevel effort,
                                  const OSREntryDescriptor* entry) {
    Timer _t("for compileFunction()");
    assert(sig);

    ASSERT(f->versions.size() < 20, "%ld", f->versions.size());
    SourceInfo* source = f->source;
    assert(source);

    std::string name = source->getName();
    const std::vector<AST_expr*>& arg_names = source->getArgNames();
    AST_arguments* args = source->getArgsAST();

    if (args) {
        // args object can be NULL if this is a module scope
        assert(!args->vararg.size());
        assert(!args->kwarg.size());
        assert(!args->defaults.size());
    }

    if (VERBOSITY("irgen") >= 1) {
        std::string s;
        llvm::raw_string_ostream ss(s);

        ss << "\033[34;1mJIT'ing " << name << " with signature (";
        for (int i = 0; i < sig->arg_types.size(); i++) {
            if (i > 0)
                ss << ", ";
            ss << sig->arg_types[i]->debugName();
            // sig->arg_types[i]->llvmType()->print(ss);
        }
        ss << ") -> ";
        ss << sig->rtn_type->debugName();
        // sig->rtn_type->llvmType()->print(ss);
        ss << " at effort level " << effort;
        if (entry != NULL) {
            ss << "\nDoing OSR-entry partial compile, starting with backedge to block " << entry->backedge->target->idx
               << '\n';
        }
        ss << "\033[0m";
        printf("%s\n", ss.str().c_str());
    }

    // Do the analysis now if we had deferred it earlier:
    if (source->cfg == NULL) {
        assert(source->ast);
        source->cfg = computeCFG(source->ast->type, source->getBody());
        source->liveness = computeLivenessInfo(source->cfg);
        source->phis = computeRequiredPhis(args, source->cfg, source->liveness,
                                           source->scoping->getScopeInfoForNode(source->ast));
    }

    CompiledFunction* cf = doCompile(source, entry, effort, sig, arg_names, name);

    compileIR(cf, effort);
    f->addVersion(cf);
    assert(f->versions.size());

    long us = _t.end();
    static StatCounter us_compiling("us_compiling");
    us_compiling.log(us);
    static StatCounter num_compiles("num_compiles");
    num_compiles.log();

    switch (effort) {
        case EffortLevel::INTERPRETED: {
            static StatCounter us_compiling("us_compiling_0_interpreted");
            us_compiling.log(us);
            static StatCounter num_compiles("num_compiles_0_interpreted");
            num_compiles.log();
            break;
        }
        case EffortLevel::MINIMAL: {
            static StatCounter us_compiling("us_compiling_1_minimal");
            us_compiling.log(us);
            static StatCounter num_compiles("num_compiles_1_minimal");
            num_compiles.log();
            break;
        }
        case EffortLevel::MODERATE: {
            static StatCounter us_compiling("us_compiling_2_moderate");
            us_compiling.log(us);
            static StatCounter num_compiles("num_compiles_2_moderate");
            num_compiles.log();
            break;
        }
        case EffortLevel::MAXIMAL: {
            static StatCounter us_compiling("us_compiling_3_maximal");
            us_compiling.log(us);
            static StatCounter num_compiles("num_compiles_3_maximal");
            num_compiles.log();
            break;
        }
    }

    return cf;
}
Пример #10
0
//--------------------------------------------------------------------------------------
HRESULT Effect9::FromD3DXEffect( ID3DXEffect* pD3DXEffect, const SourceInfo& sf, Effect9** ppEffectOut )
{
    HRESULT hr = S_OK;
    Effect9* pNew = NULL;

    if( NULL == pD3DXEffect || 
        NULL == ppEffectOut )
        return E_INVALIDARG;

    // Clear the output parameter
    *ppEffectOut = NULL;

    // Try to allocate new memory
    pNew = new Effect9();
    if( NULL == pNew )
    {
        hr = E_OUTOFMEMORY;
        goto LFail;
    }

    // Instance members
    pNew->m_pD3DXEffect = pD3DXEffect;
    pNew->m_pD3DXEffect->AddRef();


    pNew->m_Creation = sf;

    D3DXEFFECT_DESC EffectDesc;
    // Gather the parameters
    hr = pD3DXEffect->GetDesc( &EffectDesc );
    if( FAILED(hr) )
        goto LFail;
    
    for( UINT i=0; i < EffectDesc.Parameters; i++ )
    {
        D3DXHANDLE hParameter = pD3DXEffect->GetParameter( NULL, i );
        if( NULL == hParameter )
        {
            pNew->m_Variables.push_back(NULL);
            continue;
        }

        Variable* pParam = new Variable9(pD3DXEffect, hParameter, pNew, NULL, i);
        if( NULL == pParam )
        {
            hr = E_OUTOFMEMORY;
            goto LFail;
        }

        pNew->m_Variables.push_back( pParam );

        // Check for the global parameter
        if( pParam->GetParameter()->IsGlobalParameter() )
        {
            // If this is the second global parameter found, ignore it
            if( NULL != pNew->m_pGlobal )
                Sas::Host::Out( LEVEL_ERROR, L"Multiple global parameters found. Ignoring all but the first occurance" );
            else
                pNew->m_pGlobal = pParam;
        }
    }

    // If no global parameter was found, the effect is by definition
    // not Sas-complaint
    if( NULL == pNew->m_pGlobal )
    {
        Sas::Host::Out( LEVEL_ERROR, L"'%s' - Global parameter not found. Effect is not SAS-compliant.", sf.GetDescription() );
        hr = E_FAIL;
        goto LFail;
    }


LFail:
    if(FAILED(hr))
    {
        SAFE_DELETE( pNew );
    }

    *ppEffectOut = pNew;
    return hr;
}
Пример #11
0
//--------------------------------------------------------------------------------------
HRESULT Effect9::FromSource( IDirect3DDevice9* pDevice, const SourceInfo& sf, const D3DXMACRO* pDefines, ID3DXInclude* pInclude, DWORD flags, Effect9** ppEffectOut )
{
    HRESULT hr;
    hr = S_OK;
    if( NULL == ppEffectOut )
        return E_INVALIDARG;

    // Clear the output parameter
    *ppEffectOut = NULL;

    // Attempt to create the D3DXEffect
    ID3DXEffect* pD3DXEffect = NULL;
    ID3DXBuffer* pErrors = NULL;

    if(sf.GetSourceType() == SOURCEINFO_RESOURCE)
    {
        hr = SASCreateEffectFromResource(
                pDevice,
                sf.GetResourceModule(),
                sf.GetResourceName(),
                sf.GetResourceType(),
                pDefines,
                pInclude,
                flags,
                NULL,
                &pD3DXEffect,
                &pErrors );
    }
    else if(sf.GetSourceType() == SOURCEINFO_FILE)
    {
        hr = D3DXCreateEffectFromFile( 
                pDevice, 
                sf.GetFilePath(), 
                pDefines, 
                pInclude, 
                flags, 
                NULL, 
                &pD3DXEffect, 
                &pErrors );
        if( hr == E_NOTIMPL)
            hr = D3DXCreateEffectFromFile( 
                    pDevice, 
                    sf.GetFilePath(), 
                    pDefines, 
                    pInclude, 
                    (flags | D3DXSHADER_USE_LEGACY_D3DX9_31_DLL), 
                    NULL, 
                    &pD3DXEffect, 
                    &pErrors );
    }

    if( pErrors )
        Sas::Host::OutAnsi( FAILED(hr)?LEVEL_ERROR:LEVEL_WARNING, "%s", (LPSTR)pErrors->GetBufferPointer() );

    if( FAILED(hr) )
        goto e_Exit;

    D3DXHANDLE technique = NULL;
    hr= pD3DXEffect->FindNextValidTechnique(NULL, &technique);
    if( FAILED(hr) )
    {
        Sas::Host::Out( LEVEL_ERROR, L"No technique in the effect is valid on your hardware." );
        goto e_Exit;
    }
    
    pD3DXEffect->SetTechnique(technique);

    // Now that we have a D3DXEffect we can create a Sas::Effect
    hr = FromD3DXEffect( pD3DXEffect, sf, ppEffectOut );

e_Exit:
    SAFE_RELEASE(pErrors);
    SAFE_RELEASE( pD3DXEffect );

    if(SUCCEEDED(hr))
        Sas::Host::Out( LEVEL_STATUS, L"Loading effect '%s'", sf.GetDescription() );
    else
        Sas::Host::Out( LEVEL_ERROR, L"Could not load effect '%s'", sf.GetDescription() );

    return hr;
}
Пример #12
0
//--------------------------------------------------------------------------------------
HRESULT Effect10::FromSource( ID3D10Device* pDevice, const SourceInfo& sf, const D3D10_SHADER_MACRO* pDefines, ID3D10Include* pInclude, DWORD HlslFlags, DWORD FxFlags, Effect10** ppEffectOut )
{
    HRESULT hr;

    if( NULL == ppEffectOut )
        return E_INVALIDARG;

    // Clear the output parameter
    *ppEffectOut = NULL;

    // Attempt to create the D3DXEffect
    ID3D10Effect* pD3DEffect = NULL;
    ID3D10Blob* pErrors = NULL;


    if(sf.GetSourceType() == SOURCEINFO_RESOURCE)
    {
        hr = D3DX10CreateEffectFromResource( 
                sf.GetResourceModule(), 
                sf.GetResourceName(), 
                sf.GetResourceName(), 
                pDefines, 
                pInclude,
                "fx_4_0",
                HlslFlags, 
                FxFlags,
                pDevice,
                NULL,
                NULL,
                &pD3DEffect,
                &pErrors,
                NULL );
    }
    else if(sf.GetSourceType() == SOURCEINFO_FILE)
    {

        hr = D3DX10CreateEffectFromFile( 
                sf.GetFilePath(), 
                pDefines, 
                pInclude,
                "fx_4_0",
                HlslFlags, 
                FxFlags, 
                pDevice, 
                NULL, 
                NULL, 
                &pD3DEffect, 
                &pErrors,
                NULL );
    }

    if( pErrors )
        Sas::Host::OutAnsi( FAILED(hr)?LEVEL_ERROR:LEVEL_WARNING, "%s",(LPSTR)pErrors->GetBufferPointer() );

    if( FAILED(hr) )
        goto e_Exit;

    D3D10_EFFECT_DESC desc;
    pD3DEffect->GetDesc(&desc);
    if(desc.Techniques <= 0)
    {
        Sas::Host::Out( LEVEL_ERROR, L"Effect does not have a Technique10." );
        hr = E_FAIL;
        goto e_Exit;
    }


    // Now that we have a D3DXEffect we can create a Sas::Effect
    hr = FromD3DEffect( pD3DEffect, sf, ppEffectOut );

e_Exit:
    SAFE_RELEASE(pErrors);
    SAFE_RELEASE( pD3DEffect );

    if(SUCCEEDED(hr))
        Sas::Host::Out( LEVEL_STATUS, L"Loading effect '%s'", sf.GetDescription() );
    else
        Sas::Host::Out( LEVEL_ERROR, L"Could not load effect '%s'", sf.GetDescription() );

    return hr;
}
Пример #13
0
    size_t
    DisplayFunctionSource (const SymbolContext &sc,
                           SourceInfo &source_info,
                           CommandReturnObject &result)
    {
        if (!source_info.IsValid())
        {
            source_info.function = sc.GetFunctionName();
            source_info.line_entry = sc.GetFunctionStartLineEntry();
        }
    
        if (sc.function)
        {
            Target *target = m_exe_ctx.GetTargetPtr();

            FileSpec start_file;
            uint32_t start_line;
            uint32_t end_line;
            FileSpec end_file;
            
            if (sc.block == NULL)
            {
                // Not an inlined function
                sc.function->GetStartLineSourceInfo (start_file, start_line);
                if (start_line == 0)
                {
                    result.AppendErrorWithFormat("Could not find line information for start of function: \"%s\".\n", source_info.function.GetCString());
                    result.SetStatus (eReturnStatusFailed);
                    return 0;
                }
                sc.function->GetEndLineSourceInfo (end_file, end_line);
            }
            else
            {
                // We have an inlined function
                start_file = source_info.line_entry.file;
                start_line = source_info.line_entry.line;
                end_line = start_line + m_options.num_lines;
            }

            // This is a little hacky, but the first line table entry for a function points to the "{" that
            // starts the function block.  It would be nice to actually get the function
            // declaration in there too.  So back up a bit, but not further than what you're going to display.
            uint32_t extra_lines;
            if (m_options.num_lines >= 10)
                extra_lines = 5;
            else
                extra_lines = m_options.num_lines/2;
            uint32_t line_no;
            if (start_line <= extra_lines)
                line_no = 1;
            else
                line_no = start_line - extra_lines;
            
            // For fun, if the function is shorter than the number of lines we're supposed to display,
            // only display the function...
            if (end_line != 0)
            {
                if (m_options.num_lines > end_line - line_no)
                    m_options.num_lines = end_line - line_no + extra_lines;
            }
            
            m_breakpoint_locations.Clear();

            if (m_options.show_bp_locs)
            {
                const bool show_inlines = true;
                m_breakpoint_locations.Reset (start_file, 0, show_inlines);
                SearchFilter target_search_filter (m_exe_ctx.GetTargetSP());
                target_search_filter.Search (m_breakpoint_locations);
            }
            
            result.AppendMessageWithFormat("File: %s\n", start_file.GetPath().c_str());
            return target->GetSourceManager().DisplaySourceLinesWithLineNumbers (start_file,
                                                                                 line_no,
                                                                                 0,
                                                                                 m_options.num_lines,
                                                                                 "",
                                                                                 &result.GetOutputStream(),
                                                                                 GetBreakpointLocations ());
        }
        else
        {
            result.AppendErrorWithFormat("Could not find function info for: \"%s\".\n", m_options.symbol_name.c_str());
        }
        return 0;
    }